diff --git a/application/controllers/jobs/IssueResolver.php b/application/controllers/jobs/IssueResolver.php index be66a6b23..f0f13694e 100755 --- a/application/controllers/jobs/IssueResolver.php +++ b/application/controllers/jobs/IssueResolver.php @@ -9,7 +9,7 @@ class IssueResolver extends IssueResolver_Controller { parent::__construct(); - // set fehler codes which can be resolved by the job + // set fehler codes which can be resolved by the job, with own resolver defined // structure: fehlercode => class (library) name for resolving $this->_codeLibMappings = array( 'CORE_ZGV_0001' => 'CORE_ZGV_0001', @@ -30,7 +30,6 @@ class IssueResolver extends IssueResolver_Controller 'CORE_STG_0002' => 'CORE_STG_0002', 'CORE_STG_0003' => 'CORE_STG_0003', 'CORE_STG_0004' => 'CORE_STG_0004', - 'CORE_STUDENTSTATUS_0001' => 'CORE_STUDENTSTATUS_0001', 'CORE_STUDENTSTATUS_0002' => 'CORE_STUDENTSTATUS_0002', 'CORE_STUDENTSTATUS_0003' => 'CORE_STUDENTSTATUS_0003', 'CORE_STUDENTSTATUS_0004' => 'CORE_STUDENTSTATUS_0004', @@ -51,5 +50,11 @@ class IssueResolver extends IssueResolver_Controller 'CORE_PERSON_0003' => 'CORE_PERSON_0003', 'CORE_PERSON_0004' => 'CORE_PERSON_0004' ); + + // fehler which are resolved the same way as they are produced + // structure: fehlercode => class (library) name for resolving + $this->_codeProducerLibMappings = array( + 'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv', + ); } } diff --git a/application/core/IssueResolver_Controller.php b/application/core/IssueResolver_Controller.php index a9091045f..ea278ddb0 100755 --- a/application/core/IssueResolver_Controller.php +++ b/application/core/IssueResolver_Controller.php @@ -5,18 +5,18 @@ */ abstract class IssueResolver_Controller extends JOB_Controller { - protected $_codeLibMappings; + // mappings in form fehlercode -> resolverlibrary name, fehler which have explicit resolver class defined + protected $_codeLibMappings = []; + + // mappings in form fehlercode -> producer library name, fehler which are resolved the same way they are produced + protected $_codeProducerLibMappings = []; public function __construct() { parent::__construct(); // pass extension name if calling from extension - $extensionName = isset($this->_extensionName) ? $this->_extensionName : null; - $this->load->model('system/Issue_model', 'IssueModel'); - - $this->load->library('issues/PlausicheckResolverLib', ['extensionName' => $extensionName]); } /** @@ -24,14 +24,25 @@ abstract class IssueResolver_Controller extends JOB_Controller */ public function run() { + $this->load->library( + 'issues/PlausicheckResolverLib', + [ + 'extensionName' => $this->_extensionName ?? null, + 'codeLibMappings' => $this->_codeLibMappings, + 'codeProducerLibMappings' => $this->_codeProducerLibMappings + ] + ); + $this->logInfo("Issue resolve job started"); // load open issues with given errorcodes - $openIssuesRes = $this->IssueModel->getOpenIssues(array_keys($this->_codeLibMappings)); + $openIssuesRes = $this->IssueModel->getOpenIssues( + array_merge(array_keys($this->_codeLibMappings), array_keys($this->_codeProducerLibMappings)) + ); $openIssues = hasData($openIssuesRes) ? getData($openIssuesRes) : []; - $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($this->_codeLibMappings, $openIssues); + $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($openIssues); // log if error, or log info if inserted new issue foreach ($result->errors as $error) $this->logError($error); diff --git a/application/core/PlausiIssueProducer_Controller.php b/application/core/PlausiIssueProducer_Controller.php index d8eea61e9..5216d284c 100644 --- a/application/core/PlausiIssueProducer_Controller.php +++ b/application/core/PlausiIssueProducer_Controller.php @@ -5,25 +5,19 @@ */ abstract class PlausiIssueProducer_Controller extends JOB_Controller { - protected $_fehlerLibMappings; + protected $_fehlerLibMappings = []; protected $_app; - public function __construct($app = null) - { - parent::__construct(); - - // pass extension name if calling from extension - $extensionName = isset($this->_extensionName) ? $this->_extensionName : null; - - // load libraries - $this->load->library('issues/PlausicheckProducerLib', array('extensionName' => $extensionName, 'app' => $this->_app)); - } - protected function producePlausicheckIssues($params) { + $this->load->library( + 'issues/PlausicheckProducerLib', + ['extensionName' => $this->_extensionName ?? null, 'app' => $this->_app, 'fehlerLibMappings' => $this->_fehlerLibMappings] + ); + $this->logInfo("Plausicheck issue producer job started"); - $result = $this->plausicheckproducerlib->producePlausicheckIssues($this->_fehlerLibMappings, $params); + $result = $this->plausicheckproducerlib->producePlausicheckIssues($params); // log if error, or log info if inserted new issue foreach ($result->errors as $error) $this->logError($error); diff --git a/application/libraries/issues/PlausicheckProducerLib.php b/application/libraries/issues/PlausicheckProducerLib.php index e7a772e59..cea9967fb 100644 --- a/application/libraries/issues/PlausicheckProducerLib.php +++ b/application/libraries/issues/PlausicheckProducerLib.php @@ -12,12 +12,16 @@ class PlausicheckProducerLib private $_ci; // ci instance private $_extensionName; // name of extension - private $_konfiguration = array(); // configuration parameters + private $_konfiguration = []; // configuration parameters + private $_fehlerLibMappings = []; // mappings of fehler and libraries for producing them + private $_isForResolutionCheck = false; // mappings of fehler and libraries for producing them public function __construct($params = null) { // set extension name if called from extension if (isset($params['extensionName'])) $this->_extensionName = $params['extensionName']; + if (isset($params['fehlerLibMappings'])) $this->_fehlerLibMappings = $params['fehlerLibMappings']; + if (isset($params['isForResolutionCheck'])) $this->_isForResolutionCheck = $params['isForResolutionCheck']; // set application $app = isset($params['app']) ? $params['app'] : null; @@ -45,18 +49,17 @@ class PlausicheckProducerLib } /** - * Produces multiple plausicheck issues at once. - * @param array $fehlerLibMappings contains fehler type to check and library responsible for check (fehler_kurzbz => libName) + * Produces multiple plausicheck issues at once and saved them to db. * @param array $params passed to each plausicheck * @return result object with occured error and info */ - public function producePlausicheckIssues($fehlerLibMappings, $params) + public function producePlausicheckIssues($params) { $result = new StdClass(); $result->errors = []; $result->infos = []; - foreach ($fehlerLibMappings as $fehler_kurzbz => $libName) + foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName) { $plausicheckRes = $this->producePlausicheckIssue( $libName, @@ -116,7 +119,10 @@ class PlausicheckProducerLib $config = isset($this->_konfiguration[$fehler_kurzbz]) ? $this->_konfiguration[$fehler_kurzbz] : null; // load library connected to fehlercode - $this->_ci->load->library($issuesLibPath . $libName, $config); + $this->_ci->load->library( + $issuesLibPath . $libName, + ['configurationParams' => $config, 'isForResolutionCheck' => $this->_isForResolutionCheck] + ); $lowercaseLibName = mb_strtolower($libName); diff --git a/application/libraries/issues/PlausicheckResolverLib.php b/application/libraries/issues/PlausicheckResolverLib.php index cd88cf5be..618611cee 100644 --- a/application/libraries/issues/PlausicheckResolverLib.php +++ b/application/libraries/issues/PlausicheckResolverLib.php @@ -12,15 +12,20 @@ class PlausicheckResolverLib private $_ci; // ci instance private $_extensionName; // name of extension + private $_codeLibMappings = []; // mappings for issues which explicitly defined resolver + private $_codeProducerLibMappings = []; // mappings for issues which are resolved as produced public function __construct($params = null) { // set extension name if called from extension if (isset($params['extensionName'])) $this->_extensionName = $params['extensionName']; + if (isset($params['codeLibMappings'])) $this->_codeLibMappings = $params['codeLibMappings']; + if (isset($params['codeProducerLibMappings'])) $this->_codeProducerLibMappings = $params['codeProducerLibMappings']; $this->_ci =& get_instance(); // get ci instance $this->_ci->load->library('IssuesLib'); + $this->_ci->load->library('issues/PlausicheckProducerLib', ['isForResolutionCheck' => true]); } /** @@ -29,7 +34,7 @@ class PlausicheckResolverLib * @param array $openIssues passed issues to resolve * @return result object with occured error and info */ - public function resolvePlausicheckIssues($codeLibMappings, $openIssues) + public function resolvePlausicheckIssues($openIssues) { $result = new StdClass(); $result->errors = []; @@ -37,11 +42,6 @@ class PlausicheckResolverLib foreach ($openIssues as $issue) { - // ignore if Fehlercode is not in libmappings (shouldn't be checked) - if (!isset($codeLibMappings[$issue->fehlercode])) continue; - - $libName = $codeLibMappings[$issue->fehlercode]; - // add person id and oe kurzbz automatically as params, merge it with additional params // decode bewerbung_parameter into assoc array $params = array_merge( @@ -49,58 +49,85 @@ class PlausicheckResolverLib isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array() ); - // if called from extension (extension name set), path includes extension names - $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; + $issueResolved = false; - // path for loading issue library - $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; - - // file path of library for check if file exists - $issuesLibFilePath = DOC_ROOT . self::CI_PATH - . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; - - // check if library file exists - if (!file_exists($issuesLibFilePath)) + // ignore if Fehlercode is not in libmappings (shouldn't be checked) + if (isset($this->_codeLibMappings[$issue->fehlercode])) { - // log error and continue with next issue if not - $result->errors[] = "Issue library file " . $issuesLibFilePath . " does not exist"; - continue; - } + $libName = $this->_codeLibMappings[$issue->fehlercode]; - // load library connected to fehlercode - $this->_ci->load->library($issuesLibPath . $libName); + // if called from extension (extension name set), path includes extension names + $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; - $lowercaseLibName = mb_strtolower($libName); + // path for loading issue library + $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; - // check if method is defined in library class - if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) - { - // log error and continue with next issue if not - $result->errors[] = "Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"; - continue; - } + // file path of library for check if file exists + $issuesLibFilePath = DOC_ROOT . self::CI_PATH + . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; - // call the function for checking for issue resolution - $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); - - if (isError($issueResolvedRes)) - { - $result->errors[] = getError($issueResolvedRes); - } - else - { - $issueResolvedData = getData($issueResolvedRes); - - if ($issueResolvedData === true) + // check if library file exists + if (!file_exists($issuesLibFilePath)) { - // set issue to resolved if needed - $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null); - - if (isError($behobenRes)) - $result->errors[] = getError($behobenRes); - else - $result->infos[] = "Issue " . $issue->issue_id . " successfully resolved"; + // log error and continue with next issue if not + $result->errors[] = "Issue library file " . $issuesLibFilePath . " does not exist"; + continue; } + + // load library connected to fehlercode + $this->_ci->load->library($issuesLibPath . $libName); + + $lowercaseLibName = mb_strtolower($libName); + + // check if method is defined in library class + if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) + { + // log error and continue with next issue if not + $result->errors[] = "Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"; + continue; + } + + // call the function for checking for issue resolution + $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); + + if (isError($issueResolvedRes)) + { + $result->errors[] = getError($issueResolvedRes); + } + else + { + $issueResolved = getData($issueResolvedRes) === true; + } + } + elseif (isset($this->_codeProducerLibMappings[$issue->fehlercode])) + { + $libName = $this->_codeProducerLibMappings[$issue->fehlercode]; + + $issueResolvedRes = $this->_ci->plausicheckproducerlib->producePlausicheckIssue( + $libName, + $issue->fehler_kurzbz, + $params + ); + + if (isError($issueResolvedRes)) + { + $result->errors[] = getError($issueResolvedRes); + } + else + { + $issueResolved = !hasData($issueResolvedRes); + } + } + + // set issue to resolved if needed + if ($issueResolved) + { + $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null); + + if (isError($behobenRes)) + $result->errors[] = getError($behobenRes); + else + $result->infos[] = "Issue " . $issue->issue_id . " successfully resolved"; } } diff --git a/application/libraries/issues/plausichecks/AbbrecherAktiv.php b/application/libraries/issues/plausichecks/AbbrecherAktiv.php index 9eae389b5..464b77a30 100644 --- a/application/libraries/issues/plausichecks/AbbrecherAktiv.php +++ b/application/libraries/issues/plausichecks/AbbrecherAktiv.php @@ -9,83 +9,21 @@ require_once('PlausiChecker.php'); */ class AbbrecherAktiv extends PlausiChecker { - public function executePlausiCheck($params) - { - $results = array(); + protected $_base_sql = " + SELECT + pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_prestudentstatus pre_status + JOIN public.tbl_prestudent pre USING(prestudent_id) + JOIN public.tbl_student student USING(prestudent_id) + JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + WHERE + pre_status.status_kurzbz ='Abbrecher' + AND benutzer.aktiv=true"; - // get parameters from config - $exkludierte_studiengang_kz = isset($this->_config['exkludierteStudiengaenge']) ? $this->_config['exkludierteStudiengaenge'] : null; - - // pass parameters needed for plausicheck - $studiengang_kz = isset($params['studiengang_kz']) ? $params['studiengang_kz'] : null; - - // get all students failing the plausicheck - $prestudentRes = $this->getAbbrecherAktiv($studiengang_kz, null, $exkludierte_studiengang_kz); - - if (isError($prestudentRes)) return $prestudentRes; - - if (hasData($prestudentRes)) - { - $prestudents = getData($prestudentRes); - - // populate results with data necessary for writing issues - foreach ($prestudents as $prestudent) - { - $results[] = array( - 'person_id' => $prestudent->person_id, - 'oe_kurzbz' => $prestudent->prestudent_stg_oe_kurzbz, - 'fehlertext_params' => array('prestudent_id' => $prestudent->prestudent_id), - 'resolution_params' => array('prestudent_id' => $prestudent->prestudent_id) - ); - } - } - - // return the results - return success($results); - } - - /** - * Abbrecher cannot be active. - * @param studiengang_kz int if check is to be executed for certain Studiengang - * @param prestudent_id int if check is to be executed only for one prestudent - * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check - * @return success with prestudents or error - */ - public function getAbbrecherAktiv($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) - { - $params = array(); - - $qry = " - SELECT - pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz - FROM - public.tbl_prestudentstatus pre_status - JOIN public.tbl_prestudent pre USING(prestudent_id) - JOIN public.tbl_student student USING(prestudent_id) - JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid) - JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz - WHERE - pre_status.status_kurzbz ='Abbrecher' - AND benutzer.aktiv=true"; - - if (isset($studiengang_kz)) - { - $qry .= " AND stg.studiengang_kz = ?"; - $params[] = $studiengang_kz; - } - - if (isset($prestudent_id)) - { - $qry .= " AND pre.prestudent_id = ?"; - $params[] = $prestudent_id; - } - - if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz)) - { - $qry .= " AND stg.studiengang_kz NOT IN ?"; - $params[] = $exkludierte_studiengang_kz; - } - - return $this->_db->execReadOnlyQuery($qry, $params); - } + protected $_config_params = ['exkludierteStudiengaenge' => " AND stg.studiengang_kz NOT IN ?"]; + protected $_params_for_checking = ['studiengang_kz' => " AND stg.studiengang_kz = ?", 'prestudent_id' => " AND pre.prestudent_id = ?"]; + protected $_fehlertext_params = ['prestudent_id']; + protected $_resolution_params = ['prestudent_id']; } diff --git a/application/libraries/issues/plausichecks/PlausiChecker.php b/application/libraries/issues/plausichecks/PlausiChecker.php index 086a44cc4..5e9c2469f 100644 --- a/application/libraries/issues/plausichecks/PlausiChecker.php +++ b/application/libraries/issues/plausichecks/PlausiChecker.php @@ -6,15 +6,25 @@ abstract class PlausiChecker { protected $_ci; // code igniter instance - protected $_config; // configuration parameters for this plausicheck + protected $_config; // all applicable configuration parameters for this plausicheck protected $_db; // database for queries - public function __construct($configurationParams = null) + protected $_isForResolutionCheck; + + protected $_config_params = []; // name of all config params which should be applied for this plausicheck, with sql [name] => [sql] + protected $_params_for_checking = []; // name of all passed params for checking, with sql [name] => [sql] + + protected $_fehlertext_params = []; // parameter names for fehlertext params used for this plausicheck + protected $_resolution_params = []; // parameter names for resolution params used for this plausicheck + + public function __construct($params = null) { $this->_ci =& get_instance(); // get code igniter instance // set configuration - $this->_config = $configurationParams; + $this->_config = $params['configurationParams'] ?? []; + + $this->_isForResolutionCheck = $params['isForResolutionCheck'] ?? false; // get database for queries $this->_db = new DB_Model(); @@ -25,5 +35,83 @@ abstract class PlausiChecker * @param $paramsForChecking array parameters needed for executing the check * @return array with objects which failed the plausi check */ - abstract public function executePlausiCheck($paramsForChecking); + public function executePlausiCheck($paramsForChecking) + { + $results = []; + $params = []; + $qry = $this->_base_sql; + + if ($this->_isForResolutionCheck == true) + { + foreach ($this->_resolution_params as $resParam) + { + if (!isset($paramsForChecking[$resParam])) + return error("$resParam missing".(isset($paramsForChecking['issue_id']) ? ", issue ID: ".$paramsForChecking['issue_id'] : "")); + } + } + + // add config params to query + if (isset($this->_config_params) && !isEmptyArray($this->_config_params)) + { + foreach ($this->_config_params as $param_name => $param_sql) + { + if (isset($this->_config[$param_name])) + { + $qry .= $param_sql; + $params[] = $this->_config[$param_name]; + } + } + } + + // add check params to query + if (isset($this->_params_for_checking) && !isEmptyArray($this->_params_for_checking)) + { + foreach ($this->_params_for_checking as $param_name => $param_sql) + { + if (isset($paramsForChecking[$param_name])) + { + $qry .= $param_sql; + $params[] = $paramsForChecking[$param_name]; + } + } + } + + $result = $this->_db->execReadOnlyQuery($qry, $params); + + if (isError($result)) return $result; + + if (hasData($result)) + { + $data = getData($result); + + // populate results with data necessary for writing issues + foreach ($data as $d) + { + $fehlertext_params = []; + $resolution_params = []; + + // add params for error texts + foreach ($this->_fehlertext_params as $param) + { + if (isset($d->{$param})) $fehlertext_params[$param] = $d->{$param}; + } + + // add params for resolution of issue + foreach ($this->_resolution_params as $param) + { + if (isset($d->{$param})) $resolution_params[$param] = $d->{$param}; + } + + $results[] = array( + 'person_id' => $d->person_id, + 'oe_kurzbz' => $d->prestudent_stg_oe_kurzbz, + 'fehlertext_params' => $fehlertext_params, + 'resolution_params' => $resolution_params + ); + } + } + + // return the results + return success($results); + } } diff --git a/application/models/system/Issue_model.php b/application/models/system/Issue_model.php index 3d39e9879..331b0f050 100644 --- a/application/models/system/Issue_model.php +++ b/application/models/system/Issue_model.php @@ -22,13 +22,23 @@ class Issue_model extends DB_Model */ public function getOpenIssues($fehlercodes, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null) { - $params = array($fehlercodes); + $params = array(); // issue exists for a fehlercode (or fehlercode_extern), person_id, oe_kurzbz, if not verarbeitet yet - $qry = 'SELECT issue_id, fehlercode, inhalt, fehlercode_extern, inhalt_extern, person_id, oe_kurzbz, - behebung_parameter, datum, verarbeitetvon, verarbeitetamum - FROM system.tbl_issue - WHERE fehlercode IN ? - AND verarbeitetamum IS NULL'; + $qry = 'SELECT + iss.issue_id, iss.fehlercode, fe.fehler_kurzbz, iss.inhalt, iss.fehlercode_extern, + iss.inhalt_extern, iss.person_id, iss.oe_kurzbz, iss.behebung_parameter, + iss.datum, iss.verarbeitetvon, iss.verarbeitetamum + FROM + system.tbl_issue iss + JOIN system.tbl_fehler fe USING (fehlercode) + WHERE + verarbeitetamum IS NULL'; + + if (!isEmptyArray($fehlercodes)) + { + $qry .= ' AND fehlercode IN ?'; + $params[] = $fehlercodes; + } if (!isEmptyString($fehlercode_extern)) {