Merge branch 'master' into feature-25999/C4

This commit is contained in:
Harald Bamberger
2024-10-15 10:44:56 +02:00
34 changed files with 2407 additions and 346 deletions
+15
View File
@@ -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'),
@@ -0,0 +1,65 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Lehrveranstaltung extends FHCAPI_Controller
{
/**
* Lehrveranstaltung API constructor.
*/
public function __construct()
{
parent::__construct(array(
'getTemplateLvTree' => array(
'lehre/lehrveranstaltung:rw'
)
));
// Load model LehrveranstaltungModel
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
}
/**
* Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes of given Berechtigung,
* that are assigned to a template. This data structure can be used for nested tabulators' data tree.
*
* @param null|string $studiensemester_kurzbz
* @param null|string $berechtigung
* @return array|stdClass|null
*/
public function getTemplateLvTree()
{
$studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz');
$berechtigung = $this->input->get('berechtigung');
if ($berechtigung)
{
$oe_permissions = $this->permissionlib->getOE_isEntitledFor($berechtigung);
if(!$oe_permissions) $oe_permissions = [];
$result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz, $oe_permissions);
}
else
{
$result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz);
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
}
@@ -0,0 +1,118 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Studiensemester extends FHCAPI_Controller
{
/**
* Studiensemester API constructor.
*/
public function __construct()
{
parent::__construct(
array(
'getAll' => 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) ?: ''));
}
}
+21 -5
View File
@@ -5,8 +5,12 @@ if (! defined("BASEPATH")) exit("No direct script access allowed");
class UHSTAT1 extends FHC_Controller
{
const BERECHTIGUNG_UHSTAT_VERWALTEN = 'student/uhstat1daten_verwalten';
const LOGIN_SESSION_INDEX = 'bewerbung/user';
const PERSON_ID_SESSION_INDEX = 'bewerbung/personId';
const CODEX_OESTERREICH = 'A';
const CODEX_UNKNOWN_YEAR = 9999;
const CODEX_UNKNOWN_NATION = 'XXX';
const CODEX_UNKNOWN_BILDUNGMAX = 999;
const LOWER_BOUNDARY_YEARS = 160;
const UPPER_BOUNDARY_YEARS = 20;
@@ -210,7 +214,9 @@ class UHSTAT1 extends FHC_Controller
else
return true;
if (!isset($bildungsstaat)) return true;
// if no Bildungsstaat or Bildungmax unknown - valid
if (!isset($bildungsstaat) || $bildungmax == self::CODEX_UNKNOWN_BILDUNGMAX) return true;
// find out if abschluss is in Austria
$this->AbschlussModel->addSelect("in_oesterreich");
@@ -219,8 +225,11 @@ class UHSTAT1 extends FHC_Controller
if (hasData($abschlussRes))
{
$in_oesterreich = getData($abschlussRes)[0]->in_oesterreich;
// invalid if abschluss in Austria, but not Bildungsstaat, or abschluss not in Austria, but Bildungsstaat in Austria
return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH) || (!$in_oesterreich && $bildungsstaat != self::CODEX_OESTERREICH);
// valid if Bildungsstaat and Abschluss in Austria, or Bildungsstaat and Abschluss not in Austria
// (or Abschluss not in Austria and Bildungsstaat unknown)
return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH)
|| (!$in_oesterreich && ($bildungsstaat != self::CODEX_OESTERREICH || $bildungsstaat == self::CODEX_UNKNOWN_NATION));
}
return false;
@@ -363,7 +372,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'][self::CODEX_UNKNOWN_YEAR] = 'unbekannt';
return success($formMetaData);
}
@@ -411,7 +424,10 @@ class UHSTAT1 extends FHC_Controller
private function _getValidPersonId($berechtigungsArt)
{
// if coming from bewerbungstool - person id is in session (person must be logged in bewerbungstool)
if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX]) && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX]))
if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX])
&& is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX])
&& isset($_SESSION[self::LOGIN_SESSION_INDEX])
)
return $_SESSION[self::PERSON_ID_SESSION_INDEX];
// if person id passed directly...
@@ -9,8 +9,8 @@ class IssueResolver extends IssueResolver_Controller
{
parent::__construct();
// set fehler codes which can be resolved by the job
// structure: fehlercode => class (library) name for resolving
// set fehler codes which can be resolved by the job, with own resolver defined
// 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',
@@ -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 by the job the same way as they are produced
// structure: fehlercode => class (library) name for resolving in "plausichecks" folder
$this->_codeProducerLibMappings = array(
'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv',
);
}
}
@@ -51,7 +51,7 @@ class OneTimeMessages extends JOB_Controller
FROM public.tbl_prestudent p
JOIN public.tbl_prestudentstatus ps USING (prestudent_id)
JOIN public.tbl_studiengang s USING (studiengang_kz)
WHERE ps.status_kurzbz = \'Wartender\'
WHERE get_rolle_prestudent(ps.prestudent_id, NULL) = \'Wartender\'
AND ps.studiensemester_kurzbz = ?
AND ps.datum <= NOW() - \''.$days.' days\'::interval
AND s.typ = ?
@@ -0,0 +1,45 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class LvTemplateUebersicht extends Auth_Controller
{
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'lehre/lehrveranstaltung:rw',
)
);
// Load libraries
$this->load->library('AuthLib');
// Load language phrases
$this->loadPhrases(
array(
'global',
'lehre'
)
);
$this->_setAuthUID();
}
public function index()
{
$this->load->view('lehre/lvplanung/lvTemplateUebersicht.php');
}
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
}
+22 -93
View File
@@ -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';
// mappings in form fehlercode -> resolverlibrary name, fehler which have explicit resolver class defined
protected $_codeLibMappings = [];
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
$this->load->model('system/Issue_model', 'IssueModel');
$this->load->library('IssuesLib');
}
/**
@@ -27,97 +24,29 @@ 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))
);
// 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($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");
}
@@ -5,61 +5,23 @@
*/
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));
$this->load->library('IssuesLib');
}
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");
// 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($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");
}
-6
View File
@@ -1463,12 +1463,6 @@ class AntragLib
elseif($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus)
return success(-2);
}
if ($antrag->typ == Studierendenantrag_model::TYP_UNTERBRECHUNG)
{
// NOTE(chris): Ignore canceled ones
if ($antrag->status == Studierendenantragstatus_model::STATUS_CANCELLED)
continue;
}
if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG)
{
if($antrag->status == Studierendenantragstatus_model::STATUS_PASS)
+21 -15
View File
@@ -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(
@@ -12,18 +12,25 @@ 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;
$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 +48,52 @@ class PlausicheckProducerLib
}
}
/**
* 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($params)
{
$result = new StdClass();
$result->errors = [];
$result->infos = [];
foreach ($this->_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
@@ -66,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);
@@ -0,0 +1,136 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class PlausicheckResolverLib
{
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';
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', ['extensionName' => $this->_extensionName, 'isForResolutionCheck' => true]);
}
/**
* 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($openIssues)
{
$result = new StdClass();
$result->errors = [];
$result->infos = [];
foreach ($openIssues as $issue)
{
// 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()
);
$issueResolved = false;
// ignore if Fehlercode is not in libmappings (shouldn't be checked)
if (isset($this->_codeLibMappings[$issue->fehlercode]))
{
$libName = $this->_codeLibMappings[$issue->fehlercode];
// 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);
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";
}
}
return $result;
}
}
@@ -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'];
}
@@ -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; // 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]
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);
}
}
@@ -15,6 +15,297 @@ class Lehrveranstaltung_model extends DB_Model
$this->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
}
/**
* Get Lehrveranstaltungen by eventQuery string. Use with autocomplete event queries.
* @param $eventQuery String
* @param string $studiensemester_kurzbz Filter by Studiensemester
* @param array $oes Filter by Organisationseinheiten
* @return array
*/
public function getAutocompleteSuggestions($eventQuery, $studiensemester_kurzbz = null, $oes = null)
{
$subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes);
$params = [];
/* filter by input string */
if (is_string($eventQuery)) {
$subQry.= ' AND lv.bezeichnung ILIKE ?';
$params[] = '%' . $eventQuery . '%';
}
$qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp';
return $this->execQuery($qry, $params);
}
/**
* Get Lehrveranstaltungen with its Stg, OE and OE-type.
* Filter by Studiensemester and Organisationseinheiten if necessary.
* @param $eventQuery String
* @param string $studiensemester_kurzbz Filter by Studiensemester
* @param array $oes Filter by Organisationseinheiten
* @param array $lv_ids Filter by Lehrveranstaltung-Ids
* @return array
*/
public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lv_ids = null)
{
$subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes);
$qry = 'SELECT * FROM ('. $subQry. ') AS tmp';
if (isset($lv_ids) && is_array($lv_ids))
{
/* filter by lv_ids */
$implodedLvIds = "'". implode("', '", $lv_ids). "'";
$qry.= ' WHERE lehrveranstaltung_id IN ('. $implodedLvIds. ')';
}
$qry.= ' ORDER BY stg_typ_kurzbz, orgform_kurzbz DESC';
return $this->execQuery($qry);
}
/**
* Get basic query to retrieve Lehrveranstaltungen according to the Orgforms and Ausbildungssemesters actual Studienplan.
*
* @return string
*/
private function _getQryLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lehrtyp_kurzbz = 'lv')
{
$qry = '
SELECT
lv.oe_kurzbz AS lv_oe_kurzbz,
CASE
WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung)
WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung)
ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
END AS lv_oe_bezeichnung,
stplsem.studiensemester_kurzbz,
studienordnung_id,
sto.studiengang_kz,
stpl.studienplan_id,
stplsem.semester,
stpl.orgform_kurzbz,
upper(stg.typ || stg.kurzbz) AS stg_typ_kurzbz,
stg.bezeichnung AS stg_bezeichnung,
stgtyp.bezeichnung AS stg_typ_bezeichnung,
lv.lehrveranstaltung_id,
lv.semester,
lv.bezeichnung AS lv_bezeichnung,
(
-- comma seperated string of all lehreinheitgruppen
SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung
FROM(
-- distinct bezeichnung, as may come multiple times from different lehreinheiten
SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM
(
-- distinct lehreinheitgruppe, as may come multiple times from different lehrform
SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz,
-- get Spezialgruppe or Lehrverbandgruppe
COALESCE(
legr.gruppe_kurzbz,
CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe )
) as bezeichnung
FROM lehre.tbl_lehreinheitgruppe legr
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id)
JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz
WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id
AND le.studiensemester_kurzbz = stplsem.studiensemester_kurzbz
) AS lehreinheitgruppen
GROUP BY studiengang_kz, bezeichnung
ORDER BY studiengang_kz DESC
) AS uniqueLehreinheitgruppen_bezeichnung
) AS lehreinheitgruppen_bezeichnung
FROM
lehre.tbl_studienplan stpl
JOIN lehre.tbl_studienordnung sto USING (studienordnung_id)
JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id)
JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester)
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
/* filter by lehrtyp_kurzbz, default is lvs only */
WHERE
lehrtyp_kurzbz = '. $this->db->escape($lehrtyp_kurzbz);
if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz))
{
/* filter by studiensemester */
$qry.= ' AND stplsem.studiensemester_kurzbz = '. $this->db->escape($studiensemester_kurzbz);
}
if (isset($oes) && is_array($oes))
{
/* filter by organisationseinheit */
$implodedOes = "'". implode("', '", $oes). "'";
$qry.= ' AND lv.oe_kurzbz IN ('. $implodedOes. ')';
}
return $qry;
}
/**
* Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes, that are assigned to
* a template. This data structure can be used for nested tabulator data tree.
*
* @param null|string $studiensemester_kurzbz
* @param null|array $oes
* @return array|stdClass|null
*/
public function getTemplateLvTree($studiensemester_kurzbz = null, $oes = null){
$params = [];
$qry = '
WITH
-- All Lvs that are assigned to a template in given Studiensemester for given Oes
-- joining via actual Studienplan
standardisierteLvs AS (
SELECT
lv.*,
stpl.studienplan_id::text as studienplan_id,
stpl.bezeichnung AS studienplan_bezeichnung,
stplsem.studiensemester_kurzbz
FROM
lehre.tbl_studienplan stpl
JOIN lehre.tbl_studienordnung sto USING (studienordnung_id)
JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id)
JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester)
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
WHERE
-- filter type lv
lehrtyp_kurzbz = \'lv\'
-- filter lvs assigned to template (= standardisierte lv)
AND lehrveranstaltung_template_id IS NOT NULL';
if (is_string($studiensemester_kurzbz))
{
/* filter by studiensemester */
$params[]= $studiensemester_kurzbz;
$qry.= ' AND stplsem.studiensemester_kurzbz = ? ';
}
if (is_array($oes))
{
/* filter by organisationseinheit */
$params[]= $oes;
$qry.= ' AND lv.oe_kurzbz IN ? ';
}
$qry.= '
),
-- All templates
templateLvs AS (
SELECT
lv.*,
NULL AS studienplan_id,
(
SELECT string_agg(stpl_bezeichnung, \', \')
FROM
(
SELECT stlv.studienplan_bezeichnung AS stpl_bezeichnung
FROM standardisierteLvs stlv
WHERE stlv.lehrveranstaltung_template_id = lv.lehrveranstaltung_id
) AS studienplaene
) AS studienplan_bezeichnung,
NULL AS studiensemester_kurzbz
FROM
lehre.tbl_lehrveranstaltung lv
WHERE
-- filter type template
lehrtyp_kurzbz = \'tpl\'
-- filter semester that were retrieved by standardisierte lvs semester for selected studiensemester
AND EXISTS (
SELECT 1
FROM standardisierteLvs std
WHERE std.lehrveranstaltung_template_id = lv.lehrveranstaltung_id
)';
if (is_array($oes))
{
/* filter by organisationseinheit */
$params[]= $oes;
$qry.= ' AND lv.oe_kurzbz IN ? ';
}
$qry.= '
)
';
$qry.= '
SELECT
lv.lehrveranstaltung_id,
lv.kurzbz,
lv.lehrtyp_kurzbz,
lv.bezeichnung AS lv_bezeichnung,
lv.bezeichnung_english,
lv.studiengang_kz,
lv.semester,
lv.oe_kurzbz,
lv.ects,
lv.lehrform_kurzbz,
lv.orgform_kurzbz,
lv.sprache,
lv.aktiv,
lv.lehrveranstaltung_template_id,
lv.studienplan_id,
lv.studienplan_bezeichnung,
lv.studiensemester_kurzbz,
upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
stg.bezeichnung AS "stg_bezeichnung",
stgtyp.bezeichnung AS "stg_typ_bezeichnung",
CASE
WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung)
WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung)
ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
END AS "lv_oe_bezeichnung",
(
-- comma seperated string of all lehreinheitgruppen
SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung
FROM(
-- distinct bezeichnung, as may come multiple times from different lehreinheiten
SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM
(
-- distinct lehreinheitgruppe, as may come multiple times from different lehrform
SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz,
-- get Spezialgruppe or Lehrverbandgruppe
COALESCE(
legr.gruppe_kurzbz,
CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe )
) as bezeichnung
FROM lehre.tbl_lehreinheitgruppe legr
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id)
JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz
WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id
AND le.studiensemester_kurzbz = lv.studiensemester_kurzbz
) AS lehreinheitgruppen
GROUP BY studiengang_kz, bezeichnung
ORDER BY studiengang_kz DESC
) AS uniqueLehreinheitgruppen_bezeichnung
) AS lehreinheitgruppen_bezeichnung
FROM (
SELECT
*
FROM
standardisierteLvs
UNION
SELECT
*
FROM templateLvs
) AS lv
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz
JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = lv.oe_kurzbz
ORDER BY
oe.bezeichnung, lv.semester, lv.bezeichnung
';
return $this->execQuery($qry, $params);
}
/**
* Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345
* @param string $studiensemester_kurzbz
@@ -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;
}
}
@@ -25,7 +25,7 @@ class Paabgabe_model extends DB_Model
WHERE projektarbeit_id = ?
AND paabgabetyp_kurzbz = 'end'
AND paabg.abgabedatum IS NOT NULL
ORDER BY paabg.abgabedatum, paabg.datum DESC
ORDER BY paabg.abgabedatum DESC, paabg.datum DESC
LIMIT 1";
return $this->execQuery($qry, array($projektarbeit_id));
@@ -96,7 +96,8 @@ class Studierendenantrag_model extends DB_Model
Studierendenantragstatus_model::STATUS_REJECTED,
Studierendenantragstatus_model::STATUS_OBJECTION_DENIED,
Studierendenantragstatus_model::STATUS_DEREGISTERED,
Studierendenantragstatus_model::STATUS_PAUSE
Studierendenantragstatus_model::STATUS_PAUSE,
Studierendenantragstatus_model::STATUS_REMINDERSENT
]);
$this->db->or_group_start();
$this->db->where('s.studierendenantrag_statustyp_kurzbz', Studierendenantragstatus_model::STATUS_APPROVED);
@@ -410,7 +411,7 @@ class Studierendenantrag_model extends DB_Model
FROM campus.tbl_studierendenantrag
LEFT JOIN public.tbl_studiensemester USING(studiensemester_kurzbz)
WHERE typ=?
AND campus.get_status_studierendenantrag(studierendenantrag_id) != ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
AND prestudent_id=?
) a ON (s.start < a.ende AND s.ende > a.start)
WHERE s.start >= (" . $subquery . ")
@@ -420,7 +421,10 @@ class Studierendenantrag_model extends DB_Model
return $this->execQuery($sql, [
$max_length,
self::TYP_UNTERBRECHUNG,
Studierendenantragstatus_model::STATUS_CANCELLED,
array(
Studierendenantragstatus_model::STATUS_CANCELLED,
Studierendenantragstatus_model::STATUS_REJECTED
),
$prestudent_id,
$studiensemester ?: $prestudent_id,
$max_length * $max_starters
@@ -32,11 +32,20 @@ class Geschaeftsjahr_model extends DB_Model
* Gets next Geschaeftsjahr, as determined by its start date
* @return array|null
*/
public function getNextGeschaeftsjahr()
public function getNextGeschaeftsjahr($offsetDays=null)
{
$query = 'SELECT *
FROM public.tbl_geschaeftsjahr
WHERE start > now()
FROM public.tbl_geschaeftsjahr WHERE ';
if(!is_null($offsetDays))
{
$query .= "start > now() - '".$offsetDays." days'::interval";
}
else
{
$query .= 'start > now()';
}
$query .= '
ORDER BY start
LIMIT 1';
@@ -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);
}
}
+30 -7
View File
@@ -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))
{
@@ -59,7 +69,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 +95,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);
}
}
@@ -327,7 +327,7 @@ class Recipient_model extends DB_Model
pr.nachname,
ms.person_id,
mrou.token
ORDER BY sent DESC';
ORDER BY sent DESC LIMIT 1500';
return $this->execQuery($sql, array($person_id, $functions, $person_id));
}
@@ -0,0 +1,28 @@
<?php
class GehaltsTyp_model extends DB_Model
{
public function __construct()
{
parent::__construct();
$this->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;
}
}
+102 -60
View File
@@ -74,16 +74,23 @@ $saved = isset($saved) && $saved === true;
<div class="form-group">
<label for="mutter_geburtsjahr" class="col-sm-3 control-label"><?php echo ucfirst($this->p->t('uhstat', 'geburtsjahr')) ?></label>
<div class="col-sm-9">
<select type="text" name="mutter_geburtsjahr" id="mutter_geburtsjahr" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['jahre'] as $jahr): ?>
<option
value="<?php echo $jahr ?>"
<?php echo $jahr == $mutter_geburtsjahr ? " selected" : "" ?>>
<?php echo $jahr ?>
</option>
<?php endforeach; ?>
</select>
<div class="input-group">
<select type="text" name="mutter_geburtsjahr" id="mutter_geburtsjahr" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['jahre'] as $jahrKey => $jahr): ?>
<option
value="<?php echo $jahrKey ?>"
<?php echo $jahrKey == $mutter_geburtsjahr ? " selected" : "" ?>>
<?php echo $jahr ?>
</option>
<?php endforeach; ?>
</select>
<span class="input-group-btn">
<button type="button" class="btn btn-default" onclick="document.getElementById('mutter_geburtsjahr').value = 9999; return false;" <?php echo $disabled ?>>
<?php echo $this->p->t('uhstat', 'unbekannt') ?>
</button>
</span>
</div>
<?php echo form_error('mutter_geburtsjahr'); ?>
</div>
</div>
@@ -94,16 +101,23 @@ $saved = isset($saved) && $saved === true;
<?php echo '('.ucfirst($this->p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
</label>
<div class="col-sm-9">
<select type="text" name="mutter_geburtsstaat" id="mutter_geburtsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $mutter_geburtsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<div class="input-group">
<select type="text" name="mutter_geburtsstaat" id="mutter_geburtsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $mutter_geburtsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<span class="input-group-btn">
<button type="button" class="btn btn-default" onclick="document.getElementById('mutter_geburtsstaat').value = 'XXX'; return false;" <?php echo $disabled ?>>
<?php echo $this->p->t('uhstat', 'unbekannt') ?>
</button>
</span>
</div>
<?php echo form_error('mutter_geburtsstaat'); ?>
</div>
</div>
@@ -114,16 +128,23 @@ $saved = isset($saved) && $saved === true;
<?php echo '('.ucfirst($this->p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
</label>
<div class="col-sm-9">
<select type="text" name="mutter_bildungsstaat" id="mutter_bildungsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $mutter_bildungsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<div class="input-group">
<select type="text" name="mutter_bildungsstaat" id="mutter_bildungsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $mutter_bildungsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<span class="input-group-btn">
<button type="button" class="btn btn-default" onclick="document.getElementById('mutter_bildungsstaat').value = 'XXX'; return false;" <?php echo $disabled ?>>
<?php echo $this->p->t('uhstat', 'unbekannt') ?>
</button>
</span>
</div>
<?php echo form_error('mutter_bildungsstaat'); ?>
</div>
</div>
@@ -161,16 +182,23 @@ $saved = isset($saved) && $saved === true;
<div class="form-group">
<label for="vater_geburtsjahr" class="col-sm-3 control-label"><?php echo ucfirst($this->p->t('uhstat', 'geburtsjahr')) ?></label>
<div class="col-sm-9">
<select type="text" name="vater_geburtsjahr" id="vater_geburtsjahr" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['jahre'] as $jahr): ?>
<option
value="<?php echo $jahr ?>"
<?php echo $vater_geburtsjahr == $jahr ? " selected" : "" ?>>
<div class="input-group">
<select type="text" name="vater_geburtsjahr" id="vater_geburtsjahr" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['jahre'] as $jahrKey => $jahr): ?>
<option
value="<?php echo $jahrKey ?>"
<?php echo $vater_geburtsjahr == $jahrKey ? " selected" : "" ?>>
<?php echo $jahr ?>
</option>
<?php endforeach; ?>
</select>
<?php endforeach; ?>
</select>
<span class="input-group-btn">
<button type="button" class="btn btn-default" onclick="document.getElementById('vater_geburtsjahr').value = 9999; return false;" <?php echo $disabled ?>>
<?php echo $this->p->t('uhstat', 'unbekannt') ?>
</button>
</span>
</div>
<?php echo form_error('vater_geburtsjahr'); ?>
</div>
</div>
@@ -181,16 +209,23 @@ $saved = isset($saved) && $saved === true;
<?php echo '('.ucfirst($this->p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
</label>
<div class="col-sm-9">
<select type="text" name="vater_geburtsstaat" id="vater_geburtsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $vater_geburtsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<div class="input-group">
<select type="text" name="vater_geburtsstaat" id="vater_geburtsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $vater_geburtsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<span class="input-group-btn">
<button type="button" class="btn btn-default" onclick="document.getElementById('vater_geburtsstaat').value = 'XXX'; return false;" <?php echo $disabled ?>>
<?php echo $this->p->t('uhstat', 'unbekannt') ?>
</button>
</span>
</div>
<?php echo form_error('vater_geburtsstaat'); ?>
</div>
</div>
@@ -201,16 +236,23 @@ $saved = isset($saved) && $saved === true;
<?php echo '('.ucfirst($this->p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
</label>
<div class="col-sm-9">
<select type="text" name="vater_bildungsstaat" id="vater_bildungsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $vater_bildungsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<div class="input-group">
<select type="text" name="vater_bildungsstaat" id="vater_bildungsstaat" class="form-control" <?php echo $disabled ?>>
<option disabled selected value=""><?php echo $this->p->t('uhstat', 'bitteAuswaehlen') ?></option>
<?php foreach ($formMetaData['nation'] as $nation): ?>
<option
value="<?php echo $nation->nation_code ?>"
<?php echo $vater_bildungsstaat == $nation->nation_code ? " selected" : "" ?>>
<?php echo $nation->nation_text ?>
</option>
<?php endforeach; ?>
</select>
<span class="input-group-btn">
<button type="button" class="btn btn-default" onclick="document.getElementById('vater_bildungsstaat').value = 'XXX'; return false;" <?php echo $disabled ?>>
<?php echo $this->p->t('uhstat', 'unbekannt') ?>
</button>
</span>
</div>
<?php echo form_error('vater_bildungsstaat'); ?>
</div>
</div>
@@ -271,7 +313,7 @@ $saved = isset($saved) && $saved === true;
</div>
</form>
<?php endif; ?>
</div>
</div>
</div> <!-- subcontainer -->
</div> <!-- container -->
<?php $this->load->view('templates/FHC-Footer'); ?>
@@ -0,0 +1,29 @@
<?php
$includesArray = array(
'title' => 'LV Template Übersicht',
'vue3' => true,
'axios027' => true,
'bootstrap5' => true,
'tabulator5' => true,
'fontawesome6' => true,
'primevue3' => true,
'navigationcomponent' => true,
'filtercomponent' => true,
'customJSModules' => array('public/js/apps/lehre/lvplanung/LvTemplates.js'),
'customCSSs' => array(
'public/css/Fhc.css',
'public/css/lvTemplateUebersicht.css'
)
);
$this->load->view('templates/FHC-Header', $includesArray);
?>
<div id="main">
<!-- Navigation component -->
<core-navigation-cmpt></core-navigation-cmpt>
<lv-template-uebersicht></lv-template-uebersicht>
</div>
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
+1
View File
@@ -70,6 +70,7 @@ $menu=array
'link'=>'left.php?categorie=Lehre', 'target'=>'nav',
'Gruppenverwaltung'=>array('name'=>'Gruppen', 'permissions'=>array('admin','lv-plan','support','lehre/gruppe'), 'link'=>'stammdaten/lvbgruppenverwaltung.php', 'target'=>'main'),
'Lehrveranstaltung'=>array('name'=>'Lehrveranstaltung', 'link'=>'lehre/lehrveranstaltung_frameset.html', 'target'=>'main'),
'lvTemplateUebersicht'=>array('name'=>'LV-Template Übersicht', 'link'=>'../index.ci.php/lehre/lvplanung/LvTemplateUebersicht', 'target'=>'_blank'),
'Studienordnung'=>array('name'=>'Studienordnung', 'link'=>'lehre/studienordnung.php', 'target'=>'_blank','permissions'=>array('lehre/studienordnung')),
'StudienplanGueltigkeit'=>array('name'=>'Studienplan Gültigkeit', 'link'=>'lehre/studienplan_gueltigkeit.php', 'target'=>'main','permissions'=>array('lehre/studienordnung')),
'StudienplanVorruecken'=>array('name'=>'Studienplan vorrücken', 'link'=>'lehre/studienplan_vorrueckung.php', 'target'=>'main','permissions'=>array('lehre/studienplan')),
+3
View File
@@ -0,0 +1,3 @@
html {
font-size: .75em;
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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')
@@ -0,0 +1,289 @@
import {CoreFilterCmpt} from '../../components/filter/Filter.js';
import CoreFormInput from "../../components/Form/Input.js";
// Fields used to restructure table data for dataTree
const idField = 'lehrveranstaltung_id';
const parentIdField = 'lehrveranstaltung_template_id';
const STUDIENSEMESTER_DROPDOWN_STARTDATE = '2011-01-01';
export default {
components: {
CoreFilterCmpt,
CoreFormInput
},
data: function() {
return {
table: null,
studiensemester: [],
selectedStudiensemester: '',
cbDataTreeStartExpanded: false // checkbox expand dataTree or not
}
},
computed: {
tabulatorOptions() {
const fhcValuesLookup = function(cell) {
var values = {};
const field = cell.getField();
const data = cell.getTable().getData();
const collectvalues = function(rows, field) {
var values = {};
var childvalues = {};
for(const row of rows) {
const rowvalue = (row[field] !== null) ? row[field] : '';
values[rowvalue] = rowvalue;
if(row['_children'] && row['_children'].length > 0) {
childvalues = collectvalues(row['_children'], field);
values = {...values, ...childvalues}
}
}
return values;
}
values = collectvalues(data, field);
const vals = Object.keys(values).sort();
if(vals.indexOf('') === -1) {
vals.unshift('');
}
return vals;
};
const fhctreefilter = function(headerValue, rowValue, rowData, filterParams){
if (rowData['_children'] && rowData['_children'].length > 0) {
for (var i in rowData['_children']) {
return rowValue == headerValue ||
fhctreefilter(
headerValue,
rowData['_children'][i][filterParams.field],
rowData['_children'][i],
filterParams
);
}
}
return rowValue == headerValue;
};
const self = this;
return {
// NOTE: data is set on table built to await preselected actual Studiensemester
ajaxResponse(url, params, response) {
return self.prepDataTreeData(response.data) // Prepare data for dataTree view
},
layout: 'fitColumns',
autoResize: false, // prevent auto resizing of table
resizableColumnFit: true, //maintain the fit of columns when resizing
index: 'lehrveranstaltung_id',
selectable: true,
selectableRangeMode: 'click',
dataTree: true,
dataTreeStartExpanded: self.cbDataTreeStartExpanded,
dataTreeChildIndent: 15, //indent child rows by 15 px
persistence:{
filter: false, //persist filter sorting
},
columns: [
{title: 'LV-ID', field: 'lehrveranstaltung_id', headerFilter: true, visible: false},
{title: 'LV Kurzbz', field: 'kurzbz', headerFilter: true, visible:false, width: 70},
{title: 'STG Kurzbz', field: 'stg_typ_kurzbz', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'stg_typ_kurzbz'}, visible:true, width: 80},
{title: 'OrgEinheit', field: 'lv_oe_bezeichnung', headerFilter: true, visible: false, width: 250},
{title: 'Lehrtyp Kurzbz', field: 'lehrtyp_kurzbz', headerFilter: true, visible:false, width: 70},
{title: 'Studiengangtyp', field: 'stg_typ_bezeichnung', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'stg_typ_bezeichnung'}, width: 150},
{title: 'OrgForm', field: 'orgform_kurzbz', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'orgform_kurzbz'}, width: 70},
{title: 'Semester', field: 'semester', headerFilter: true, width: 50},
{title: 'Lehrveranstaltung', field: 'lv_bezeichnung', headerFilter: true, minWidth: 250},
{title: 'Lehrveranstaltung ENG', field: 'bezeichnung_english', headerFilter: true, minWidth: 250},
{title: 'ECTS', field: 'ects', headerFilter: true, width: 50, hozAlign: 'right'},
{title: 'Lehrform', field: 'lehrform_kurzbz', headerFilter: true, width: 50},
{title: 'Sprache', field: 'sprache', headerFilter: true, width: 100},
{title: 'Aktiv', field: 'aktiv', width: 50,
formatter:"tickCross",
headerFilter:"tickCross",
headerFilterParams:{"tristate": true},
hozAlign:"center",
formatterParams: {
tickElement: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>'
}
},
{title: 'Studienplan', field: 'studienplan_bezeichnung', headerFilter: true, visible:true, width: 220},
{title: 'OE Kurzbz', field: 'lv_oe_kurzbz', headerFilter: true, visible:false, minWidth: 80},
{
title: this.$p.t('global/aktionen'),
field: 'actions',
width: 140,
formatter: (cell, formatterParams, onRendered) => {
let container = document.createElement('div');
container.className = "d-flex gap-2";
let button = document.createElement('button');
button.className = 'btn btn-outline-secondary';
button.innerHTML = '<i class="fa fa-external-link"></i> ' + this.$p.t('global/verwalten');
button.addEventListener('click', (event) => this.openAdminLvTemplate(event, cell.getRow()));
container.append(button);
return container;
},
frozen: true
}
]
}
},
urlToAdminAllTemplates() {
return FHC_JS_DATA_STORAGE_OBJECT.app_root +
'vilesci/lehre/lehrveranstaltung.php?stg_kz=99999&semester=-1&orgform=-1';
}
},
methods: {
async loadAndSetStudiensemester(){
const result = await this.$fhcApi
.get('api/frontend/v1/organisation/Studiensemester/getAll', {start: STUDIENSEMESTER_DROPDOWN_STARTDATE})
.then(result => this.studiensemester = result.data )
.then(() => this.$fhcApi.get('api/frontend/v1/organisation/Studiensemester/getAktNext') ) // Get actual Studiensemester
.then(result => this.selectedStudiensemester = result.data[0].studiensemester_kurzbz ) // Preselect Studiensemester
.catch(error => this.$fhcAlert.handleSystemError(error) );
},
async onTableBuilt(){
this.table = this.$refs.lvTemplateUebersichtTable.tabulator;
// Await Studiensemester
await this.loadAndSetStudiensemester();
// Set table data
this.table.setData(
this.$fhcApi.getUri() +
'/api/frontend/v1/education/Lehrveranstaltung/getTemplateLvTree' +
'?studiensemester_kurzbz=' + this.selectedStudiensemester
);
// Await phrases categories
await this.$p.loadCategory(['lehre']);
// Replace column titles with phrasen
this.table.updateColumnDefinition('lv_bezeichnung', {title: this.$p.t('lehre', 'lehrveranstaltung')});
},
onChangeStudiensemester(){
// Reset table data
this.table.setData(
this.$fhcApi.getUri() +
'/api/frontend/v1/education/Lehrveranstaltung/getTemplateLvTree' +
'?studiensemester_kurzbz=' + this.selectedStudiensemester
);
},
openAdminLvTemplate(event, row){
const url = FHC_JS_DATA_STORAGE_OBJECT.app_root +
'vilesci/lehre/lehrveranstaltung.php?stg_kz=&semester=-1&orgform=-1&lehrveranstaltung_id=' +
row.getData().lehrveranstaltung_id;
window.open(url, '_blank').focus();
},
prepDataTreeData(data){
let toDelete = [];
// loop through all data
for (let childIdx = 0; childIdx < data.length; childIdx++)
{
let child = data[childIdx];
// if it has parent id, it is a child
if (child[parentIdField])
{
// append the child on the right place. If parent found, mark original sw child on 0 level for deleting
if (this._appendChild(data, child)) toDelete.push(childIdx);
}
}
// delete the marked children from 0 level
for (let counter = 0; counter < toDelete.length; counter++)
{
// decrease index by counter as index of data array changes after every deletion
data.splice(toDelete[counter] - counter, 1);
}
return data;
},
_appendChild(data, child) {
// get parent id
let parentId = child[parentIdField];
// loop thorugh all data
for (let parentIdx = 0; parentIdx < data.length; parentIdx++)
{
let parent = data[parentIdx];
// if it's the parent
if (parent[idField] == parentId)
{
// create children array if not done yet
if (!parent._children) parent._children = [];
// if child is not included in children array, append the child
if (!parent._children.includes(child)) parent._children.push(child);
// parent found
return true;
}
// search children for parents
else if (parent._children) this._appendChild(parent._children, child);
}
// parent not found
return false;
},
reloadTabulator() {
if (this.table !== null && this.table !== undefined)
{
for (let option in this.tabulatorOptions)
{
if (this.table.options.hasOwnProperty(option))
this.table.options[option] = this.tabulatorOptions[option];
}
this.$refs.lvTemplateUebersichtTable.reloadTable();
}
},
},
template: `
<div class="lvTemplateUebersicht overflow-hidden">
<div class="row d-flex mb-3">
<div class="col-10 h2 mb-4">{{ $p.t('lehre/lvTemplatesUebersicht') }}</div>
<div class="col-2 ms-auto align-self-end">
<core-form-input
type="select"
v-model="selectedStudiensemester"
name="studiensemester"
@change="onChangeStudiensemester">
<option
v-for="(studSem, index) in studiensemester"
:key="index"
:value="studSem.studiensemester_kurzbz">
{{studSem.studiensemester_kurzbz}}
</option>
</core-form-input>
</div>
</div>
<div class="row mb-5">
<div class="col">
<core-filter-cmpt
ref="lvTemplateUebersichtTable"
uniqueId="lvTemplateUebersichtTable"
table-only
:side-menu="false"
:tabulator-options="tabulatorOptions"
:tabulator-events="[{event: 'tableBuilt', handler: onTableBuilt}]">
<template v-slot:actions>
<a type="button" class="btn btn-primary" :href="urlToAdminAllTemplates" target="_blank"><i class="fa fa-external-link me-2"></i>{{ $p.t('lehre/lvTemplatesVerwalten') }}</a>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="checkbox"
v-model="cbDataTreeStartExpanded"
:checked="cbDataTreeStartExpanded"
@change="reloadTabulator">
<label class="form-check-label">Templates {{ $p.t('global/aufgeklappt') }}</label>
</div>
</template>
</core-filter-cmpt>
</div>
</div>
</div>
`
};
+22 -10
View File
@@ -1,15 +1,11 @@
<?php
if (! defined('DB_NAME')) exit('No direct script access allowed');
if ($result = $db->db_query("SELECT * FROM information_schema.views WHERE table_catalog = '" . DB_NAME . "' AND table_schema = 'public' AND table_name = 'vw_oe_path'"))
{
if($db->db_num_rows($result) == 0)
{
$qry = "
$qry = "
CREATE OR REPLACE VIEW public.vw_oe_path AS
WITH RECURSIVE vw_oe_path(oe_kurzbz, bezeichnung, oe_parent_kurzbz, organisationseinheittyp_kurzbz, oetyp_bezeichnung, depth, path) AS (
WITH RECURSIVE vw_oe_path(oe_kurzbz, bezeichnung, oe_parent_kurzbz, organisationseinheittyp_kurzbz, oetyp_bezeichnung, depth, path, path_kurzbz) AS (
SELECT
oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, 0, '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung AS path
oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, 0, '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung AS path, '/' || oe.oe_kurzbz AS path_kurzbz
FROM
public.tbl_organisationseinheit oe
JOIN
@@ -18,7 +14,7 @@ if ($result = $db->db_query("SELECT * FROM information_schema.views WHERE table_
oe.oe_parent_kurzbz IS NULL
UNION ALL
SELECT
oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, depth + 1, oet.path || '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung
oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, depth + 1, oet.path || '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung, oet.path_kurzbz || '/' || oe.oe_kurzbz AS path_kurzbz
FROM
public.tbl_organisationseinheit oe, vw_oe_path oet
JOIN
@@ -29,11 +25,27 @@ if ($result = $db->db_query("SELECT * FROM information_schema.views WHERE table_
SELECT * FROM vw_oe_path ORDER BY path, depth;
GRANT SELECT ON public.vw_oe_path TO vilesci;
";
";
if ($result = $db->db_query("SELECT * FROM information_schema.views WHERE table_catalog = '" . DB_NAME . "' AND table_schema = 'public' AND table_name = 'vw_oe_path'"))
{
if($db->db_num_rows($result) == 0)
{
if (!$db->db_query($qry))
echo '<strong>public.vw_oe_path: ' . $db->db_last_error() . '</strong><br />';
else
echo 'public.vw_oe_path: erstellt<br />';
}
}
if ($result = $db->db_query("SELECT * FROM information_schema.columns WHERE table_catalog = '" . DB_NAME . "' AND table_schema = 'public' AND table_name = 'vw_oe_path' AND column_name = 'path_kurzbz'"))
{
if($db->db_num_rows($result) == 0)
{
if (!$db->db_query($qry))
echo '<strong>public.vw_oe_path: ' . $db->db_last_error() . '</strong><br />';
else
echo 'public.vw_oe_path: neu erstellt mit zusätzlicher spalte path_kurzbz<br />';
}
}
+1
View File
@@ -1298,6 +1298,7 @@ $filters = array(
{"name": "os"},
{"name": "lizenzserver_kurzbz"},
{"name": "lizenzserver_port"},
{"name": "anzahl_lizenzen"},
{"name": "softwarestatus_kurzbz"}
],
"filters": []
+860
View File
@@ -18188,6 +18188,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',
@@ -18703,6 +18723,366 @@ array(
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusGeplant',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'geplant',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'planned',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusGeplantDesc',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Studierende hat die Maßnahme geplant.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The student has planned the measure.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusAkzeptiert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'akzeptiert',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'accepted',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusAkzeptiertDesc',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Die geplante Maßnahme wurde akzeptiert.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The planned measure has been accepted.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusDurchgefuehrt',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'durchgeführt',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'performed',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusDurchgefuehrtDesc',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Eine Bestätigung wurde hochgeladen.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'A confirmation has been uploaded.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusBestaetigt',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'bestätigt',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'confirmed',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusBestaetigtDesc',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Die hochgeladene Bestätigung wurde akzeptiert.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The uploaded confirmation has been accepted.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusAbgelehnt',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'abgelehnt',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'declined',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'statusAbgelehntDesc',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Die Maßnahme wurde abgelehnt.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The measure was rejected.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'ampelRed',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Es wurden keine Maßnahmen geplant oder alle wurden abgelehnt.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'No measures have been planned, or all have been rejected.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'ampelYellow',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Mindestens eine Maßnahme wurde akzeptiert.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'At least one measure has been accepted.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'ampelOrange',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Es gibt mindestens eine geplante oder durchgeführte Maßnahme.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'There is at least one planned or performed measure.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'ampelGreenyellow',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Nur bestätigte Maßnahmen vorhanden, aber weniger als 5 ECTs.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Only confirmed measures, but fewer than 5 ECTs.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'ampelGreen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Es wurden 5 ECTs erreicht.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => '5 ECTs points have been achieved.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'mailMeldungzuviele',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Die Anzahl der Empfänger überschreitet 50. Bitte verwenden Sie einen Filter (z.B. Semester), um die Empfängeranzahl zu reduzieren.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The number of recipients exceeds 50. Please use a filter (e.g., semester) to reduce the number of recipients.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'mailMeldung',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Keine Studierenden ohne geplante Maßnahmen gefunden.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'No students without planned measures were found.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'mailButton',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'E-Mail nur an Studierende, die keine Maßnahmen geplant haben.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Send email only to students who have no planned measures.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
@@ -18743,6 +19123,26 @@ array(
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'mailversenden',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Mail versenden',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Send mail',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
@@ -31765,6 +32165,446 @@ array(
)
),
// Betriebsmittel end
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'softwareanforderung',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Softwareanforderung',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Software Request',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'softwareanforderungSubtitle',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Softwareanforderung und Lizenzmanagement für die Lehre',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Software Request and License management for Education',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swAnforderungenUndLizenen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Softwareanforderungen & Lizenzen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Software Requirements & Licenses',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anforderungNachSw',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Anforderung nach Software',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Request by Software',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anforderungNachLv',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Anforderung nach LV',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Request by Course',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swNichtGefundenHierBestellen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Software nicht gefunden?<br>Hier bei IT-Services bestellen",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software not found?<br>Order here from IT Services",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'bereitsAngefordert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Bereits angefordert",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Requested already",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'mindEineZuorndungExistiertBereits',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Mindestens eine Zuordnung existiert bereits.",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "At least one assignment already exists.",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swFuerLvAnfordern',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Software für LV anfordern",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Request software for courses",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swWurdeBereitsAngefordert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Software wurde bereits angefordert",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software has already been requested",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swAnforderungUeberAuswahlVonSw',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Softwareanforderung über die Auswahl von Software",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software Requirements based on the Selection of Software",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swAnforderungUeberAuswahlVonLvs',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Softwareanforderung über die Auswahl von Lehrveranstaltungen",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software Requirements based on the Selection of Courses",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'lizenzAnzahlNeu',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Lizenz-Anzahl NEU",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "License Number NEW",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'lizenzanzahlAendern',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Lizenzanzahl ändern",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Change Number of Licenses",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'eingabeFehlt',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Eingabe fehlt",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Input missing",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'unveraendert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Unverändert",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Unchanged",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anforderungenVorruecken',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Anforderungen vorrücken",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Take over Requirements",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'vorrueckenInStudiensemester',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Vorrücken in Studiensemester",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Take over to semester",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anteiligInProzent',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Anteilig in %",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Percentage share",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'verwalten',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Verwalten",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Administrate",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'lvTemplatesVerwalten',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "LV Templates verwalten",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Administrate Course Templates",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'lvTemplatesUebersicht',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "LV Templates Übersicht",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Course Templates Overview",
'description' => '',
'insertvon' => 'system'
)
)
),
//**************************** CORE/konto
array(
'app' => 'core',
@@ -33132,6 +33972,26 @@ array(
)
)
),
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'
)
)
)
// AMPELN PHRASEN -----------------------------------------------------------------------------
array(
'app' => 'core',
+14 -6
View File
@@ -106,7 +106,7 @@ echo '<!DOCTYPE HTML>
</script>
</head>
<body style="background-color:#eeeeee;">
<h2>Lehreinheiten Vorr&uuml;ckung</h2>
<h2>LV-Teile Vorr&uuml;ckung</h2>
';
echo '<form action="'.$_SERVER['PHP_SELF'].'" method="GET">';
echo 'Studiengang: <SELECT name="studiengang_kz">';
@@ -246,9 +246,17 @@ if ($studiengang_kz != '' && $stsem_von != '' && $stsem_nach != '')
{
$anzahl_nach = $db->db_num_rows($result);
$baseurl = basename($_SERVER['REQUEST_URI']);
if ($anzahl_nach >= $anzahl_von && !isset($_GET['continue']))
if ($anzahl_von == 0 && !isset($_GET['continue']))
{
echo '<br><br><span style="color:red">Es sind schon Lehreinheiten fuer das
echo '<br><br><span style="color:orange">Es sind kein LV-Teile im
'.$stsem_von.' in '.$stg_arr[$studiengang_kz].' '.$semester.' vorhanden.
Trotzdem fortsetzen?</span><br><br>
<form action="'.$baseurl.'&continue" method="POST"><input type="submit" value="Fortsetzen"></form>';
die ();
}
elseif ($anzahl_von > 0 && $anzahl_nach >= $anzahl_von && !isset($_GET['continue']))
{
echo '<br><br><span style="color:red">Es sind schon '.$anzahl_nach.' LV-Teile fuer das
'.$stsem_nach.' in '.$stg_arr[$studiengang_kz].' '.$semester.' vorhanden.
Trotzdem fortsetzen?</span><br><br>
<form action="'.$baseurl.'&continue" method="POST"><input type="submit" value="Fortsetzen"></form>';
@@ -553,15 +561,15 @@ if ($studiengang_kz != '' && $stsem_von != '' && $stsem_nach != '')
}
else
{
$text .= 'Fehler beim Laden der Lehreinheiten '.$db->db_last_error();
$text .= 'Fehler beim Laden der LV-Teile '.$db->db_last_error();
$error_lehreinheit++;
}
echo "<br><br>";
echo "Vorgerueckte Lehreinheiten: $anzahl_lehreinheiten<br>";
echo "Vorgerueckte LV-Teile: $anzahl_lehreinheiten<br>";
echo "Vorgerueckte LEMitarbeiter: $anzahl_lehreinheitmitarbeiter<br>";
echo "Vorgerueckte LEGruppen: $anzahl_lehreinheitgruppe<br>";
echo "Fehler bei Lehreinheiten: $error_lehreinheit<br>";
echo "Fehler bei LV-Teil: $error_lehreinheit<br>";
echo "Fehler bei LEMitarbeiter: $error_lehreinheitmitarbeiter<br>";
echo "Fehler bei LEGruppen: $error_lehreinheitmitarbeiter<br>";