From 30c6f10d8091b8ce460e1b79c0052fae30f815e6 Mon Sep 17 00:00:00 2001 From: Paolo Date: Wed, 4 Mar 2020 15:54:23 +0100 Subject: [PATCH 001/162] First proposal --- application/config/jqm.php | 6 ++ .../controllers/system/JobsQueueMonitor.php | 56 +++++++++++++++++++ application/core/JQW_Controller.php | 56 +++++++++++++++++++ application/libraries/JobsQueueLib.php | 56 +++++++++++++++++++ 4 files changed, 174 insertions(+) create mode 100644 application/config/jqm.php create mode 100644 application/controllers/system/JobsQueueMonitor.php create mode 100644 application/core/JQW_Controller.php create mode 100644 application/libraries/JobsQueueLib.php diff --git a/application/config/jqm.php b/application/config/jqm.php new file mode 100644 index 000000000..5890241ae --- /dev/null +++ b/application/config/jqm.php @@ -0,0 +1,6 @@ + 'monitoring:r', + 'getJobsByStatus' => 'monitoring:r', + 'getJobsByCreationTime' => 'monitoring:r' + ) + ); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + } + + /** + * + */ + public function getJobsByType() + { + $jobType = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); + + $this->outputJson($this->jobsqueuelib->getJobsByType($jobType)); + } + + /** + * + */ + public function getJobsByStatus() + { + $jobStatus = $this->input->get(JobsQueueLib::PARAM_JOB_STATUS); + + $this->outputJson($this->jobsqueuelib->getJobsByStatus($jobStatus)); + } + + /** + * + */ + public function getJobsByCreationTime() + { + $jobCreationTime = $this->input->get(JobsQueueLib::PARAM_JOB_CREATION_TIME); + + $this->outputJson($this->jobsqueuelib->getJobsByCreationTime($jobCreationTime)); + } +} diff --git a/application/core/JQW_Controller.php b/application/core/JQW_Controller.php new file mode 100644 index 000000000..9cb058f6b --- /dev/null +++ b/application/core/JQW_Controller.php @@ -0,0 +1,56 @@ +load->library('LogLib', array( + 'classIndex' => 5, + 'functionIndex' => 5, + 'lineIndex' => 4, + 'dbLogType' => 'job', // required + 'dbExecuteUser' => 'Jobs queue system' + )); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + } + + // ------------------------------------------------------------------------------------------------------------ + // Protected methods to read/write the jobs queue + + /** + * + */ + protected function getJobsByType($jobType) + { + $jobs = $this->jobsqueuelib->getJobsByType($jobType); + + if (isError($jobs)) $this->logError(getError($jobs), $jobType); + + return $jobs; + } + + /** + * + */ + protected function addNewJobsToQueue($jobType, $jobs) + { + $result = $this->jobsqueuelib->addNewJobsToQueue($jobType, $jobs); + + if (isError($result)) $this->logError(getError($result), $jobType); + + return $result; + } +} diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php new file mode 100644 index 000000000..0c7e44274 --- /dev/null +++ b/application/libraries/JobsQueueLib.php @@ -0,0 +1,56 @@ +_ci =& get_instance(); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * + */ + public function getJobsByType() + { + } + + /** + * + */ + public function addNewJobsToQueue() + { + } + + /** + * + */ + public function getJobsByStatus() + { + } +} From cd815acdbff64ab4797ec95d5661936cea17137b Mon Sep 17 00:00:00 2001 From: Paolo Date: Thu, 5 Mar 2020 15:57:06 +0100 Subject: [PATCH 002/162] - Added new constant BEGINNING_OF_TIME - Added new config entry job_type_permissions_white_list in jqm.php - Added new navigation entry jobsqueueviewer - Added new model application/models/system/JobsQueue_model.php - Added new option in FilterWidget for hours comparison with dates - Added new filter core-jq-lastHour to system/filtersupdate.php - Added new statements to system/dbupdate_3.3.php to create tables system.tbl_jobstatuses, system.tbl_jobtypes and system.tbl_jobstatuses - Added new views application/views/system/jq/jobsQueueViewer.php and application/views/system/jq/jobsQueueViewerData.php --- application/config/constants.php | 7 + application/config/jqm.php | 14 +- application/config/navigation.php | 7 + .../controllers/system/JobsQueueMonitor.php | 56 -------- application/controllers/system/LogsViewer.php | 2 +- .../system/jq/JobsQueueManager.php | 51 +++++++ .../controllers/system/jq/JobsQueueViewer.php | 48 +++++++ application/core/JQW_Controller.php | 33 +++-- application/libraries/FilterWidgetLib.php | 7 +- application/libraries/JobsQueueLib.php | 30 ++-- application/models/system/JobsQueue_model.php | 15 ++ .../views/system/jq/jobsQueueViewer.php | 47 +++++++ .../views/system/jq/jobsQueueViewerData.php | 67 +++++++++ application/views/system/logs/logsViewer.php | 4 +- system/dbupdate_3.3.php | 131 ++++++++++++++++++ system/filtersupdate.php | 31 +++++ 16 files changed, 462 insertions(+), 88 deletions(-) delete mode 100644 application/controllers/system/JobsQueueMonitor.php create mode 100644 application/controllers/system/jq/JobsQueueManager.php create mode 100644 application/controllers/system/jq/JobsQueueViewer.php create mode 100644 application/models/system/JobsQueue_model.php create mode 100644 application/views/system/jq/jobsQueueViewer.php create mode 100644 application/views/system/jq/jobsQueueViewerData.php diff --git a/application/config/constants.php b/application/config/constants.php index ef4cdaf2c..f21b6c962 100644 --- a/application/config/constants.php +++ b/application/config/constants.php @@ -31,6 +31,13 @@ define('EXIT_VALIDATION_UDF_NOT_VALID_VAL', 17); // UDF validation has been fail define('EXIT_AUTO_MIN', 1000); // lowest automatically-assigned error code define('EXIT_AUTO_MAX', 2000); // highest automatically-assigned error code +/* +|-------------------------------------------------------------------------- +| General purpose +|-------------------------------------------------------------------------- +*/ +define('BEGINNING_OF_TIME', '1970-01-01'); + /* |-------------------------------------------------------------------------- | Authentication constants diff --git a/application/config/jqm.php b/application/config/jqm.php index 5890241ae..579fc6987 100644 --- a/application/config/jqm.php +++ b/application/config/jqm.php @@ -2,5 +2,15 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); -// -$config['addable_jobs_black_list'] = array('doomsday', 'sudo rm -fR /', 'sudo mv / /dev/null'); +// White list of permissions that are able to store a spcific job type in database +$config['job_type_permissions_white_list'] = array( + 'SAPStammdatenUpdate' => array( + 'admin' + ), + 'OEHPayment' => array( + 'admin' + ), + 'SAPPayment' => array( + 'admin' + ) +); diff --git a/application/config/navigation.php b/application/config/navigation.php index 9253c87a1..f44b297a5 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -102,6 +102,13 @@ $config['navigation_header'] = array( 'expand' => true, 'sort' => 20, 'requiredPermissions' => 'system/developer:r' + ), + 'jobsqueueviewer' => array( + 'link' => site_url('system/jq/JobsQueueViewer'), + 'description' => 'Jobs Queue Viewer', + 'expand' => true, + 'sort' => 20, + 'requiredPermissions' => 'system/developer:r' ) ) ) diff --git a/application/controllers/system/JobsQueueMonitor.php b/application/controllers/system/JobsQueueMonitor.php deleted file mode 100644 index affb59bef..000000000 --- a/application/controllers/system/JobsQueueMonitor.php +++ /dev/null @@ -1,56 +0,0 @@ - 'monitoring:r', - 'getJobsByStatus' => 'monitoring:r', - 'getJobsByCreationTime' => 'monitoring:r' - ) - ); - - // Loads JobsQueueLib - $this->load->library('JobsQueueLib'); - } - - /** - * - */ - public function getJobsByType() - { - $jobType = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); - - $this->outputJson($this->jobsqueuelib->getJobsByType($jobType)); - } - - /** - * - */ - public function getJobsByStatus() - { - $jobStatus = $this->input->get(JobsQueueLib::PARAM_JOB_STATUS); - - $this->outputJson($this->jobsqueuelib->getJobsByStatus($jobStatus)); - } - - /** - * - */ - public function getJobsByCreationTime() - { - $jobCreationTime = $this->input->get(JobsQueueLib::PARAM_JOB_CREATION_TIME); - - $this->outputJson($this->jobsqueuelib->getJobsByCreationTime($jobCreationTime)); - } -} diff --git a/application/controllers/system/LogsViewer.php b/application/controllers/system/LogsViewer.php index 8caf9f3a7..4e39db5e3 100644 --- a/application/controllers/system/LogsViewer.php +++ b/application/controllers/system/LogsViewer.php @@ -35,7 +35,7 @@ class LogsViewer extends Auth_Controller // Public methods /** - * Main page of the InfoCenter tool + * Everything has a beginning */ public function index() { diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php new file mode 100644 index 000000000..4e82ff44e --- /dev/null +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -0,0 +1,51 @@ + 'admin:r', + 'addNewJobsToQueue' => 'admin:rw' + ) + ); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * To get all the most recently added jobs using the given job type + */ + public function getLastJobs() + { + $type = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); + + $this->outputJson($this->jobsqueuelib->getLastJobs($type)); + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + public function addNewJobsToQueue() + { + $type = $this->input->post(JobsQueueLib::PARAM_JOB_TYPE); + $jobs = $this->input->post(JobsQueueLib::PARAM_JOBS); + + $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + } +} diff --git a/application/controllers/system/jq/JobsQueueViewer.php b/application/controllers/system/jq/JobsQueueViewer.php new file mode 100644 index 000000000..7e8760209 --- /dev/null +++ b/application/controllers/system/jq/JobsQueueViewer.php @@ -0,0 +1,48 @@ + 'system/developer:r' + ) + ); + + // Loads WidgetLib + $this->load->library('WidgetLib'); + + // Loads phrases system + $this->loadPhrases( + array( + 'global', + 'ui', + 'filter' + ) + ); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Everything has a beginning + */ + public function index() + { + $this->load->view('system/jq/jobsQueueViewer.php'); + } +} diff --git a/application/core/JQW_Controller.php b/application/core/JQW_Controller.php index 9cb058f6b..616eaf4fd 100644 --- a/application/core/JQW_Controller.php +++ b/application/core/JQW_Controller.php @@ -3,18 +3,22 @@ if (!defined("BASEPATH")) exit("No direct script access allowed"); /** + * Job Queue Worker * + * This controller acts as interface of the JobsQueueLib that contains all the needed functionalities to operate with + * the Jobs Queue System + * This is an abstract class that provide basic functionalities, it has to be extended to broaden its logic */ abstract class JQW_Controller extends JOB_Controller { /** - * + * Constructor */ public function __construct() { parent::__construct(); - // Loads LogLib with different ... + // Loads LogLib with different parameters $this->load->library('LogLib', array( 'classIndex' => 5, 'functionIndex' => 5, @@ -23,33 +27,36 @@ abstract class JQW_Controller extends JOB_Controller 'dbExecuteUser' => 'Jobs queue system' )); - // Loads JobsQueueLib + // Loads JobsQueueLib library $this->load->library('JobsQueueLib'); } - // ------------------------------------------------------------------------------------------------------------ - // Protected methods to read/write the jobs queue + //------------------------------------------------------------------------------------------------------------------ + // Protected methods /** - * + * To get all the most recently added jobs using the given job type */ - protected function getJobsByType($jobType) + protected function getLastJobs($type) { - $jobs = $this->jobsqueuelib->getJobsByType($jobType); + $jobs = $this->jobsqueuelib->getLastJobs($type); - if (isError($jobs)) $this->logError(getError($jobs), $jobType); + // If an error occurred then log it in database + if (isError($jobs)) $this->logError(getError($jobs), $type); return $jobs; } /** - * + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects */ - protected function addNewJobsToQueue($jobType, $jobs) + protected function addNewJobsToQueue($type, $jobs) { - $result = $this->jobsqueuelib->addNewJobsToQueue($jobType, $jobs); + $result = $this->jobsqueuelib->addNewJobsToQueue($type, $jobs); - if (isError($result)) $this->logError(getError($result), $jobType); + // If an error occurred then log it in database + if (isError($result)) $this->logError(getError($result), $type); return $result; } diff --git a/application/libraries/FilterWidgetLib.php b/application/libraries/FilterWidgetLib.php index 6e87833bd..f909c7083 100644 --- a/application/libraries/FilterWidgetLib.php +++ b/application/libraries/FilterWidgetLib.php @@ -93,6 +93,7 @@ class FilterWidgetLib const OP_NOT_SET = 'nset'; // Filter options values + const OPT_HOURS = 'hours'; const OPT_DAYS = 'days'; const OPT_MONTHS = 'months'; @@ -884,7 +885,8 @@ class FilterWidgetLib // It it's a date type if (is_numeric($filterDefinition->condition) && isset($filterDefinition->option) - && ($filterDefinition->option == self::OPT_DAYS + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS || $filterDefinition->option == self::OPT_MONTHS)) { $condition = '< (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; @@ -899,7 +901,8 @@ class FilterWidgetLib // It it's a date type if (is_numeric($filterDefinition->condition) && isset($filterDefinition->option) - && ($filterDefinition->option == self::OPT_DAYS + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS || $filterDefinition->option == self::OPT_MONTHS)) { $condition = '> (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index 0c7e44274..fe73b40c6 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -2,27 +2,33 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); +/** + * Library that contains all the needed functionalities to operate with the Jobs Queue System + */ class JobsQueueLib { - // - const STATUS_RUNNING = 'running'; - const STATUS_NEW = 'new'; - const STATUS_DONE = 'done'; - - // - const PARAM_JOB_TYPE = 'jobType'; - const PARAM_JOB_STATUS = 'jobStatus'; - const PARAM_JOB_CREATION_TIME = 'jobCreatinTime'; - - // + // Job types + // SAP const JOB_TYPE_SAP_STAMMDATEN_UPDATE = 'SAPStammdatenUpdate'; const JOB_TYPE_SAP_PAYMENT = 'SAPPayment'; + // DVUH const JOB_TYPE_OEH_PAYMENT = 'OEHPayment'; + // Job statuses + const STATUS_NEW = 'new'; + const STATUS_RUNNING = 'running'; + const STATUS_DONE = 'done'; + const STATUS_FAILED = 'failed'; + + // Parameter names + const PARAM_JOB_TYPE = 'type'; + const PARAM_JOB_STATUS = 'status'; + const PARAM_JOBS = 'jobs'; + private $_ci; // CI instance /** - * Construct + * Constructor */ public function __construct($authenticate = true) { diff --git a/application/models/system/JobsQueue_model.php b/application/models/system/JobsQueue_model.php new file mode 100644 index 000000000..e35b45cb3 --- /dev/null +++ b/application/models/system/JobsQueue_model.php @@ -0,0 +1,15 @@ +dbTable = 'system.tbl_jobsqueue'; + $this->pk = 'jobid'; + } +} diff --git a/application/views/system/jq/jobsQueueViewer.php b/application/views/system/jq/jobsQueueViewer.php new file mode 100644 index 000000000..6d92d610b --- /dev/null +++ b/application/views/system/jq/jobsQueueViewer.php @@ -0,0 +1,47 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Jobs Queue Viewer', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'tablesorter' => true, + 'ajaxlib' => true, + 'filterwidget' => true, + 'navigationwidget' => true, + 'phrases' => array( + 'global' => array('mailAnXversandt'), + 'ui' => array('bitteEintragWaehlen') + ), + 'customCSSs' => 'public/css/sbadmin2/tablesort_bootstrap.css', + 'customJSs' => array('public/js/bootstrapper.js') + ) + ); +?> + + +
+ + widgetlib->widget('NavigationWidget'); ?> + +
+
+
+
+ +
+
+
+ load->view('system/jq/jobsQueueViewerData.php'); ?> +
+
+
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/system/jq/jobsQueueViewerData.php b/application/views/system/jq/jobsQueueViewerData.php new file mode 100644 index 000000000..be09e0baf --- /dev/null +++ b/application/views/system/jq/jobsQueueViewerData.php @@ -0,0 +1,67 @@ + ' + SELECT jq.jobid AS "JobId", + jq.creationtime AS "CreationTime", + jq.type AS "Type", + jq.status AS "Status", + jq.starttime AS "StartTime", + jq.endtime AS "EndTime", + jq.insertvon AS "UserService" + FROM system.tbl_jobsqueue jq + ORDER BY jq.creationtime DESC, jq.starttime DESC, jq.endtime DESC + ', + 'requiredPermissions' => 'admin', + 'datasetRepresentation' => 'tablesorter', + 'columnsAliases' => array( + 'Job id', + 'Creation time', + 'Type', + 'Status', + 'Start time', + 'End time', + 'User/Service' + ), + 'formatRow' => function($datasetRaw) { + + $datasetRaw->CreationTime = date_format(date_create($datasetRaw->CreationTime), 'd.m.Y H:i:s'); + $datasetRaw->StartTime = date_format(date_create($datasetRaw->StartTime), 'd.m.Y H:i:s'); + $datasetRaw->EndTime = date_format(date_create($datasetRaw->EndTime), 'd.m.Y H:i:s'); + + return $datasetRaw; + }, + 'markRow' => function($datasetRaw) { + + $mark = ''; + + if ($datasetRaw->Status == 'Failed') + { + $mark = 'text-red'; + } + + if ($datasetRaw->Status == 'Done') + { + $mark = 'text-green'; + } + + if ($datasetRaw->Status == 'Running') + { + $mark = 'text-orange'; + } + + if ($datasetRaw->Status == 'New') + { + $mark = 'text-info'; + } + + return $mark; + } + ); + + $filterWidgetArray['app'] = 'core'; + $filterWidgetArray['datasetName'] = 'jq'; + $filterWidgetArray['filter_id'] = $this->input->get('filter_id'); + + echo $this->widgetlib->widget('FilterWidget', $filterWidgetArray); +?> diff --git a/application/views/system/logs/logsViewer.php b/application/views/system/logs/logsViewer.php index 96790b479..86423006b 100644 --- a/application/views/system/logs/logsViewer.php +++ b/application/views/system/logs/logsViewer.php @@ -2,7 +2,7 @@ $this->load->view( 'templates/FHC-Header', array( - 'title' => 'Logs viewer', + 'title' => 'Logs Viewer', 'jquery' => true, 'jqueryui' => true, 'bootstrap' => true, @@ -32,7 +32,7 @@
diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 623ea7ac7..0440ee5ff 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3842,6 +3842,134 @@ if ($result = $db->db_query("SELECT 1 FROM pg_class WHERE relname = 'unq_idx_abl } } +// Creates table system.tbl_jobstatuses if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobstatuses ( + status character varying NOT NULL + ); + + COMMENT ON TABLE system.tbl_jobstatuses IS \'All possible job statuses\'; + COMMENT ON COLUMN system.tbl_jobstatuses.status IS \'Job status value and primary key\'; + + ALTER TABLE ONLY system.tbl_jobstatuses ADD CONSTRAINT pk_jobstatuses PRIMARY KEY (status); + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobstatuses: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobstatuses table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobstatuses TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobstatuses: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobstatuses'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobstatuses TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobstatuses: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobstatuses'; +} + +// Creates table system.tbl_jobtypes if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtypes LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobtypes ( + type character varying(256) NOT NULL, + description text NOT NULL + ); + + COMMENT ON TABLE system.tbl_jobtypes IS \'All possible job types\'; + COMMENT ON COLUMN system.tbl_jobtypes.type IS \'Job type value and primary key\'; + COMMENT ON COLUMN system.tbl_jobtypes.description IS \'Job type description\'; + + ALTER TABLE ONLY system.tbl_jobtypes ADD CONSTRAINT pk_jobtypes PRIMARY KEY (type); + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobtypes: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobtypes table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobtypes TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtypes: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobtypes'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobtypes TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtypes: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobtypes'; +} + +// Creates table system.tbl_jobsqueue if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobsqueue ( + jobid integer NOT NULL, + type character varying(256) NOT NULL, + creationtime timestamp without time zone DEFAULT now(), + status character varying(64) NOT NULL, + input jsonb, + output jsonb, + starttime timestamp without time zone, + endtime timestamp without time zone, + insertvon character varying(32), + insertamum timestamp without time zone DEFAULT now() + ); + + COMMENT ON TABLE system.tbl_jobsqueue IS \'Table to schedule/manage the jobs queue\'; + COMMENT ON COLUMN system.tbl_jobsqueue.jobid IS \'Primary key\'; + COMMENT ON COLUMN system.tbl_jobsqueue.type IS \'Job type\'; + COMMENT ON COLUMN system.tbl_jobsqueue.creationtime IS \'Job creation timestamp\'; + COMMENT ON COLUMN system.tbl_jobsqueue.status IS \'Job current status\'; + COMMENT ON COLUMN system.tbl_jobsqueue.input IS \'Job input in JSON format\'; + COMMENT ON COLUMN system.tbl_jobsqueue.output IS \'Job output in JSON format\'; + COMMENT ON COLUMN system.tbl_jobsqueue.starttime IS \'Job start timestamp\'; + COMMENT ON COLUMN system.tbl_jobsqueue.endtime IS \'Job end timestamp\'; + COMMENT ON COLUMN system.tbl_jobsqueue.insertvon IS \'User/Service who/that inserted this record\'; + COMMENT ON COLUMN system.tbl_jobsqueue.insertamum IS \'Record insert time stamp\'; + + CREATE SEQUENCE system.seq_jobsqueue_jobid + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + ALTER SEQUENCE system.seq_jobsqueue_jobid OWNED BY system.tbl_jobsqueue.jobid; + + ALTER TABLE ONLY system.tbl_jobsqueue ALTER COLUMN jobid SET DEFAULT nextval(\'system.seq_jobsqueue_jobid\'::regclass); + + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT pk_jobsqueue PRIMARY KEY (jobid); + + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT fk_jobsqueue_status FOREIGN KEY (status) REFERENCES system.tbl_jobstatuses(status) ON UPDATE CASCADE ON DELETE RESTRICT; + + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT fk_jobsqueue_type FOREIGN KEY (type) REFERENCES system.tbl_jobtypes(type) ON UPDATE CASCADE ON DELETE RESTRICT; + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobsqueue: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobsqueue table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobsqueue TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobsqueue: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobsqueue'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobsqueue TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobsqueue: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobsqueue'; +} + // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -4100,6 +4228,9 @@ $tabellen=array( "system.tbl_log" => array("log_id","person_id","zeitpunkt","app","oe_kurzbz","logtype_kurzbz","logdata","insertvon","taetigkeit_kurzbz"), "system.tbl_logtype" => array("logtype_kurzbz", "data_schema"), "system.tbl_filters" => array("filter_id","app","dataset_name","filter_kurzbz","person_id","description","sort","default_filter","filter","oe_kurzbz","statistik_kurzbz"), + "system.tbl_jobsqueue" => array("jobid", "type", "creationtime", "status", "input", "output", "starttime", "endtime", "insertvon", "insertamum"), + "system.tbl_jobstatuses" => array("status"), + "system.tbl_jobtypes" => array("type", "description"), "system.tbl_phrase" => array("phrase_id","app","phrase","insertamum","insertvon","category"), "system.tbl_phrasentext" => array("phrasentext_id","phrase_id","sprache","orgeinheit_kurzbz","orgform_kurzbz","text","description","insertamum","insertvon"), "system.tbl_rolle" => array("rolle_kurzbz","beschreibung"), diff --git a/system/filtersupdate.php b/system/filtersupdate.php index d05a39aab..9c648a572 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -631,6 +631,37 @@ $filters = array( } ', 'oe_kurzbz' => null, + ), + array( + 'app' => 'core', + 'dataset_name' => 'jq', + 'filter_kurzbz' => 'lastHour', + 'description' => '{Last hour queued jobs}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "All jobs queued in the last hour", + "columns": [ + {"name": "JobId"}, + {"name": "CreationTime"}, + {"name": "Type"}, + {"name": "Status"}, + {"name": "StartTime"}, + {"name": "EndTime"}, + {"name": "UserService"} + ], + "filters": [ + { + "name": "CreationTime", + "operation": "lt", + "condition": "1", + "option": "hours" + } + ] + } + ', + 'oe_kurzbz' => null, ) ); From 3bfe1cdeea79322d4d0c4b52264d24ddd2307250 Mon Sep 17 00:00:00 2001 From: Paolo Date: Thu, 5 Mar 2020 18:48:26 +0100 Subject: [PATCH 003/162] - Fixed messages and comments in PermissionLib - JobsQueueManager->addNewJobsToQueue now checks permission to write new jobs in the queue - Added statuses for system.tbl_jobstatuses in system/dbupdate_3.3.php - Added permission access type (read/write) in configuration file application/config/jqm.php --- application/config/jqm.php | 13 +++++-------- .../system/jq/JobsQueueManager.php | 19 +++++++++++++++++-- application/libraries/PermissionLib.php | 6 +++--- system/dbupdate_3.3.php | 5 +++++ 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/application/config/jqm.php b/application/config/jqm.php index 579fc6987..77d9bb35d 100644 --- a/application/config/jqm.php +++ b/application/config/jqm.php @@ -2,15 +2,12 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); -// White list of permissions that are able to store a spcific job type in database +// White list of permissions (write mode have to be set) that are able to store a specific job type in database $config['job_type_permissions_white_list'] = array( 'SAPStammdatenUpdate' => array( - 'admin' + 'admin:rw', + 'developer:rw' ), - 'OEHPayment' => array( - 'admin' - ), - 'SAPPayment' => array( - 'admin' - ) + 'OEHPayment' => 'developer:rw', + 'SAPPayment' => 'developer:rw' ); diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php index 4e82ff44e..9275fa845 100644 --- a/application/controllers/system/jq/JobsQueueManager.php +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -8,6 +8,9 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); */ class JobsQueueManager extends Auth_Controller { + // Config entry name for White list of permissions... + const JOB_TYPE_PERMISSIONS_WHITE_LIST = 'job_type_permissions_white_list'; + /** * Constructor */ @@ -15,7 +18,7 @@ class JobsQueueManager extends Auth_Controller { parent::__construct( array( - 'getJobsByType' => 'admin:r', + 'getLastJobs' => 'admin:r', 'addNewJobsToQueue' => 'admin:rw' ) ); @@ -46,6 +49,18 @@ class JobsQueueManager extends Auth_Controller $type = $this->input->post(JobsQueueLib::PARAM_JOB_TYPE); $jobs = $this->input->post(JobsQueueLib::PARAM_JOBS); - $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + // Loads permission lib + $this->load->library('PermissionLib'); + + // Checks if the caller has the permissions to add new jobs with the given type in the queue + if (!$this->permissionlib->isEntitled($this->config->item(self::JOB_TYPE_PERMISSIONS_WHITE_LIST), $type)) + { + // Permissions NOT valid + $this->outputJsonError('You are not allowed to access to this content'); + } + else // Otherwise call JobsQueueLib library + { + $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + } } } diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index 348c8b87b..09f89abee 100644 --- a/application/libraries/PermissionLib.php +++ b/application/libraries/PermissionLib.php @@ -147,7 +147,7 @@ class PermissionLib $accessType = ''; - // Checks if the required access type is compliant with the HTTP method (GET => r, POST => w) + // Set the access type if (strpos($requiredAccessType, PermissionLib::READ_RIGHT) !== false) { $accessType = PermissionLib::SELECT_RIGHT; // S @@ -184,12 +184,12 @@ class PermissionLib } else { - show_error('The given permission array does not contain the called method or is not correctly set'); + show_error('The given permission array does not contain the given method or is not correctly set'); } } else { - show_error('You must give the permissions array as parameter to the constructor of the controller'); + show_error('The given permissions is not a valid array or it is an empty one'); } return $checkPermissions; diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 0440ee5ff..42a1b531a 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3853,6 +3853,11 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) COMMENT ON COLUMN system.tbl_jobstatuses.status IS \'Job status value and primary key\'; ALTER TABLE ONLY system.tbl_jobstatuses ADD CONSTRAINT pk_jobstatuses PRIMARY KEY (status); + + INSERT INTO system.tbl_jobstatuses(status) VALUES('new'); + INSERT INTO system.tbl_jobstatuses(status) VALUES('running'); + INSERT INTO system.tbl_jobstatuses(status) VALUES('done'); + INSERT INTO system.tbl_jobstatuses(status) VALUES('failed'); '; if (!$db->db_query($qry)) From ba566ab459d6e752b09636cb64fad85749c1eddf Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:13:25 +0100 Subject: [PATCH 004/162] Added new models system/JobStatuses_model and system/JobTypes_model --- application/models/system/JobStatuses_model.php | 16 ++++++++++++++++ application/models/system/JobTypes_model.php | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 application/models/system/JobStatuses_model.php create mode 100644 application/models/system/JobTypes_model.php diff --git a/application/models/system/JobStatuses_model.php b/application/models/system/JobStatuses_model.php new file mode 100644 index 000000000..82d1ee31b --- /dev/null +++ b/application/models/system/JobStatuses_model.php @@ -0,0 +1,16 @@ +dbTable = 'system.tbl_jobstatuses'; + $this->pk = 'status'; + $this->hasSequence = false; + } +} diff --git a/application/models/system/JobTypes_model.php b/application/models/system/JobTypes_model.php new file mode 100644 index 000000000..1d578bcab --- /dev/null +++ b/application/models/system/JobTypes_model.php @@ -0,0 +1,16 @@ +dbTable = 'system.tbl_jobtypes'; + $this->pk = 'type'; + $this->hasSequence = false; + } +} From d2e7336f2ce6b91246a065158fcebe0783e6312e Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:14:11 +0100 Subject: [PATCH 005/162] Granted permission to user fhcomplete and vilesci for sequence seq_jobsqueue_jobid --- system/dbupdate_3.3.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 42a1b531a..5bccd5e1a 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3950,6 +3950,9 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) ALTER TABLE ONLY system.tbl_jobsqueue ALTER COLUMN jobid SET DEFAULT nextval(\'system.seq_jobsqueue_jobid\'::regclass); + GRANT SELECT, UPDATE ON SEQUENCE system.seq_jobsqueue_jobid TO vilesci; + GRANT SELECT, UPDATE ON SEQUENCE system.seq_jobsqueue_jobid TO fhcomplete; + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT pk_jobsqueue PRIMARY KEY (jobid); ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT fk_jobsqueue_status FOREIGN KEY (status) REFERENCES system.tbl_jobstatuses(status) ON UPDATE CASCADE ON DELETE RESTRICT; From e92880b79a76d0003968c4e82ff88aa1e9721da5 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:15:10 +0100 Subject: [PATCH 006/162] - Added new private methods _checkPermissions and _convertJobs to controller system/jq/JobsQueueManager - Added new public method updateJobsQueue to controller system/jq/JobsQueueManager - system/jq/JobsQueueManager->getLastJobs now checks permissions - Added new public method updateJobsQueue to JQW_Controller - Less redundant constansts in Library JobsQueueLib - JobsQueueLib constructor now loads models JobsQueueModel, JobTypesModel and JobStatusesModel - Added new public methods getLastJobs, addNewJobsToQueue and updateJobsQueue to JobsQueueLib - Added new private methods _checkNewJobStructure, _checkUpdateJobStructure, _checkJobType, _checkJobStatus, _inArray, _dropNotAllowedPropertiesNewJob and _dropNotAllowedPropertiesUpdateJob to --- .../system/jq/JobsQueueManager.php | 83 +++++- application/core/JQW_Controller.php | 14 + application/libraries/JobsQueueLib.php | 255 ++++++++++++++++-- 3 files changed, 324 insertions(+), 28 deletions(-) diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php index 9275fa845..b6e4efe29 100644 --- a/application/controllers/system/jq/JobsQueueManager.php +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -10,6 +10,8 @@ class JobsQueueManager extends Auth_Controller { // Config entry name for White list of permissions... const JOB_TYPE_PERMISSIONS_WHITE_LIST = 'job_type_permissions_white_list'; + // Parameter names + const PARAM_JOBS = 'jobs'; /** * Constructor @@ -19,12 +21,15 @@ class JobsQueueManager extends Auth_Controller parent::__construct( array( 'getLastJobs' => 'admin:r', - 'addNewJobsToQueue' => 'admin:rw' + 'addNewJobsToQueue' => 'admin:rw', + 'updateJobsQueue' => 'admin:rw' ) ); // Loads JobsQueueLib $this->load->library('JobsQueueLib'); + // Loads permission lib + $this->load->library('PermissionLib'); } //------------------------------------------------------------------------------------------------------------------ @@ -35,7 +40,9 @@ class JobsQueueManager extends Auth_Controller */ public function getLastJobs() { - $type = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); + $type = $this->input->get(JobsQueueLib::PROPERTY_TYPE); + + $this->_checkPermissions($type); $this->outputJson($this->jobsqueuelib->getLastJobs($type)); } @@ -46,21 +53,75 @@ class JobsQueueManager extends Auth_Controller */ public function addNewJobsToQueue() { - $type = $this->input->post(JobsQueueLib::PARAM_JOB_TYPE); - $jobs = $this->input->post(JobsQueueLib::PARAM_JOBS); + $type = $this->input->post(JobsQueueLib::PROPERTY_TYPE); + $jobs = $this->input->post(self::PARAM_JOBS); - // Loads permission lib - $this->load->library('PermissionLib'); + $this->_checkPermissions($type); + // Otherwise convert jobs from json to php and call JobsQueueLib library + $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $this->_convertJobs($jobs))); + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + public function updateJobsQueue() + { + $type = $this->input->post(JobsQueueLib::PROPERTY_TYPE); + $jobs = $this->input->post(self::PARAM_JOBS); + + $this->_checkPermissions($type); + + // Otherwise convert jobs from json to php and call JobsQueueLib library + $this->outputJson($this->jobsqueuelib->updateJobsQueue($type, $this->_convertJobs($jobs))); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * + */ + private function _checkPermissions($type) + { // Checks if the caller has the permissions to add new jobs with the given type in the queue if (!$this->permissionlib->isEntitled($this->config->item(self::JOB_TYPE_PERMISSIONS_WHITE_LIST), $type)) { // Permissions NOT valid - $this->outputJsonError('You are not allowed to access to this content'); - } - else // Otherwise call JobsQueueLib library - { - $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + $this->terminateWithJsonError('You are not allowed to access to this content'); } } + + /** + * + */ + private function _convertJobs($jobs) + { + if (isEmptyArray($jobs)) return null; // if not a valid array then return null + + $convertedJobsArray = array(); // returned values + + // Loops through all the provided jobs + foreach ($jobs as $job) + { + $tmpObj = json_decode($job); // Try to decode json to php + + // If decode was a success + if ($tmpObj != null) + { + $convertedJobsArray[] = $tmpObj; // then store the decoded object in the result array + } + else // otherwise + { + // Create a new object and store the error message in it + $tmpObj = new stdClass(); + $tmpObj->{JobsQueueLib::PROPERTY_ERROR} = 'A not valid json was provided'; + + $convertedJobsArray[] = $tmpObj; // store this object into the result array + } + } + + return $convertedJobsArray; + } } diff --git a/application/core/JQW_Controller.php b/application/core/JQW_Controller.php index 616eaf4fd..c6d2362e3 100644 --- a/application/core/JQW_Controller.php +++ b/application/core/JQW_Controller.php @@ -60,4 +60,18 @@ abstract class JQW_Controller extends JOB_Controller return $result; } + + /** + * Updates jobs already present in the jobs queue + * jobs is an array of job objects + */ + protected function updateJobsQueue($type, $jobs) + { + $result = $this->jobsqueuelib->updateJobsQueue($type, $jobs); + + // If an error occurred then log it in database + if (isError($result)) $this->logError(getError($result), $type); + + return $result; + } } diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index fe73b40c6..ac0e38786 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -7,23 +7,22 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); */ class JobsQueueLib { - // Job types - // SAP - const JOB_TYPE_SAP_STAMMDATEN_UPDATE = 'SAPStammdatenUpdate'; - const JOB_TYPE_SAP_PAYMENT = 'SAPPayment'; - // DVUH - const JOB_TYPE_OEH_PAYMENT = 'OEHPayment'; - // Job statuses const STATUS_NEW = 'new'; const STATUS_RUNNING = 'running'; const STATUS_DONE = 'done'; const STATUS_FAILED = 'failed'; - // Parameter names - const PARAM_JOB_TYPE = 'type'; - const PARAM_JOB_STATUS = 'status'; - const PARAM_JOBS = 'jobs'; + // Job object properties + const PROPERTY_JOBID = 'jobid'; + const PROPERTY_CREATIONTIME = 'creationtime'; + const PROPERTY_TYPE = 'type'; + const PROPERTY_STATUS = 'status'; + const PROPERTY_INPUT = 'input'; + const PROPERTY_OUTPUT = 'output'; + const PROPERTY_START_TIME = 'starttime'; + const PROPERTY_END_TIME = 'endtime'; + const PROPERTY_ERROR = 'error'; private $_ci; // CI instance @@ -34,29 +33,251 @@ class JobsQueueLib { // Gets CI instance $this->_ci =& get_instance(); + + // Loads JQM configuration + $this->_ci->config->load('jqm'); + + // Loads all needed models + $this->_ci->load->model('system/JobsQueue_model', 'JobsQueueModel'); + $this->_ci->load->model('system/JobTypes_model', 'JobTypesModel'); + $this->_ci->load->model('system/JobStatuses_model', 'JobStatusesModel'); } //------------------------------------------------------------------------------------------------------------------ // Public methods /** - * + * To get all the most recently added jobs using the given job type */ - public function getJobsByType() + public function getLastJobs($type) { + $this->_ci->JobsQueueModel->resetQuery(); + + $this->_ci->JobsQueueModel->addOrder('creationtime', 'DESC'); + + return $this->_ci->JobsQueueModel->loadWhere(array('status' => self::STATUS_NEW, 'type' => $type)); } /** - * + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects */ - public function addNewJobsToQueue() + public function addNewJobsToQueue($type, $jobs) { + // Checks parameters + if (isEmptyString($type)) return error('The provided type parameter is not a valid string'); + if (isEmptyArray($jobs)) return error('The provided jobs parameter is not a valid array'); + + // Get all the job types + $dbResult = $this->_ci->JobTypesModel->load(); + if (isError($dbResult)) return $dbResult; + $types = getData($dbResult); + + // If the given type is not present in database + if (!$this->_checkJobType($type, $types)) return error('The provided type parameter is not valid'); + + $results = $jobs; // returned values + $errorOccurred = false; // very optimistic + + // Get all the job statuses + $dbResult = $this->_ci->JobStatusesModel->load(); + if (isError($dbResult)) return $dbResult; + $statuses = getData($dbResult); + + // Loops through all the provided jobs + foreach ($results as $job) + { + // If the structure of the job object is valid AND the type is valid AND the status is valid + if ($this->_checkNewJobStructure($job) && $this->_checkJobStatus($job, $statuses)) + { + $this->_dropNotAllowedPropertiesNewJob($job); // remove the black listed properties from this object + + $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! + + // Try to insert the single job into database + $dbResult = $this->_ci->JobsQueueModel->insert($job); + + // If an error occurred during while inserting in database + if (isError($dbResult)) + { + $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + else // otherwise + { + $job->{self::PROPERTY_JOBID} = getData($dbResult); // get the jobid and store it in job object + } + } + else // otherwise + { + $errorOccurred = true; // set error occurred flag + } + } + + // If an error occurred then returns the results in an error object + if ($errorOccurred) return error($results); + + return success($results); // otherwise return results in a success object } /** - * + * Updates jobs already present in the jobs queue + * jobs is an array of job objects */ - public function getJobsByStatus() + public function updateJobsQueue($type, $jobs) { + // Checks parameters + if (isEmptyArray($jobs)) return error('The provided jobs parameter is not a valid array'); + + $results = $jobs; // returned values + $errorOccurred = false; // very optimistic + + // Get all the job statuses + $dbResult = $this->_ci->JobStatusesModel->load(); + if (isError($dbResult)) return $dbResult; + $statuses = getData($dbResult); + + // Loops through all the provided jobs + foreach ($results as $job) + { + // If the structure of the job object is valid + if ($this->_checkUpdateJobStructure($job) && $this->_checkJobStatus($job, $statuses)) + { + $this->_dropNotAllowedPropertiesUpdateJob($job); // remove the black listed properties from this object + + $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! + + // Try to update the single job into database + $dbResult = $this->_ci->JobsQueueModel->update($job->{self::PROPERTY_JOBID}, (array)$job); + + // If an error occurred during while updating in database + if (isError($dbResult)) + { + $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + } + else // otherwise + { + $errorOccurred = true; // set error occurred flag + } + } + + // If an error occurred then returns the results in an error object + if ($errorOccurred) return error($results); + + return success($results); // otherwise return results in a success object + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks the job object structure when needed for insert + */ + private function _checkNewJobStructure(&$job) + { + // If job is a valid object and contains the required properties AND does NOT already contain the property error + if (is_object($job) + && property_exists($job, self::PROPERTY_STATUS) + && !property_exists($job, self::PROPERTY_ERROR)) + { + return true; // it is valid! + } + + // If not object then object it! + if (!is_object($job)) $job = new stdClass(); + + // If an error property was not already previously stored then store an error message in job object + if (!property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid'; + } + + return false; // better sorry than wrong + } + + /** + * Checks the job object structure when needed for update + */ + private function _checkUpdateJobStructure(&$job) + { + // If job is a valid object + if (is_object($job) && property_exists($job, self::PROPERTY_JOBID)) return true; // it is valid! + + // If not object then object it! + if (!is_object($job)) $job = new stdClass(); + + // If an error property was not already previously stored then store an error message in job object + if (!property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid'; + } + + return false; // better sorry than wrong + } + + /** + * Checks if the given job contains a valid type + */ + private function _checkJobType($type, $types) + { + return $this->_inArray($type, $types, self::PROPERTY_TYPE); + } + + /** + * Checks if the given job contains a valid status + */ + private function _checkJobStatus(&$job, $statuses) + { + $found = $this->_inArray($job->{self::PROPERTY_STATUS}, $statuses, self::PROPERTY_STATUS); + + // No status was not found and does NOT already contain the property error + if (!$found && !property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The provided status of this job is not valid'; // store the error message in the object + } + + return $found; + } + + /** + * Search in an array the given value + * The elements of the given array are objects + * The given value is compared with the property specified by the $propertyName parameter of each object of the given array + */ + private function _inArray($value, $array, $propertyName) + { + $found = false; + + foreach ($array as $element) + { + if ($value == $element->{$propertyName}) + { + $found = true; + break; + } + } + + return $found; + } + + /** + * Drop not allowed properties from the given job + */ + private function _dropNotAllowedPropertiesNewJob(&$job) + { + unset($job->{self::PROPERTY_JOBID}); + unset($job->{self::PROPERTY_CREATIONTIME}); + unset($job->{self::PROPERTY_TYPE}); + } + + /** + * Drop not allowed properties from the given job + */ + private function _dropNotAllowedPropertiesUpdateJob(&$job) + { + unset($job->{self::PROPERTY_CREATIONTIME}); + unset($job->{self::PROPERTY_TYPE}); } } From 6b0bf895928e2e4ddb26af8f8e67ff23b8f7d4c8 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:25:52 +0100 Subject: [PATCH 007/162] Removed load config loads in JobsQueueLib --- application/libraries/JobsQueueLib.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index ac0e38786..ea79e099e 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -34,9 +34,6 @@ class JobsQueueLib // Gets CI instance $this->_ci =& get_instance(); - // Loads JQM configuration - $this->_ci->config->load('jqm'); - // Loads all needed models $this->_ci->load->model('system/JobsQueue_model', 'JobsQueueModel'); $this->_ci->load->model('system/JobTypes_model', 'JobTypesModel'); From 8363f0d26c6bc76d1753310c034d4406ddce6468 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:30:52 +0100 Subject: [PATCH 008/162] Fixed marker in JobsQueueViewer --- application/controllers/system/jq/JobsQueueViewer.php | 3 +++ application/views/system/jq/jobsQueueViewerData.php | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/application/controllers/system/jq/JobsQueueViewer.php b/application/controllers/system/jq/JobsQueueViewer.php index 7e8760209..2698d79d1 100644 --- a/application/controllers/system/jq/JobsQueueViewer.php +++ b/application/controllers/system/jq/JobsQueueViewer.php @@ -25,6 +25,9 @@ class JobsQueueViewer extends Auth_Controller // Loads WidgetLib $this->load->library('WidgetLib'); + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + // Loads phrases system $this->loadPhrases( array( diff --git a/application/views/system/jq/jobsQueueViewerData.php b/application/views/system/jq/jobsQueueViewerData.php index be09e0baf..023ec5406 100644 --- a/application/views/system/jq/jobsQueueViewerData.php +++ b/application/views/system/jq/jobsQueueViewerData.php @@ -35,22 +35,22 @@ $mark = ''; - if ($datasetRaw->Status == 'Failed') + if ($datasetRaw->Status == JobsQueueLib::STATUS_FAILED) { $mark = 'text-red'; } - if ($datasetRaw->Status == 'Done') + if ($datasetRaw->Status == JobsQueueLib::STATUS_DONE) { $mark = 'text-green'; } - if ($datasetRaw->Status == 'Running') + if ($datasetRaw->Status == JobsQueueLib::STATUS_RUNNING) { $mark = 'text-orange'; } - if ($datasetRaw->Status == 'New') + if ($datasetRaw->Status == JobsQueueLib::STATUS_NEW) { $mark = 'text-info'; } From 4d1dbdfae98b4a51fd22613bbcf6cb7dcad0154a Mon Sep 17 00:00:00 2001 From: Paolo Date: Thu, 12 Mar 2020 18:51:26 +0100 Subject: [PATCH 009/162] - Added new model system/JobTriggers_model - Loads jqm configuration in controller system/jq/JobsQueueManager - Added new table system.tbl_jobtriggers to system/dbupdate_3.3.php - Added new privacy method _addNewTriggeredJobToQueue to JobsQueueLib - JobsQueueLib is called by addNewJobsToQueue and updateJobsQueue --- .../system/jq/JobsQueueManager.php | 3 + application/libraries/JobsQueueLib.php | 64 +++++++++++++++++-- .../models/system/JobTriggers_model.php | 32 ++++++++++ system/dbupdate_3.3.php | 56 ++++++++++++++-- 4 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 application/models/system/JobTriggers_model.php diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php index b6e4efe29..e72607675 100644 --- a/application/controllers/system/jq/JobsQueueManager.php +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -26,6 +26,9 @@ class JobsQueueManager extends Auth_Controller ) ); + // Loading config file jqm + $this->config->load('jqm'); + // Loads JobsQueueLib $this->load->library('JobsQueueLib'); // Loads permission lib diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index ea79e099e..9aafc808d 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -38,6 +38,7 @@ class JobsQueueLib $this->_ci->load->model('system/JobsQueue_model', 'JobsQueueModel'); $this->_ci->load->model('system/JobTypes_model', 'JobTypesModel'); $this->_ci->load->model('system/JobStatuses_model', 'JobStatusesModel'); + $this->_ci->load->model('system/JobTriggers_model', 'JobTriggersModel'); } //------------------------------------------------------------------------------------------------------------------ @@ -92,17 +93,21 @@ class JobsQueueLib $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! // Try to insert the single job into database - $dbResult = $this->_ci->JobsQueueModel->insert($job); + $dbNewJobResult = $this->_ci->JobsQueueModel->insert($job); // If an error occurred during while inserting in database - if (isError($dbResult)) + if (isError($dbNewJobResult)) { - $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $job->{self::PROPERTY_ERROR} = getError($dbNewJobResult); // retrieve the cause and store it in job object $errorOccurred = true; // set error occurred flag } else // otherwise { - $job->{self::PROPERTY_JOBID} = getData($dbResult); // get the jobid and store it in job object + $job->{self::PROPERTY_JOBID} = getData($dbNewJobResult); // get the jobid and store it in job object + + $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue($type, $job, array(self::STATUS_NEW)); + // If an error occurred during while inserting in database + if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; } } else // otherwise @@ -137,6 +142,8 @@ class JobsQueueLib // Loops through all the provided jobs foreach ($results as $job) { + // TODO: find if present in database or not!!! + // If the structure of the job object is valid if ($this->_checkUpdateJobStructure($job) && $this->_checkJobStatus($job, $statuses)) { @@ -153,6 +160,16 @@ class JobsQueueLib $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object $errorOccurred = true; // set error occurred flag } + else // otherwise + { + $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue( + $type, + $job, + array($job->status) + ); + // If an error occurred during while inserting in database + if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; + } } else // otherwise { @@ -277,4 +294,43 @@ class JobsQueueLib unset($job->{self::PROPERTY_CREATIONTIME}); unset($job->{self::PROPERTY_TYPE}); } + + /** + * Add e new triggered job to the jobs queue + * NOTE: + * - In this method there are less checks compared to addNewJobsToQueue method because + * the new jobs that will be added are generate in this method + * - Job ids in this case are not returned, therefore the caller is not going to be informed about these new jobs + */ + private function _addNewTriggeredJobToQueue($type, $job, $triggeredStatuses) + { + // Get all the job trigggers for the given type and for the given statuses + $dbTriggersResult = $this->_ci->JobTriggersModel->getJobtriggersByTypeStatuses($type, $triggeredStatuses); + + // If an error occurred while getting job triggers from database then return it + if (isError($dbTriggersResult)) return $dbTriggersResult; + if (hasData($dbTriggersResult)) // If triggers were retrieved + { + // The output of the trigging job is the input of the trigged job + $triggeredJobInput = null; + if (isset($job->{self::PROPERTY_OUTPUT})) $triggeredJobInput = $job->{self::PROPERTY_OUTPUT}; + + // For each trigger + foreach (getData($dbTriggersResult) as $trigger) + { + $triggeredJob = array( + self::PROPERTY_TYPE => $trigger->following_type, // the new type is the one defined in tbl_jobtriggers + self::PROPERTY_STATUS => self::STATUS_NEW, // new job status is new + self::PROPERTY_INPUT => $triggeredJobInput // new job input + ); + + // Try to insert the single job into database + $dbNewJob = $this->_ci->JobsQueueModel->insert($triggeredJob); + // If an error occurred during while inserting in database + if (isError($dbNewJob)) return $dbNewJob; + } + } + + return success(); // if here then it was a success! + } } diff --git a/application/models/system/JobTriggers_model.php b/application/models/system/JobTriggers_model.php new file mode 100644 index 000000000..176b4f5b1 --- /dev/null +++ b/application/models/system/JobTriggers_model.php @@ -0,0 +1,32 @@ +dbTable = 'system.tbl_jobtriggers'; + $this->pk = array('type', 'status', 'followingType'); + $this->hasSequence = false; + } + + /** + * + */ + public function getJobtriggersByTypeStatuses($type, $triggeredStatuses) + { + $query = 'SELECT jt.type, + jt.status, + jt.following_type + FROM system.tbl_jobtriggers jt + WHERE jt.type = ? + AND jt.status IN ? + ORDER BY jt.type, jt.status'; + + return $this->execQuery($query, array($type, $triggeredStatuses)); + } +} diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 5bccd5e1a..b54b28373 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3846,7 +3846,7 @@ if ($result = $db->db_query("SELECT 1 FROM pg_class WHERE relname = 'unq_idx_abl if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) { $qry = 'CREATE TABLE system.tbl_jobstatuses ( - status character varying NOT NULL + status character varying(64) NOT NULL ); COMMENT ON TABLE system.tbl_jobstatuses IS \'All possible job statuses\'; @@ -3854,10 +3854,10 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) ALTER TABLE ONLY system.tbl_jobstatuses ADD CONSTRAINT pk_jobstatuses PRIMARY KEY (status); - INSERT INTO system.tbl_jobstatuses(status) VALUES('new'); - INSERT INTO system.tbl_jobstatuses(status) VALUES('running'); - INSERT INTO system.tbl_jobstatuses(status) VALUES('done'); - INSERT INTO system.tbl_jobstatuses(status) VALUES('failed'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'new\'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'running\'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'done\'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'failed\'); '; if (!$db->db_query($qry)) @@ -3882,7 +3882,7 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtypes LIMIT 1')) { $qry = 'CREATE TABLE system.tbl_jobtypes ( - type character varying(256) NOT NULL, + type character varying(128) NOT NULL, description text NOT NULL ); @@ -3916,7 +3916,7 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) { $qry = 'CREATE TABLE system.tbl_jobsqueue ( jobid integer NOT NULL, - type character varying(256) NOT NULL, + type character varying(128) NOT NULL, creationtime timestamp without time zone DEFAULT now(), status character varying(64) NOT NULL, input jsonb, @@ -3978,6 +3978,47 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) echo '
Granted privileges to vilesci on system.tbl_jobsqueue'; } +// Creates table system.tbl_jobtriggers if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtriggers LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobtriggers ( + type character varying(128) NOT NULL, + status character varying(64) NOT NULL, + following_type character varying(128) NOT NULL + ); + + COMMENT ON TABLE system.tbl_jobtriggers IS \'Table to manage the job triggers\'; + COMMENT ON COLUMN system.tbl_jobtriggers.type IS \'Job type\'; + COMMENT ON COLUMN system.tbl_jobtriggers.status IS \'Job status\'; + COMMENT ON COLUMN system.tbl_jobtriggers.following_type IS \'New job type\'; + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT pk_jobtriggers PRIMARY KEY (type, status, following_type); + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT fk_jobtriggers_status FOREIGN KEY (status) REFERENCES system.tbl_jobstatuses(status) ON UPDATE CASCADE ON DELETE RESTRICT; + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT fk_jobtriggers_type FOREIGN KEY (type) REFERENCES system.tbl_jobtypes(type) ON UPDATE CASCADE ON DELETE RESTRICT; + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT fk_jobtriggers_following_type FOREIGN KEY (following_type) REFERENCES system.tbl_jobtypes(type) ON UPDATE CASCADE ON DELETE RESTRICT; + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobtriggers: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobtriggers table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobtriggers TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtriggers: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobtriggers'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobtriggers TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtriggers: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobtriggers'; +} + // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -4238,6 +4279,7 @@ $tabellen=array( "system.tbl_filters" => array("filter_id","app","dataset_name","filter_kurzbz","person_id","description","sort","default_filter","filter","oe_kurzbz","statistik_kurzbz"), "system.tbl_jobsqueue" => array("jobid", "type", "creationtime", "status", "input", "output", "starttime", "endtime", "insertvon", "insertamum"), "system.tbl_jobstatuses" => array("status"), + "system.tbl_jobtriggers" => array("type", "status", "following_type"), "system.tbl_jobtypes" => array("type", "description"), "system.tbl_phrase" => array("phrase_id","app","phrase","insertamum","insertvon","category"), "system.tbl_phrasentext" => array("phrasentext_id","phrase_id","sprache","orgeinheit_kurzbz","orgform_kurzbz","text","description","insertamum","insertvon"), From 3ff527b2ad3400fd3329d63a95b9d4b5b045b9cc Mon Sep 17 00:00:00 2001 From: Paolo Date: Wed, 18 Mar 2020 00:56:28 +0100 Subject: [PATCH 010/162] - Added check on property status in private method _checkJobStatus of JobsQueueLib - When updating a job now it is checked if the job is present in the database --- application/libraries/JobsQueueLib.php | 81 ++++++++++++++++---------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index 9aafc808d..2213315f8 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -135,46 +135,59 @@ class JobsQueueLib $errorOccurred = false; // very optimistic // Get all the job statuses - $dbResult = $this->_ci->JobStatusesModel->load(); - if (isError($dbResult)) return $dbResult; - $statuses = getData($dbResult); + $dbResultStatuses = $this->_ci->JobStatusesModel->load(); + if (isError($dbResultStatuses)) return $dbResultStatuses; + $statuses = getData($dbResultStatuses); // Loops through all the provided jobs foreach ($results as $job) { - // TODO: find if present in database or not!!! - - // If the structure of the job object is valid - if ($this->_checkUpdateJobStructure($job) && $this->_checkJobStatus($job, $statuses)) + // Check if the required job is present in the database + $dbResultJobs = $this->_ci->JobsQueueModel->load($job->{self::PROPERTY_JOBID}); + if (isError($dbResultJobs)) { - $this->_dropNotAllowedPropertiesUpdateJob($job); // remove the black listed properties from this object - - $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! - - // Try to update the single job into database - $dbResult = $this->_ci->JobsQueueModel->update($job->{self::PROPERTY_JOBID}, (array)$job); - - // If an error occurred during while updating in database - if (isError($dbResult)) + $job->{self::PROPERTY_ERROR} = getError($dbResultJobs); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + elseif (!hasData($dbResultJobs)) // if no jobs were found + { + $job->{self::PROPERTY_ERROR} = 'The required job is not present'; + $errorOccurred = true; // set error occurred flag + } + else // if a job was found then it could be updated + { + // If the structure of the job object is valid + if ($this->_checkUpdateJobStructure($job) && $this->_checkJobStatus($job, $statuses)) { - $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object - $errorOccurred = true; // set error occurred flag + $this->_dropNotAllowedPropertiesUpdateJob($job); // remove the black listed properties from this object + + $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! + + // Try to update the single job into database + $dbResult = $this->_ci->JobsQueueModel->update($job->{self::PROPERTY_JOBID}, (array)$job); + + // If an error occurred during while updating in database + if (isError($dbResult)) + { + $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + else // otherwise + { + $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue( + $type, + $job, + array($job->status) + ); + // If an error occurred during while inserting in database + if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; + } } else // otherwise { - $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue( - $type, - $job, - array($job->status) - ); - // If an error occurred during while inserting in database - if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; + $errorOccurred = true; // set error occurred flag } } - else // otherwise - { - $errorOccurred = true; // set error occurred flag - } } // If an error occurred then returns the results in an error object @@ -244,7 +257,15 @@ class JobsQueueLib */ private function _checkJobStatus(&$job, $statuses) { - $found = $this->_inArray($job->{self::PROPERTY_STATUS}, $statuses, self::PROPERTY_STATUS); + // If the given job doesn't have the property status then it is not valid + if (!isset($job->{self::PROPERTY_STATUS})) + { + $found = false; + } + else // otherwise test if it valid + { + $found = $this->_inArray($job->{self::PROPERTY_STATUS}, $statuses, self::PROPERTY_STATUS); + } // No status was not found and does NOT already contain the property error if (!$found && !property_exists($job, self::PROPERTY_ERROR)) From 554fb2586a3bc8612f3011c7986e84f628310aac Mon Sep 17 00:00:00 2001 From: Alexei Date: Thu, 30 Apr 2020 21:42:30 +0200 Subject: [PATCH 011/162] person/Benutzer_model: - added methods for generating alias and checking if alias exists ressource/Mitarbeiter_model: - added method getPersonal --- application/models/person/Benutzer_model.php | 49 +++++++++++++++++++ .../models/ressource/Mitarbeiter_model.php | 41 ++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/application/models/person/Benutzer_model.php b/application/models/person/Benutzer_model.php index a21811bb4..b2bc0f027 100644 --- a/application/models/person/Benutzer_model.php +++ b/application/models/person/Benutzer_model.php @@ -33,4 +33,53 @@ class Benutzer_model extends DB_Model return $this->execQuery($sql, array($person_id, $oe_kurzbz)); } + + /** + * Checks if alias exists + * @param $alias + */ + public function aliasExists($alias) + { + $this->addSelect('1'); + $result = $this->loadWhere(array('alias' => $alias)); + + if (!isError($result)) + { + if (hasData($result)) + { + $result = success(array(true)); + } + else if (!hasData($result)) + { + $result = success(array(false)); + } + } + + return $result; + } + + /** + * Generates alias for a uid + * @param $uid + * @return array the alias + */ + public function generateAlias($uid) + { + $aliasres = ''; + $this->addSelect('vorname, nachname'); + $this->addJoin('public.tbl_person', 'person_id'); + $nameresult = $this->loadWhere(array('uid' => $uid)); + + if (hasData($nameresult)) + { + $aliasdata = getData($nameresult); + $alias = mb_strtolower($aliasdata[0]->vorname).'.'.mb_strtolower($aliasdata[0]->nachname); + $aliasexists = $this->aliasExists($alias); + + if (hasData($aliasexists) && !getData($aliasexists)[0]) + $aliasres = $alias; + + } + return success($aliasres); + } } diff --git a/application/models/ressource/Mitarbeiter_model.php b/application/models/ressource/Mitarbeiter_model.php index ccaeacd0d..523a69fa1 100644 --- a/application/models/ressource/Mitarbeiter_model.php +++ b/application/models/ressource/Mitarbeiter_model.php @@ -40,4 +40,45 @@ class Mitarbeiter_model extends DB_Model return success(false); } } + + /** + * Laedt das Personal + * + * @param $fix wenn true werden nur fixangestellte geladen + * @param $aktiv wenn true werden nur aktive geladen, wenn false dann nur inaktve, wenn null dann alle + * @param $verwendung wenn true werden alle geladen die eine BIS-Verwendung eingetragen haben + * @return array + */ + public function getPersonal($aktiv, $fix, $verwendung) + { + $qry = "SELECT DISTINCT ON(mitarbeiter_uid) *, + tbl_benutzer.aktiv as aktiv, + tbl_mitarbeiter.insertamum, + tbl_mitarbeiter.insertvon, + tbl_mitarbeiter.updateamum, + tbl_mitarbeiter.updatevon + FROM ((public.tbl_mitarbeiter JOIN public.tbl_benutzer ON(mitarbeiter_uid=uid)) + JOIN public.tbl_person USING(person_id)) + LEFT JOIN public.tbl_benutzerfunktion USING(uid) + WHERE true"; + + if ($fix === true) + $qry .= " AND fixangestellt=true"; + if ($fix === false) + $qry .= " AND fixangestellt=false"; + if ($aktiv === true) + $qry .= " AND tbl_benutzer.aktiv=true"; + if ($aktiv === false) + $qry .= " AND tbl_benutzer.aktiv=false"; + if ($verwendung === true) + { + $qry.=" AND EXISTS(SELECT * FROM bis.tbl_bisverwendung WHERE (ende>now() or ende is null) AND tbl_bisverwendung.mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid)"; + } + if ($verwendung === false) + { + $qry.=" AND NOT EXISTS(SELECT * FROM bis.tbl_bisverwendung WHERE (ende>now() or ende is null) AND tbl_bisverwendung.mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid)"; + } + + return $this->execQuery($qry); + } } From e8648e52ecd27dea3603e8e8a08303fe41bbe86b Mon Sep 17 00:00:00 2001 From: Alexei Date: Mon, 4 May 2020 20:21:57 +0200 Subject: [PATCH 012/162] person/Benutzer_model.php: generated alias string is sanitized (special characters, spaces,...) --- application/models/person/Benutzer_model.php | 48 +++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/application/models/person/Benutzer_model.php b/application/models/person/Benutzer_model.php index b2bc0f027..2c65003dd 100644 --- a/application/models/person/Benutzer_model.php +++ b/application/models/person/Benutzer_model.php @@ -59,7 +59,7 @@ class Benutzer_model extends DB_Model } /** - * Generates alias for a uid + * Generates alias for a uid. * @param $uid * @return array the alias */ @@ -73,7 +73,7 @@ class Benutzer_model extends DB_Model if (hasData($nameresult)) { $aliasdata = getData($nameresult); - $alias = mb_strtolower($aliasdata[0]->vorname).'.'.mb_strtolower($aliasdata[0]->nachname); + $alias = $this->_sanitizeAliasName($aliasdata[0]->vorname).'.'.$this->_sanitizeAliasName($aliasdata[0]->nachname); $aliasexists = $this->aliasExists($alias); if (hasData($aliasexists) && !getData($aliasexists)[0]) @@ -82,4 +82,48 @@ class Benutzer_model extends DB_Model } return success($aliasres); } + + // -------------------------------------------------------------------------------------------- + // Private methods + + /** + * Sanitizes a string used for alias. Replaces special characters, spaces, upper case. + * @param string $str + * @return string + */ + private function _sanitizeAliasName($str) + { + $enc = 'UTF-8'; + + $acentos = array( + 'A' => '/À|Á|Â|Ã|Å/', + 'Ae' => '/Ä/', + 'a' => '/à|á|â|ã|å/', + 'ae'=> '/ä/', + 'C' => '/Ç/', + 'c' => '/ç/', + 'E' => '/È|É|Ê|Ë/', + 'e' => '/è|é|ê|ë/', + 'I' => '/Ì|Í|Î|Ï/', + 'i' => '/ì|í|î|ï/', + 'N' => '/Ñ/', + 'n' => '/ñ/', + 'O' => '/Ò|Ó|Ô|Õ/', + 'Oe' => '/Ö/', + 'o' => '/ò|ó|ô|õ/', + 'oe' => '/ö/', + 'U' => '/Ù|Ú|Û/', + 'Ue' => '/Ü/', + 'u' => '/ù|ú|û/', + 'ue' => '/ü/', + 'Y' => '/Ý/', + 'y' => '/ý|ÿ/', + 'a.' => '/ª/', + 'o.' => '/º/', + 'ss' => '/ß/', + ); + + $str = preg_replace($acentos, array_keys($acentos), htmlentities($str,ENT_NOQUOTES, $enc)); + return mb_strtolower(str_replace(' ','_', $str)); + } } From 704d39095b8b5026790c2b8e71a9f1c4a1b4ac4b Mon Sep 17 00:00:00 2001 From: Alexei Date: Tue, 12 May 2020 19:34:17 +0200 Subject: [PATCH 013/162] - ressource/Mitarbeiter_model.php - improved getPersonal method - person/Kontakt_model.php - added getFormaKontakttyp and get FirmenTelefon methods --- application/models/person/Kontakt_model.php | 60 +++++++++++++++++++ .../models/ressource/Mitarbeiter_model.php | 8 ++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/application/models/person/Kontakt_model.php b/application/models/person/Kontakt_model.php index 3f27604e8..36ba05be4 100644 --- a/application/models/person/Kontakt_model.php +++ b/application/models/person/Kontakt_model.php @@ -10,6 +10,7 @@ class Kontakt_model extends DB_Model parent::__construct(); $this->dbTable = 'public.tbl_kontakt'; $this->pk = 'kontakt_id'; + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); } public function getWholeKontakt($kontakt_id, $person_id = null, $kontakttyp = null) @@ -59,4 +60,63 @@ class Kontakt_model extends DB_Model return $this->execQuery($sql, array($person_id, $kontakttyp)); } + + /** + * Laedt einen Kontakt eines Standortes + * Es wird nur der erste Eintrag zurueckgeliefert! + * @param $standort_id + * @param $kontakttyp + */ + public function getFirmaKontakttyp($standort_id, $kontakttyp) + { + if (!is_numeric($standort_id)) + { + return error('StandortID ist ungueltig'); + } + + $qry = "SELECT kontakt, kontakt_id FROM public.tbl_kontakt WHERE standort_id=? AND kontakttyp=? ORDER BY kontakt_id LIMIT 1;"; + + return $this->execQuery($qry, array('standort_id' => $standort_id, 'kontakttyp' => $kontakttyp)); + } + + /** + * Gets Firmentelefon for a uid, can be Vorwahl with Telefonklappe or Formenhandy + * @param $uid + */ + public function getFirmenTelefon($uid) + { + $firmentelefon = success(array()); + + $this->MitarbeiterModel->addSelect('standort_id, telefonklappe, person_id'); + $this->MitarbeiterModel->addJoin('public.tbl_benutzer', 'tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid'); + $mitarbeiter = $this->MitarbeiterModel->load(array('uid' => $uid)); + + if (hasData($mitarbeiter)) + { + $mitarbeiter = getData($mitarbeiter); + if (isEmptyString($mitarbeiter[0]->telefonklappe)) + { + $this->addSelect('kontakt'); + $this->addOrder('updateamum, insertamum', 'DESC'); + $this->addLimit(1); + $firmenhandy = $this->loadWhere(array('person_id' => $mitarbeiter[0]->person_id, 'kontakttyp' => 'firmenhandy')); + if (hasData($firmenhandy)) + { + $firmenhandy = getData($firmenhandy); + $firmentelefon = success($firmenhandy[0]->kontakt); + } + } + else + { + $firmaKontakttyp = $this->getFirmaKontakttyp($mitarbeiter[0]->standort_id, 'telefon'); + if (hasData($firmaKontakttyp)) + { + $vorwahl = getData($firmaKontakttyp); + $vorwahl = $vorwahl[0]->kontakt; + $firmentelefon = success(array($vorwahl.'-'.$mitarbeiter[0]->telefonklappe)); + } + } + } + return $firmentelefon; + } } diff --git a/application/models/ressource/Mitarbeiter_model.php b/application/models/ressource/Mitarbeiter_model.php index 523a69fa1..3b0bd2479 100644 --- a/application/models/ressource/Mitarbeiter_model.php +++ b/application/models/ressource/Mitarbeiter_model.php @@ -64,17 +64,19 @@ class Mitarbeiter_model extends DB_Model if ($fix === true) $qry .= " AND fixangestellt=true"; - if ($fix === false) + elseif ($fix === false) $qry .= " AND fixangestellt=false"; + if ($aktiv === true) $qry .= " AND tbl_benutzer.aktiv=true"; - if ($aktiv === false) + elseif ($aktiv === false) $qry .= " AND tbl_benutzer.aktiv=false"; + if ($verwendung === true) { $qry.=" AND EXISTS(SELECT * FROM bis.tbl_bisverwendung WHERE (ende>now() or ende is null) AND tbl_bisverwendung.mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid)"; } - if ($verwendung === false) + elseif ($verwendung === false) { $qry.=" AND NOT EXISTS(SELECT * FROM bis.tbl_bisverwendung WHERE (ende>now() or ende is null) AND tbl_bisverwendung.mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid)"; } From a1600c9f3ac34683b490894b5d6774bd4757c725 Mon Sep 17 00:00:00 2001 From: Paolo Date: Wed, 13 May 2020 17:55:56 +0200 Subject: [PATCH 014/162] CL/Messages_model->sendImplicitTemplate now writes the person log in any case --- application/models/CL/Messages_model.php | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/application/models/CL/Messages_model.php b/application/models/CL/Messages_model.php index 67e7ff969..f023c9150 100644 --- a/application/models/CL/Messages_model.php +++ b/application/models/CL/Messages_model.php @@ -411,23 +411,20 @@ class Messages_model extends CI_Model $message = $this->messagelib->sendMessageUser( $msgVarsDataArray['person_id'], // receiverPersonId - $parsedSubject, // subject - $parsedBody, // body - $sender_id, // sender_id - $senderOU, // senderOU - $relationmessage_id, // relationmessage_id - MSG_PRIORITY_NORMAL // priority + $parsedSubject, // subject + $parsedBody, // body + $sender_id, // sender_id + $senderOU, // senderOU + $relationmessage_id, // relationmessage_id + MSG_PRIORITY_NORMAL // priority ); if (isError($message)) return $message; if (!hasData($message)) return error('No messages were saved in database'); - // Write log entry only if persons were given - if ($type == self::TYPE_PERSONS) - { - $personLog = $this->_personLog($sender_id, $msgVarsDataArray['person_id'], getData($message)[0]); - if (isError($personLog)) return $personLog; - } + // Write log entry only + $personLog = $this->_personLog($sender_id, $msgVarsDataArray['person_id'], getData($message)[0]); + if (isError($personLog)) return $personLog; $receiversCounter++; // increment the counter } From 90eaf41b2c753215ce88dd56a1789cb3d58b37f0 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 14 May 2020 16:15:19 +0200 Subject: [PATCH 015/162] =?UTF-8?q?studentDBDML.php:=20wenn=20Gesamtnotepu?= =?UTF-8?q?nkte=20und=20Pr=C3=BCfung=20=C3=BCbernehmen=20aktiviert,=20werd?= =?UTF-8?q?en=20Punkte=20bei=20Noten=C3=BCbernahme=20auch=20f=C3=BCr=20Pr?= =?UTF-8?q?=C3=BCfung=20=C3=BCbernommen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/student/studentDBDML.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/content/student/studentDBDML.php b/content/student/studentDBDML.php index 8ec746015..dd714a33c 100644 --- a/content/student/studentDBDML.php +++ b/content/student/studentDBDML.php @@ -166,7 +166,7 @@ function generateMatrikelnummer($studiengang_kz, $studiensemester_kurzbz) * @param $note * @return null, error wird direkt in globale Variable geschrieben */ -function NotePruefungAnlegen($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $note) +function NotePruefungAnlegen($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $note, $punkte) { global $return, $error, $errormsg; @@ -227,6 +227,8 @@ function NotePruefungAnlegen($studiensemester_kurzbz, $student_uid, $lehrveranst if(count($benutzerfunktion->result)>0) $anwesenheitsbefreit=true; + $gesamtnote_punkte = defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE; + // Wenn nicht Anwesenheitsbefreit und Anwesenheit unter einem bestimmten Prozentsatz faellt dann wird ein // Pruefungsantritt abgezogen if(isset($anwesenheit->result[0]) && $anwesenheit->result[0]->prozent < FAS_ANWESENHEIT_ROT && !$anwesenheitsbefreit) @@ -239,6 +241,8 @@ function NotePruefungAnlegen($studiensemester_kurzbz, $student_uid, $lehrveranst // 2. Termin mit Note erstellen $pruefung->pruefungstyp_kurzbz = "Termin2"; $pruefung->note = $note; + if($gesamtnote_punkte) + $pruefung->punkte = $punkte; if($pruefung->save()) { $return = true; @@ -260,6 +264,8 @@ function NotePruefungAnlegen($studiensemester_kurzbz, $student_uid, $lehrveranst // 1. Termin mit Note erstellen $pruefung->pruefungstyp_kurzbz = "Termin1"; $pruefung->note = $note; + if($gesamtnote_punkte) + $pruefung->punkte = $punkte; if($pruefung->save()) { @@ -3065,7 +3071,7 @@ if(!$error) if(defined('FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN') && FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN && $return == true && $noten->new == true) { - NotePruefungAnlegen($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $noten->note); + NotePruefungAnlegen($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $noten->note, $noten->punkte); } } } @@ -3193,7 +3199,7 @@ if(!$error) { if(defined('FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN') && FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN && $zeugnisnote->new == true) { - NotePruefungAnlegen($zeugnisnote->studiensemester_kurzbz, $zeugnisnote->student_uid, $zeugnisnote->lehrveranstaltung_id, $zeugnisnote->note); + NotePruefungAnlegen($zeugnisnote->studiensemester_kurzbz, $zeugnisnote->student_uid, $zeugnisnote->lehrveranstaltung_id, $zeugnisnote->note, $zeugnisnote->punkte); } } } @@ -3362,7 +3368,7 @@ if(!$error) { if(defined('FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN') && FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN && $zeugnisnote->new == true) { - NotePruefungAnlegen($semester_aktuell, $uid, $_POST['lehrveranstaltung_id'], $zeugnisnote->note); + NotePruefungAnlegen($semester_aktuell, $uid, $_POST['lehrveranstaltung_id'], $zeugnisnote->note, $zeugnisnote->punkte); } } } From 13dc57b90cb06c59debccd4b1b87a61ac4c40890 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 22 May 2020 16:17:46 +0200 Subject: [PATCH 016/162] Added ISO-3166-1-A-2 column to bis.tbl_nation --- system/dbupdate_3.3.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index b54b28373..f21e6b3f7 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -4019,6 +4019,18 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtriggers LIMIT 1')) echo '
Granted privileges to vilesci on system.tbl_jobtriggers'; } +// Add column ISO-3166-1-A-2 to bis.tbl_nation +if (!$result = @$db->db_query("SELECT ISO-3166-1-A-2 FROM bis.tbl_nation LIMIT 1")) +{ + $qry = "ALTER TABLE bis.tbl_nation ADD COLUMN \"ISO-3166-1-A-2\" character varying(2);"; + $qry .= "COMMENT ON COLUMN bis.tbl_nation.\"ISO-3166-1-A-2\" IS 'ISO 3166-1 alpha-2 country code';"; + + if(!$db->db_query($qry)) + echo 'bis.tbl_nation.ISO-3166-1-A-2: '.$db->db_last_error().'
'; + else + echo '
bis.tbl_nation.ISO-3166-1-A-2: Spalte ISO-3166-1-A-2 hinzugefuegt'; +} + // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -4048,7 +4060,7 @@ $tabellen=array( "bis.tbl_mobilitaet" => array("mobilitaet_id","prestudent_id","mobilitaetstyp_kurzbz","studiensemester_kurzbz","mobilitaetsprogramm_code","gsprogramm_id","firma_id","status_kurzbz","ausbildungssemester","insertvon","insertamum","updatevon","updateamum"), "bis.tbl_mobilitaetstyp" => array("mobilitaetstyp_kurzbz","bezeichnung","aktiv"), "bis.tbl_mobilitaetsprogramm" => array("mobilitaetsprogramm_code","kurzbz","beschreibung","sichtbar","sichtbar_outgoing"), - "bis.tbl_nation" => array("nation_code","entwicklungsstand","eu","ewr","kontinent","kurztext","langtext","engltext","sperre","nationengruppe_kurzbz"), + "bis.tbl_nation" => array("nation_code","entwicklungsstand","eu","ewr","kontinent","kurztext","langtext","engltext","sperre","nationengruppe_kurzbz", "ISO-3166-1-A-2"), "bis.tbl_nationengruppe" => array("nationengruppe_kurzbz","nationengruppe_bezeichnung","aktiv"), "bis.tbl_orgform" => array("orgform_kurzbz","code","bezeichnung","rolle","bisorgform_kurzbz","bezeichnung_mehrsprachig"), "bis.tbl_verwendung" => array("verwendung_code","verwendungbez"), From 89ccb2f3a5f2c85c49d0b9867e4236162a07bb53 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 22 May 2020 17:18:59 +0200 Subject: [PATCH 017/162] Renamed column bis.tbl_nation.ISO-3166-1-A-2 as iso3166_1_a2 --- system/dbupdate_3.3.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index f21e6b3f7..d401b7efb 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -4019,16 +4019,16 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtriggers LIMIT 1')) echo '
Granted privileges to vilesci on system.tbl_jobtriggers'; } -// Add column ISO-3166-1-A-2 to bis.tbl_nation -if (!$result = @$db->db_query("SELECT ISO-3166-1-A-2 FROM bis.tbl_nation LIMIT 1")) +// Add column iso3166_1_a2 to bis.tbl_nation +if (!$result = @$db->db_query("SELECT iso3166_1_a2 FROM bis.tbl_nation LIMIT 1")) { - $qry = "ALTER TABLE bis.tbl_nation ADD COLUMN \"ISO-3166-1-A-2\" character varying(2);"; - $qry .= "COMMENT ON COLUMN bis.tbl_nation.\"ISO-3166-1-A-2\" IS 'ISO 3166-1 alpha-2 country code';"; + $qry = "ALTER TABLE bis.tbl_nation ADD COLUMN iso3166_1_a2 character varying(2);"; + $qry .= "COMMENT ON COLUMN bis.tbl_nation.iso3166_1_a2 IS 'ISO 3166-1 alpha-2 country code';"; if(!$db->db_query($qry)) - echo 'bis.tbl_nation.ISO-3166-1-A-2: '.$db->db_last_error().'
'; + echo 'bis.tbl_nation.iso3166_1_a2: '.$db->db_last_error().'
'; else - echo '
bis.tbl_nation.ISO-3166-1-A-2: Spalte ISO-3166-1-A-2 hinzugefuegt'; + echo '
bis.tbl_nation.iso3166_1_a2: Spalte iso3166_1_a2 hinzugefuegt'; } // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen @@ -4060,7 +4060,7 @@ $tabellen=array( "bis.tbl_mobilitaet" => array("mobilitaet_id","prestudent_id","mobilitaetstyp_kurzbz","studiensemester_kurzbz","mobilitaetsprogramm_code","gsprogramm_id","firma_id","status_kurzbz","ausbildungssemester","insertvon","insertamum","updatevon","updateamum"), "bis.tbl_mobilitaetstyp" => array("mobilitaetstyp_kurzbz","bezeichnung","aktiv"), "bis.tbl_mobilitaetsprogramm" => array("mobilitaetsprogramm_code","kurzbz","beschreibung","sichtbar","sichtbar_outgoing"), - "bis.tbl_nation" => array("nation_code","entwicklungsstand","eu","ewr","kontinent","kurztext","langtext","engltext","sperre","nationengruppe_kurzbz", "ISO-3166-1-A-2"), + "bis.tbl_nation" => array("nation_code","entwicklungsstand","eu","ewr","kontinent","kurztext","langtext","engltext","sperre","nationengruppe_kurzbz", "iso3166_1_a2"), "bis.tbl_nationengruppe" => array("nationengruppe_kurzbz","nationengruppe_bezeichnung","aktiv"), "bis.tbl_orgform" => array("orgform_kurzbz","code","bezeichnung","rolle","bisorgform_kurzbz","bezeichnung_mehrsprachig"), "bis.tbl_verwendung" => array("verwendung_code","verwendungbez"), From 26d030d63339e6f36db5893fd291a59052467940 Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 25 May 2020 16:57:33 +0200 Subject: [PATCH 018/162] Created method setXMLTag_archivierbar in Dokument class This method appends an XML tag named 'archivierbar' with value 'true' to the XML data. --- include/dokument_export.class.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/dokument_export.class.php b/include/dokument_export.class.php index 523a5f89d..4f23a7dcd 100644 --- a/include/dokument_export.class.php +++ b/include/dokument_export.class.php @@ -575,5 +575,11 @@ class dokument_export } } } + + public function setXMLTag_archivierbar() + { + $archivierbar = $this->xml_data->createElement("archivierbar", "true"); + $this->xml_data->documentElement->appendChild($archivierbar); + } } ?> From ad136d140754617dfa7900188ed65ce72a5c7530 Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 25 May 2020 17:00:27 +0200 Subject: [PATCH 019/162] Added setting of XML-tag 'archivierbar' in pdfExport If the template is archivable, XML-tag 'archivierbar' is added. --- content/pdfExport.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/content/pdfExport.php b/content/pdfExport.php index 3fc058adf..22f0110f4 100644 --- a/content/pdfExport.php +++ b/content/pdfExport.php @@ -458,6 +458,12 @@ else } $dokument->setFilename($filename); + + if ($vorlage->archivierbar) + { + // XML-tag archivierbar ergaenzen + $dokument->setXMLTag_archivierbar(); + } if ($sign === true) { @@ -537,6 +543,9 @@ else $dokument->setFilename($filename); $error = false; + + // XML-tag archivierbar ergaenzen + $dokument->setXMLTag_archivierbar(); // Beim Archivieren wird das Dokument immer signiert wenn moeglich if($vorlage->signierbar) @@ -546,7 +555,7 @@ else { $dokument->sign($user); } - + if ($dokument->create($output)) $doc = $dokument->output(false); else From 28d0563fa5e6259e3fbe5280d52a88999ef839ad Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Mon, 25 May 2020 18:21:08 +0200 Subject: [PATCH 020/162] Digital Pruefungsprotokoll is displayed for Bachelor/Master, English/German --- .../controllers/lehre/Pruefungsprotokoll.php | 93 +++ .../education/Abschlusspruefung_model.php | 87 +++ .../models/education/Projektarbeit_model.php | 58 ++ .../views/lehre/pruefungsprotokoll.php | 152 +++++ public/css/lehre/pruefungsprotokoll.css | 11 + system/phrasesupdate.php | 626 ++++++++++++++++++ 6 files changed, 1027 insertions(+) create mode 100644 application/controllers/lehre/Pruefungsprotokoll.php create mode 100644 application/views/lehre/pruefungsprotokoll.php create mode 100644 public/css/lehre/pruefungsprotokoll.css diff --git a/application/controllers/lehre/Pruefungsprotokoll.php b/application/controllers/lehre/Pruefungsprotokoll.php new file mode 100644 index 000000000..9ac439fe1 --- /dev/null +++ b/application/controllers/lehre/Pruefungsprotokoll.php @@ -0,0 +1,93 @@ + 'lehre:r', + 'Protokoll' => 'lehre:r' + ) + ); + + // Load models + $this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel'); + $this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel'); + + // Load language phrases + $this->loadPhrases( + array( + 'abschlusspruefung' + ) + ); + + $this->_setAuthUID(); // sets property uid + + $this->setControllerId(); // sets the controller id + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + */ + public function Protokoll() + { + $abschlusspruefung_id = $this->input->get('abschlusspruefung_id'); + + if (!is_numeric($abschlusspruefung_id)) + show_error('invalid abschlusspruefung'); + + $abschlusspruefung = $this->AbschlusspruefungModel->getAbschlusspruefung($abschlusspruefung_id); + + if (isError($abschlusspruefung)) + show_error(getError($abschlusspruefung)); + else + $abschlusspruefung = getData($abschlusspruefung); + + $this->AbschlussbeurteilungModel->addOrder("(CASE WHEN abschlussbeurteilung_kurzbz = 'ausgezeichnet' THEN 1 + WHEN abschlussbeurteilung_kurzbz = 'gut' THEN 2 + WHEN abschlussbeurteilung_kurzbz = 'bestanden' THEN 3 + WHEN abschlussbeurteilung_kurzbz = 'angerechnet' THEN 4 + ELSE 5 + END + )"); + $abschlussbeurteilung = $this->AbschlussbeurteilungModel->load(); + + if (isError($abschlussbeurteilung)) + show_error(getError($abschlussbeurteilung)); + else + $abschlussbeurteilung = getData($abschlussbeurteilung); + + $data = array( + 'abschlusspruefung' => $abschlusspruefung, + 'abschlussbeurteilung' => $abschlussbeurteilung + ); + + $this->load->view('lehre/pruefungsprotokoll.php', $data); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * 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'); + } +} diff --git a/application/models/education/Abschlusspruefung_model.php b/application/models/education/Abschlusspruefung_model.php index aef5f67c3..d1649a990 100644 --- a/application/models/education/Abschlusspruefung_model.php +++ b/application/models/education/Abschlusspruefung_model.php @@ -11,4 +11,91 @@ class Abschlusspruefung_model extends DB_Model $this->dbTable = 'lehre.tbl_abschlusspruefung'; $this->pk = 'abschlusspruefung_id'; } + + /** + * Gets data of an Abschlusspruefung, including Abschlussarbeit. + * @param $abschlusspruefung_id + * @return object + */ + public function getAbschlusspruefung($abschlusspruefung_id) + { + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $abschlusspruefungdata = array(); + + $this->addSelect('tbl_abschlusspruefung.datum, tbl_abschlusspruefung.abschlussbeurteilung_kurzbz, + studentpers.vorname AS vorname_student, studentpers.nachname AS nachname_student, studentpers.titelpre AS titelpre_student, studentpers.titelpost AS titelpost_student, studentben.uid AS uid_student, matrikelnr, + vorsitzenderpers.vorname AS vorname_vorsitz, vorsitzenderpers.nachname AS nachname_vorsitz, vorsitzenderpers.titelpre AS titelpre_vorsitz, vorsitzenderpers.titelpost AS titelpost_vorsitz, + erstprueferpers.vorname AS vorname_erstpruefer, erstprueferpers.nachname AS nachname_erstpruefer, erstprueferpers.titelpre AS titelpre_erstpruefer, erstprueferpers.titelpost AS titelpost_erstpruefer, + zweitprueferpers.vorname AS vorname_zweitpruefer, zweitprueferpers.nachname AS nachname_zweitpruefer, zweitprueferpers.titelpre AS titelpre_zweitpruefer, zweitprueferpers.titelpost AS titelpost_zweitpruefer + '); + $this->addJoin('public.tbl_benutzer studentben', 'tbl_abschlusspruefung.student_uid = studentben.uid'); + $this->addJoin('public.tbl_person studentpers', 'studentben.person_id = studentpers.person_id'); + $this->addJoin('public.tbl_student', 'studentben.uid = tbl_student.student_uid'); + $this->addJoin('public.tbl_benutzer vorsitzenderben', 'vorsitz = vorsitzenderben.uid', 'LEFT'); + $this->addJoin('public.tbl_person vorsitzenderpers', 'vorsitzenderben.person_id = vorsitzenderpers.person_id', 'LEFT'); + $this->addJoin('public.tbl_person erstprueferpers', 'pruefer1 = erstprueferpers.person_id', 'LEFT'); + $this->addJoin('public.tbl_person zweitprueferpers', 'pruefer2 = zweitprueferpers.person_id', 'LEFT'); + + $abschlusspruefung = $this->load($abschlusspruefung_id); + + if (isError($abschlusspruefung)) + return $abschlusspruefung; + elseif (hasData($abschlusspruefung)) + { + $abschlusspruefungdata = getData($abschlusspruefung)[0]; + + // get Studiengang of Student + $student_uid = $abschlusspruefungdata->uid_student; + $this->StudentModel->addSelect('prestudent_id'); + $prestudent_id = $this->StudentModel->load(array('student_uid' => $student_uid)); + + if (isError($prestudent_id)) + return $prestudent_id; + elseif (hasData($prestudent_id)) + { + //get Studiengangname from Studienplan and -ordnung + $studienordnung = $this->PrestudentstatusModel->getStudienordnungFromPrestudent(getData($prestudent_id)[0]->prestudent_id); + + if (isError($studienordnung)) + return $studienordnung; + elseif (hasData($studienordnung)) + { + $studienordnungdata = getData($studienordnung)[0]; + + $abschlusspruefungdata->studiengang_kz = $studienordnungdata->studiengang_kz; + $abschlusspruefungdata->studiengangbezeichnung = $studienordnungdata->studiengangbezeichnung; + $abschlusspruefungdata->studiengangbezeichnung_englisch = $studienordnungdata->studiengangbezeichnung_englisch; + + $this->StudiengangModel->addSelect('typ'); + $typ = $this->StudiengangModel->load($studienordnungdata->studiengang_kz); + if (isError($typ)) + return $typ; + elseif (hasData($typ)) + { + $abschlusspruefungdata->studiengangstyp = getData($typ)[0]->typ; + } + + // get Abschlussarbeit + $projekttyp = array('Bachelor','Diplom','Master','Dissertation','Lizenziat','Magister'); + $abschlussarbeit = $this->ProjektarbeitModel->getProjektarbeit($student_uid, $studienordnungdata->studiengang_kz, null, $projekttyp, true); + + if (isError($abschlussarbeit)) + return $abschlussarbeit; + if (hasData($abschlussarbeit)) + { + $abschlussarbeit = getData($abschlussarbeit)[0]; + $abschlusspruefungdata->projektarbeit_studiengangstyp_name = $abschlussarbeit->projekttyp_kurzbz; + $abschlusspruefungdata->abschlussarbeit_titel = $abschlussarbeit->titel; + $abschlusspruefungdata->abschlussarbeit_note = $abschlussarbeit->note; + } + } + } + } + + return success($abschlusspruefungdata); + } } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index e5652d6ff..109e23373 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -11,4 +11,62 @@ class Projektarbeit_model extends DB_Model $this->dbTable = 'lehre.tbl_projektarbeit'; $this->pk = 'projektarbeit_id'; } + + /** + * Gets Projektarbeit(en) of a student for a Studiengang, Semester, Projekttyp, final. + * @param $student_uid + * @param $studiengang_kz + * @param $studiensemester_kurzbz + * @param $projekttyp + * @param $final + * @return object + */ + public function getProjektarbeit($student_uid, $studiengang_kz = null, $studiensemester_kurzbz = null, $projekttyp = null, $final = null) + { + $qry = "SELECT + tbl_projektarbeit.* , tbl_projekttyp.bezeichnung + FROM + lehre.tbl_projektarbeit + JOIN + lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung + + WHERE + tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND + tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND + tbl_projektarbeit.student_uid = ?"; + + $params = array($student_uid); + + if (isset($studiengang_kz)) + { + $qry .= ' AND tbl_lehrveranstaltung.studiengang_kz=?'; + $params[] = $studiengang_kz; + } + + if (isset($studiensemester_kurzbz)) + { + $qry .= ' AND tbl_lehreinheit.studiensemester_kurzbz=?'; + $params[] = $studiensemester_kurzbz; + } + + if (isset($projekttyp)) + { + if (is_array($projekttyp)) + $qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz IN ?'; + else + $qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz=?'; + + $params[] = $projekttyp; + } + + if (isset($final)) + { + $qry .= ' AND tbl_projektarbeit.final=?'; + $params[] = $final; + } + + $qry .= ' ORDER BY beginn DESC, projektarbeit_id DESC'; + + return $this->execQuery($qry, $params); + } } diff --git a/application/views/lehre/pruefungsprotokoll.php b/application/views/lehre/pruefungsprotokoll.php new file mode 100644 index 000000000..4d8705510 --- /dev/null +++ b/application/views/lehre/pruefungsprotokoll.php @@ -0,0 +1,152 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Pruefungsprotokoll', + 'jquery' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'dialoglib' => true, + 'ajaxlib' => true, + 'sbadmintemplate' => true, + 'customCSSs' => array( + 'public/css/sbadmin2/admintemplate_contentonly.css', + 'public/css/lehre/pruefungsprotokoll.css' + ), + 'customJSs' => array( + 'public/js/bootstrapper.js' + ) + ) +); +?> + +
+
+
+ studiengangstyp == 'b' ? 'Bachelor' : 'Master'; + $pruefung_name = $abschlusspruefung->studiengangstyp == 'b' ? $this->p->t('abschlusspruefung', 'PruefungBachelor') : $this->p->t('abschlusspruefung', 'PruefungMaster'); + $arbeit_name = $abschlusspruefung->studiengangstyp == 'b' ? $this->p->t('abschlusspruefung', 'ArbeitBachelor') : $this->p->t('abschlusspruefung', 'ArbeitMaster'); + ?> +
+
+ +

+ studiengangstyp == 'b' ? $this->p->t('abschlusspruefung', 'AbgehaltenAmBachelor') : $this->p->t('abschlusspruefung', 'AbgehaltenAmMaster'); ?> + studiengangbezeichnung?>, p->t('abschlusspruefung', 'Studiengangskennzahl') ?>  + studiengang_kz ?> +

+
+
+
+
+

+ titelpre_student . ' ' . $abschlusspruefung->vorname_student . ' ' . $abschlusspruefung->nachname_student . ' ' . $abschlusspruefung->titelpost_student?> +

+

p->t('abschlusspruefung', 'Personenkennzeichen') ?>: matrikelnr ?>

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + p->t('abschlusspruefung', 'Pruefungssenat') ?> +
+ p->t('abschlusspruefung', 'Vorsitz') ?> + + titelpre_vorsitz . ' ' . $abschlusspruefung->vorname_vorsitz . ' ' . $abschlusspruefung->nachname_vorsitz . ' ' . $abschlusspruefung->titelpost_vorsitz ?> +
+ p->t('abschlusspruefung', 'Erstpruefer') ?> + + titelpre_erstpruefer . ' ' . $abschlusspruefung->vorname_erstpruefer . ' ' . $abschlusspruefung->nachname_erstpruefer . ' ' . $abschlusspruefung->titelpost_erstpruefer ?> +
+ p->t('abschlusspruefung', 'Zweitpruefer') ?> + + titelpre_zweitpruefer . ' ' . $abschlusspruefung->vorname_zweitpruefer . ' ' . $abschlusspruefung->nachname_zweitpruefer . ' ' . $abschlusspruefung->titelpost_zweitpruefer ?> +
+ p->t('abschlusspruefung', 'Pruefungsdatum') ?> + + datum), 'd.m.Y'); ?> +
+ p->t('abschlusspruefung', 'EinverstaendniserklaerungName') ?> + + + p->t('abschlusspruefung', 'EinverstaendniserklaerungText') ?> +
+ p->t('abschlusspruefung', 'ThemaBeurteilung') ?>  + + abschlussarbeit_titel) ? $abschlusspruefung->abschlussarbeit_titel : '' ?> + + p->t('abschlusspruefung', 'Note') ?>: abschlussarbeit_note) ? $abschlusspruefung->abschlussarbeit_note : '' ?> +
+ p->t('abschlusspruefung', 'Pruefungsgegenstand') ?> + + studiengangstyp == 'b' ? $this->p->t('abschlusspruefung', 'PruefungsgegenstandBachelor') : $this->p->t('abschlusspruefung', 'PruefungsgegenstandMaster')) ?> +
+ p->t('abschlusspruefung', 'Notizen') ?> +
+ +
+ studiengangstyp == 'b' ? $this->p->t('abschlusspruefung', 'BeurteilungKriterienBachelor') : $this->p->t('abschlusspruefung', 'BeurteilungKriterienMaster')) ?> +
+ p->t('abschlusspruefung', 'Beurteilung') ?>: + +
+
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/public/css/lehre/pruefungsprotokoll.css b/public/css/lehre/pruefungsprotokoll.css new file mode 100644 index 000000000..7511ed8e2 --- /dev/null +++ b/public/css/lehre/pruefungsprotokoll.css @@ -0,0 +1,11 @@ +#protocoltbl textarea { + /* notiz field should stay in table */ + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; +} + +#protocoltbl td:nth-child(1) { + background-color: #f5f5f5; +} \ No newline at end of file diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 14af8e733..45d4183de 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -6766,6 +6766,632 @@ When on hold, the date is only a reminder.', ) ) ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'PruefungBachelor', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'kommissionelle Bachelorprüfung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Bachelor Examination before a Committee', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'PruefungMaster', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'kommissionelle Masterprüfung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Master Examination before a Committee', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'ArbeitBachelor', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bachelorarbeit', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Bachelor paper', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'ArbeitMaster', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Masterarbeit', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Master\'s Thesis', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Protokoll', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Protokoll', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Record of', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'AbgehaltenAmBachelor', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'abgehalten am FH-Bachelorstudiengang', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'held in the UAS Bachelor\'s Degree Program', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'AbgehaltenAmMaster', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'abgehalten am FH-Masterstudiengang', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'held in the UAS Master\'s Degree Program', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Studiengangskennzahl', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Studiengangskennzahl', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Classification Number', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Personenkennzeichen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Personenkennzeichen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Personal identity number', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Pruefungssenat', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungssenat', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Examining Committee', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Vorsitz', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Vorsitzende/r', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Chair', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Erstpruefer', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => '1. Prüfer/in', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '1st Examiner', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Zweitpruefer', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => '2. Prüfer/in', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '2nd Examiner', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Pruefungsdatum', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungsdatum', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Exam Date', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'EinverstaendniserklaerungName', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Einverständniserklärung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'EinverstaendniserklaerungText', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Der/Die Studierende bestätigt, sich in guter körperlicher und geistiger Verfassung zu befinden, + um die Prüfung durchzuführen und dass die technischen Voraussetzungen und gegeben sind.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'ThemaBeurteilung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Thema und Beurteilung der', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Topic and Assessment of', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Note', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Note', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Grade', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Pruefungsgegenstand', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungsgegenstand', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Subject of Examination', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Notizen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Notizen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Notes', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'PruefungsnotizenBachelor', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungsteil/e in Englisch (Optional - entsprechend der Vorgabe des Studiengangs): +<< Nichtzutreffendes Streichen >> +* Präsentation der Bachelorarbeit +* Prüfungsgespräch über die Bachelorarbeit + +Fragen zur Eröffnung des Prüfungsgesprächs +<< Bitte ausfüllen >> + +Gründe für negative Beurteilung ODER allfällige Anmerkungen bei positiver Beurteilung +<< Bitte ausfüllen >> + +Allfällige besondere Vorkommnisse +<< Bitte ausfüllen >>', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Parts of the examination held in English (Optional - in line with the degree program\'s guidelines): +<< Delete as appropriate >> +* Presentation of the Bachelor Paper +* Examination interview on the Bachelor Paper + +Question(s) to open the examination interview +<< Please fill out >> + +Reasons for failing OR any possible explanatory notes on a passing grade +<< Please fill out >> + +Any unusual occurrences +<< Please fill out >>', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'PruefungsnotizenMaster', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungsteil/e in Englisch (Optional - entsprechend der Vorgabe des Studiengangs): +<< Nichtzutreffendes Streichen >> +* Präsentation der Masterarbeit +* Prüfungsgespräch über die Masterarbeit und Querverbindungen zu Fächern des Studienplans +* Prüfungsgespräch über sonstige studienplanrelevante Inhalte + +Fragen zur Eröffnung des Prüfungsgesprächs +<< Bitte ausfüllen >> + +Gründe für negative Beurteilung ODER allfällige Anmerkungen bei positiver Beurteilung +<< Bitte ausfüllen >> + +Allfällige besondere Vorkommnisse +<< Bitte ausfüllen >>', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Parts of the examination held in English (Optional - in line with the degree program\'s guidelines): +<< Delete as appropriate >> +* Presentation of the Master\'s Thesis +* Examination interview on the Master\'s Thesis and its links to subjects of the curriculum +* Examination interview on other subjects relevant to the curriculum + +Question(s) to open the examination interview +<< Please fill out >> + +Reasons for failing OR any possible explanatory notes on a passing grade +<< Please fill out >> + +Any unusual occurrences +<< Please fill out >>', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'PruefungsgegenstandBachelor', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungsgespräch über die Bachelorarbeit', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Presentation and Examination interview on the Bachelor Paper', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'PruefungsgegenstandMaster', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungsgespräch über die Masterarbeit und deren Querverbindungen zu Fächern des Studienplans sowie Prüfungsgespräch über das Stoffgebiet', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '', + 'description' => 'Examination interview on the Master’s Thesis and its links to subjects of the curriculum as well as examination interview on a curricular theme', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'BeurteilungKriterienBachelor', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Beurteilung und Kriterien Bachelorprüfung
+
    +
  • + Mit ausgezeichnetem Erfolg bestanden
    + Der oder die KandidatIn ist in der Lage, Wissen aus verschiedenen Lernbereichen fachlich korrekt in einem weit über das Wesentliche hinausgehenden Ausmaß souverän auf neue Situationen anzuwenden, und das noch dazu auf einem sehr hohen argumentativen Niveau. +
  • +
  • + Mit gutem Erfolg bestanden
    + Der oder die KandidatIn ist in der Lage, Wissen aus verschiedenen Lernbereichen fachlich korrekt in einem über das Wesentliche hinausgehenden Ausmaß auf neue Situationen anzuwenden, und das noch dazu auf einem hohen argumentativen Niveau. +
  • +
  • + Bestanden
    + Alle Lehrveranstaltungen (einschl. Bachelorarbeit) und Bachelorprüfung wurden positiv beurteilt. +
  • +
  • + Nicht bestanden +
  • +
', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'BeurteilungKriterienMaster', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Beurteilung und Kriterien Masterprüfung
+
    +
  • + Mit ausgezeichnetem Erfolg bestanden
    + Der oder die KandidatIn ist in der Lage, Wissen aus verschiedenen Lernbereichen fachlich korrekt in einem weit über das Wesentliche hinausgehenden Ausmaß souverän auf neue Situationen anzuwenden, und das noch dazu auf einem sehr hohen argumentativen Niveau. +
  • +
  • + Mit gutem Erfolg bestanden
    + Der oder die KandidatIn ist in der Lage, Wissen aus verschiedenen Lernbereichen fachlich korrekt in einem über das Wesentliche hinausgehenden Ausmaß auf neue Situationen anzuwenden, und das noch dazu auf einem hohen argumentativen Niveau. +
  • +
  • + Bestanden
    + Alle Lehrveranstaltungen (einschl. Bachelorarbeit) und Bachelorprüfung wurden positiv beurteilt. +
  • +
  • + Nicht bestanden +
  • +
', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abschlusspruefung', + 'phrase' => 'Beurteilung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Beurteilung + ', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Assessment', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ) ); From 3199d5e25fc4ce194421f49a30abed045a7c6790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Mon, 25 May 2020 21:43:32 +0200 Subject: [PATCH 021/162] Added Function for Loading Last Student Status of all Prestudents of a Person --- .../models/crm/Prestudentstatus_model.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php index d579037e1..3335de021 100644 --- a/application/models/crm/Prestudentstatus_model.php +++ b/application/models/crm/Prestudentstatus_model.php @@ -182,4 +182,30 @@ class Prestudentstatus_model extends DB_Model return success(array()); } } + + /** + * getLastStatuses + */ + public function getLastStatusPerson($person_id, $studiensemester_kurzbz = null) + { + $query = 'SELECT * + FROM public.tbl_prestudent p + JOIN ( + SELECT DISTINCT ON(prestudent_id) * + FROM public.tbl_prestudentstatus + WHERE prestudent_id IN (SELECT prestudent_id FROM public.tbl_prestudent WHERE person_id = ?) + ORDER BY prestudent_id, datum desc, insertamum desc + ) ps USING(prestudent_id) + JOIN public.tbl_status USING(status_kurzbz)'; + + $parametersArray = array($person_id); + + if ($studiensemester_kurzbz != '') + { + array_push($parametersArray, $studiensemester_kurzbz); + $query .= ' AND ps.studiensemester_kurzbz = ?'; + } + + return $this->execQuery($query, $parametersArray); + } } From 6cb5d757bea114152ff284d1aa7bfd867f407af5 Mon Sep 17 00:00:00 2001 From: Manfred Kindl Date: Tue, 26 May 2020 10:36:05 +0200 Subject: [PATCH 022/162] =?UTF-8?q?BugFix=20Akte=20l=C3=B6schen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/student/studentoverlay.js.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/student/studentoverlay.js.php b/content/student/studentoverlay.js.php index f0e2715bf..2b511a0de 100644 --- a/content/student/studentoverlay.js.php +++ b/content/student/studentoverlay.js.php @@ -3058,6 +3058,11 @@ function StudentAkteDel() } studiengang_kz = document.getElementById('student-detail-menulist-studiengang_kz').value; + //Wenn es kein Student ist, Studiengangs_kz vom PreStudenten ermitteln + if (studiengang_kz == '') + { + studiengang_kz = document.getElementById('student-prestudent-menulist-studiengang_kz').value; + } //Abfrage ob wirklich geloescht werden soll if (confirm('Dokument wirklich entfernen?')) { From d263216aa0aef114b15d01aaf95af1ff442891b8 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 26 May 2020 09:59:52 +0200 Subject: [PATCH 023/162] Changed: Download in CIS Selfservice does not require to be signed anymore Self-Download is determined by attribute 'stud_selfservice', not by 'signiert' anymore. This is required e.g. for Bachelor diploma, that should be downloadable but does not need to be signed. --- cis/private/profile/dokumente.php | 2 -- include/akte.class.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/cis/private/profile/dokumente.php b/cis/private/profile/dokumente.php index ee31824af..b0c179345 100644 --- a/cis/private/profile/dokumente.php +++ b/cis/private/profile/dokumente.php @@ -76,7 +76,6 @@ if(isset($_GET['action']) && $_GET['action']=='download') $akte = new akte(); $akte->load($id); if ($akte->person_id == $student_studiengang->person_id - && $akte->signiert && $akte->stud_selfservice) { if($akte->inhalt!='') @@ -123,7 +122,6 @@ echo ' }); $(".tablesorter2").tablesorter( { - sortList: [[1,1]], headers: { 0: { sorter: false }}, widgets: ["zebra"] }); diff --git a/include/akte.class.php b/include/akte.class.php index 67a6dc71f..b1498320d 100644 --- a/include/akte.class.php +++ b/include/akte.class.php @@ -527,7 +527,7 @@ class akte extends basis_db if(!is_null($stud_selfservice)) $qry.=" AND stud_selfservice=".($stud_selfservice?'true':'false'); - $qry.=" ORDER BY erstelltam"; + $qry.=" ORDER BY erstelltam DESC"; $this->errormsg = $qry; From 862b48e3a72a93ff126c92785c8c7757995ab63f Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 26 May 2020 10:53:19 +0200 Subject: [PATCH 024/162] Changed aborting messages for easier debugging --- cis/private/profile/dokumente.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cis/private/profile/dokumente.php b/cis/private/profile/dokumente.php index b0c179345..298383f90 100644 --- a/cis/private/profile/dokumente.php +++ b/cis/private/profile/dokumente.php @@ -88,12 +88,12 @@ if(isset($_GET['action']) && $_GET['action']=='download') } else { - die('Id ist ungueltig'); + die('Akte hat keinen Inhalt.'); } } else { - die('Id ist ungueltig'); + die('Nicht zum selbständigen Download bestimmt oder falsche PersonID.'); } } else From 2ca2ece708b436f0dc662597f1475118371387a1 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Tue, 26 May 2020 16:05:23 +0200 Subject: [PATCH 025/162] Abschlusspruefung database changes - created table lehre.tbl_abschlusspruefung_antritt - added protokoll,endezeit,pruefungsantritt_kurzbz,freigabedatum to lehre.tbl_abschlusspruefung --- system/dbupdate_3.3.php | 58 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index df4a1e77e..8d7f077ca 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -4115,6 +4115,61 @@ if(!$result = @$db->db_query('SELECT "Orgform DE", "Orgform EN" FROM public.vw_m echo '
public.vw_msg_vars added'; } +// TABLE lehre.tbl_abschlusspruefung_antritt +if (!@$db->db_query("SELECT 0 FROM lehre.tbl_abschlusspruefung_antritt WHERE 0 = 1")) +{ + $qry = ' + CREATE TABLE lehre.tbl_abschlusspruefung_antritt ( + pruefungsantritt_kurzbz character varying(20) NOT NULL, + bezeichnung character varying(64), + bezeichnung_english character varying(64) + ); + ALTER TABLE lehre.tbl_abschlusspruefung_antritt ADD CONSTRAINT pk_abschlusspruefung_antritt PRIMARY KEY (pruefungsantritt_kurzbz); + INSERT INTO lehre.tbl_abschlusspruefung_antritt(pruefungsantritt_kurzbz, bezeichnung, bezeichnung_english) VALUES (\'erstantritt\', \'Erstantritt\', \'1st Attempt\'); + INSERT INTO lehre.tbl_abschlusspruefung_antritt(pruefungsantritt_kurzbz, bezeichnung, bezeichnung_english) VALUES (\'erstewiederholung\', \'1. Wiederholung\', \'1st Retake\'); + INSERT INTO lehre.tbl_abschlusspruefung_antritt(pruefungsantritt_kurzbz, bezeichnung, bezeichnung_english) VALUES (\'zweitewiederholung\', \'2. Wiederholung\', \'2nd Retake\');'; + + if (!$db->db_query($qry)) + echo 'lehre.tbl_abschlusspruefung_antritt '.$db->db_last_error().'
'; + else + echo '
Created table lehre.tbl_abschlusspruefung_antritt'; + + // GRANT SELECT ON TABLE lehre.tbl_abschlusspruefung_antritt TO web; + $qry = 'GRANT SELECT ON TABLE lehre.tbl_abschlusspruefung_antritt TO web;'; + if (!$db->db_query($qry)) + echo 'lehre.tbl_abschlusspruefung_antritt '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on lehre.tbl_abschlusspruefung_antritt'; + + // GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE lehre.tbl_abschlusspruefung_antritt TO vilesci; + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE lehre.tbl_abschlusspruefung_antritt TO vilesci;'; + if (!$db->db_query($qry)) + echo 'lehre.tbl_abschlusspruefung_antritt '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on lehre.tbl_abschlusspruefung_antritt'; + + // COMMENT ON TABLE lehre.tbl_abschlusspruefung_antritt + $qry = 'COMMENT ON TABLE lehre.tbl_abschlusspruefung_antritt IS \'Type of Abschlusspruefung depending on number of attempts\';'; + if (!$db->db_query($qry)) + echo 'Adding comment to lehre.tbl_abschlusspruefung_antritt: '.$db->db_last_error().'
'; + else + echo '
Added comment to lehre.tbl_abschlusspruefung_antritt'; +} +// add protokoll,endezeit,pruefungsantritt_kurzbz,freigabedatum to lehre.tbl_abschlusspruefung +if(!$result = @$db->db_query("SELECT protokoll,endezeit,pruefungsantritt_kurzbz,freigabedatum FROM lehre.tbl_abschlusspruefung LIMIT 1")) +{ + $qry = "ALTER TABLE lehre.tbl_abschlusspruefung ADD COLUMN protokoll text; + ALTER TABLE lehre.tbl_abschlusspruefung ADD COLUMN endezeit time; + ALTER TABLE lehre.tbl_abschlusspruefung ADD COLUMN pruefungsantritt_kurzbz character varying(20); + ALTER TABLE lehre.tbl_abschlusspruefung ADD CONSTRAINT fk_abschlusspruefung_antritt FOREIGN KEY (pruefungsantritt_kurzbz) REFERENCES lehre.tbl_abschlusspruefung_antritt (pruefungsantritt_kurzbz) ON DELETE RESTRICT ON UPDATE CASCADE; + ALTER TABLE lehre.tbl_abschlusspruefung ADD COLUMN freigabedatum date;"; + + if(!$db->db_query($qry)) + echo 'lehre.tbl_abschlusspruefung: '.$db->db_last_error().'
'; + else + echo '
lehre.tbl_abschlusspruefung: Spalten protokoll,endezeit,pruefungsantritt_kurzbz,freigabedatum hinzugefuegt'; +} + // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -4218,7 +4273,8 @@ $tabellen=array( "fue.tbl_scrumteam" => array("scrumteam_kurzbz","bezeichnung","punkteprosprint","tasksprosprint","gruppe_kurzbz"), "fue.tbl_scrumsprint" => array("scrumsprint_id","scrumteam_kurzbz","sprint_kurzbz","sprintstart","sprintende","insertamum","insertvon","updateamum","updatevon"), "lehre.tbl_abschlussbeurteilung" => array("abschlussbeurteilung_kurzbz","bezeichnung","bezeichnung_english"), - "lehre.tbl_abschlusspruefung" => array("abschlusspruefung_id","student_uid","vorsitz","pruefer1","pruefer2","pruefer3","abschlussbeurteilung_kurzbz","akadgrad_id","pruefungstyp_kurzbz","datum","uhrzeit","sponsion","anmerkung","updateamum","updatevon","insertamum","insertvon","ext_id","note"), + "lehre.tbl_abschlusspruefung" => array("abschlusspruefung_id","student_uid","vorsitz","pruefer1","pruefer2","pruefer3","abschlussbeurteilung_kurzbz","akadgrad_id","pruefungstyp_kurzbz","datum","uhrzeit","sponsion","anmerkung","updateamum","updatevon","insertamum","insertvon","ext_id","note","protokoll","endezeit","pruefungsantritt_kurzbz","freigabedatum"), + "lehre.tbl_abschlusspruefung_antritt" => array("pruefungsantritt_kurzbz","bezeichnung","bezeichnung_english"), "lehre.tbl_akadgrad" => array("akadgrad_id","akadgrad_kurzbz","studiengang_kz","titel","geschlecht"), "lehre.tbl_anrechnung" => array("anrechnung_id","prestudent_id","lehrveranstaltung_id","begruendung_id","lehrveranstaltung_id_kompatibel","genehmigt_von","insertamum","insertvon","updateamum","updatevon","ext_id"), "lehre.tbl_anrechnung_begruendung" => array("begruendung_id","bezeichnung"), From b56b5af5616bd5a0d7ce04d6ebe0ea87b73344e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Wed, 27 May 2020 11:36:06 +0200 Subject: [PATCH 026/162] =?UTF-8?q?Abschlusspr=C3=BCfungen=20im=20FAS=20f?= =?UTF-8?q?=C3=BCr=20digitales=20Pr=C3=BCfungsprotokoll=20adaptiert=20-=20?= =?UTF-8?q?Pr=C3=BCfungsantritt=20kann=20im=20FAS=20gesetzt=20werden=20-?= =?UTF-8?q?=20Freigabestatus=20des=20Protokolls=20wird=20im=20FAS=20angeze?= =?UTF-8?q?igt=20-=20Sortierung=20der=20Pr=C3=BCfungsantritte=20hinzugef?= =?UTF-8?q?=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/student/studentDBDML.php | 3 + .../student/studentabschlusspruefung.js.php | 6 + .../studentabschlusspruefungoverlay.xul.php | 45 +++++-- include/abschlusspruefung.class.php | 32 ++++- include/abschlusspruefung_antritt.class.php | 117 ++++++++++++++++++ rdf/abschlusspruefung.rdf.php | 10 ++ rdf/abschlusspruefung_antritt.rdf.php | 76 ++++++++++++ system/dbupdate_3.3.php | 9 +- 8 files changed, 283 insertions(+), 15 deletions(-) create mode 100644 include/abschlusspruefung_antritt.class.php create mode 100644 rdf/abschlusspruefung_antritt.rdf.php diff --git a/content/student/studentDBDML.php b/content/student/studentDBDML.php index 8ec746015..2345141c7 100644 --- a/content/student/studentDBDML.php +++ b/content/student/studentDBDML.php @@ -3764,6 +3764,9 @@ if(!$error) $pruefung->pruefer2 = $_POST['pruefer2']; $pruefung->pruefer3 = $_POST['pruefer3']; $pruefung->abschlussbeurteilung_kurzbz = $_POST['abschlussbeurteilung_kurzbz']; + if(isset($_POST['pruefungsantritt_kurzbz'])) + $pruefung->pruefungsantritt_kurzbz = $_POST['pruefungsantritt_kurzbz']; + $pruefung->note = $_POST['notekommpruef']; $pruefung->akadgrad_id = $_POST['akadgrad_id']; $pruefung->pruefungstyp_kurzbz = $_POST['pruefungstyp_kurzbz']; diff --git a/content/student/studentabschlusspruefung.js.php b/content/student/studentabschlusspruefung.js.php index cac9cb78a..caaa32051 100644 --- a/content/student/studentabschlusspruefung.js.php +++ b/content/student/studentabschlusspruefung.js.php @@ -163,6 +163,7 @@ function StudentAbschlusspruefungDetailDisableFields(val) document.getElementById('student-abschlusspruefung-menulist-pruefer2').disabled=val; document.getElementById('student-abschlusspruefung-menulist-pruefer3').disabled=val; document.getElementById('student-abschlusspruefung-menulist-abschlussbeurteilung').disabled=val; + document.getElementById('student-abschlusspruefung-menulist-pruefungsantritt').disabled=val; document.getElementById('student-abschlusspruefung-menulist-notekommpruef').disabled=val; document.getElementById('student-abschlusspruefung-menulist-akadgrad').disabled=val; document.getElementById('student-abschlusspruefung-menulist-typ').disabled=val; @@ -186,6 +187,7 @@ function StudentAbschlusspruefungResetFields() document.getElementById('student-abschlusspruefung-menulist-pruefer2').value=''; document.getElementById('student-abschlusspruefung-menulist-pruefer3').value=''; document.getElementById('student-abschlusspruefung-menulist-abschlussbeurteilung').value=''; + document.getElementById('student-abschlusspruefung-menulist-pruefungsantritt').value=''; document.getElementById('student-abschlusspruefung-menulist-notekommpruef').value=''; //document.getElementById('student-abschlusspruefung-menulist-akadgrad').value=''; //document.getElementById('student-abschlusspruefung-menulist-typ').value='Bachelor'; @@ -342,6 +344,7 @@ function StudentAbschlusspruefungAuswahl() pruefer3 = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#pruefer3" )); pruefer3_nachname = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#pruefer3_nachname" )); abschlussbeurteilung_kurzbz = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#abschlussbeurteilung_kurzbz" )); + pruefungsantritt_kurzbz = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#pruefungsantritt_kurzbz" )); notekommpruef = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#notekommpruef" )); akadgrad_id = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#akadgrad_id" )); datum = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#datum" )); @@ -395,6 +398,7 @@ function StudentAbschlusspruefungAuswahl() MenulistSelectItemOnValue('student-abschlusspruefung-menulist-pruefer2', pruefer2); MenulistSelectItemOnValue('student-abschlusspruefung-menulist-pruefer3', pruefer3); document.getElementById('student-abschlusspruefung-menulist-abschlussbeurteilung').value=abschlussbeurteilung_kurzbz; + document.getElementById('student-abschlusspruefung-menulist-pruefungsantritt').value=pruefungsantritt_kurzbz; document.getElementById('student-abschlusspruefung-menulist-notekommpruef').value=notekommpruef; document.getElementById('student-abschlusspruefung-menulist-akadgrad').value=akadgrad_id; document.getElementById('student-abschlusspruefung-datum-datum').value=datum; @@ -424,6 +428,7 @@ function StudentAbschlusspruefungSpeichern() var pruefer2 = MenulistGetSelectedValue('student-abschlusspruefung-menulist-pruefer2'); var pruefer3 = MenulistGetSelectedValue('student-abschlusspruefung-menulist-pruefer3'); var abschlussbeurteilung_kurzbz = document.getElementById('student-abschlusspruefung-menulist-abschlussbeurteilung').value; + var pruefungsantritt_kurzbz = document.getElementById('student-abschlusspruefung-menulist-pruefungsantritt').value; var notekommpruef = document.getElementById('student-abschlusspruefung-menulist-notekommpruef').value; var akadgrad_id = document.getElementById('student-abschlusspruefung-menulist-akadgrad').value; var datum = document.getElementById('student-abschlusspruefung-datum-datum').value; @@ -482,6 +487,7 @@ function StudentAbschlusspruefungSpeichern() req.add('pruefer2', pruefer2); req.add('pruefer3', pruefer3); req.add('abschlussbeurteilung_kurzbz', abschlussbeurteilung_kurzbz); + req.add('pruefungsantritt_kurzbz', pruefungsantritt_kurzbz); req.add('notekommpruef', notekommpruef); req.add('akadgrad_id', akadgrad_id); req.add('datum', ConvertDateToISO(datum)); diff --git a/content/student/studentabschlusspruefungoverlay.xul.php b/content/student/studentabschlusspruefungoverlay.xul.php index 3c915e270..e281a7a16 100644 --- a/content/student/studentabschlusspruefungoverlay.xul.php +++ b/content/student/studentabschlusspruefungoverlay.xul.php @@ -97,6 +97,14 @@ echo ''; class="sortDirectionIndicator" sort="rdf:http://www.technikum-wien.at/abschlusspruefung/rdf#uhrzeit" onclick="StudentAbschlusspruefungTreeSort()"/> +