diff --git a/application/config/studierendenantrag.php b/application/config/studierendenantrag.php index 159ead759..c5ebc0d80 100644 --- a/application/config/studierendenantrag.php +++ b/application/config/studierendenantrag.php @@ -110,11 +110,10 @@ $config['abmeldung_job_deadline_date_modifier'] = '+2 weeks'; /** * System User - uid of a user that is allowed to set prestudentstatus - * TODO(chris): DEBUG! CHANGE THIS! * * @var string */ -$config['antrag_job_systemuser'] = 'ma0168'; +$config['antrag_job_systemuser'] = ''; /** diff --git a/application/controllers/jobs/AntragJob.php b/application/controllers/jobs/AntragJob.php index 6bd4e29d6..6f5747232 100644 --- a/application/controllers/jobs/AntragJob.php +++ b/application/controllers/jobs/AntragJob.php @@ -426,40 +426,56 @@ class AntragJob extends JOB_Controller $modifier_request_2 = $this->config->item('wiederholung_job_request_2_date_modifier'); $modifier_deadline = $this->config->item('wiederholung_job_deadline_date_modifier'); - if ($modifier_deadline) - { + $digi_start = $this->config->item('digitalization_start'); + if ($digi_start) { + try { + $digi_start = new DateTime($digi_start); + } catch(Exception $e) { + } + } + + if ($modifier_deadline) { $dateDeadline = new DateTime(); $dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline)); + + if ($digi_start) + $dateDeadline = max($digi_start, $dateDeadline); + } else { + $dateDeadline = $digi_start ?: null; } - else - $dateDeadline = null; //first request - if ($modifier_request_1) - $this->sendReminder( - 'Request1', - null, - Studierendenantragstatus_model::STATUS_REQUESTSENT_1, - $dateDeadline, - $modifier_request_1, - $modifier_deadline, - 'Aufforderung: Bekanntgabe Wiederholung' - ); - else + if ($modifier_request_1) { + $dateStichtag = new DateTime(); + $dateStichtag->sub(DateInterval::createFromDateString($modifier_request_1)); + if (!$dateDeadline || $dateStichtag > $dateDeadline) + $this->sendReminder( + 'Request1', + null, + Studierendenantragstatus_model::STATUS_REQUESTSENT_1, + $dateDeadline, + $dateStichtag, + $modifier_deadline, + 'Aufforderung: Bekanntgabe Wiederholung' + ); + } else $this->logError('Config "wiederholung_job_request_1_date_modifier" nicht gesetzt'); //second request - if ($modifier_request_2) - $this->sendReminder( - 'Request2', - Studierendenantragstatus_model::STATUS_REQUESTSENT_1, - Studierendenantragstatus_model::STATUS_REQUESTSENT_2, - $dateDeadline, - $modifier_request_2, - $modifier_deadline, - 'Reminder Aufforderung: Bekanntgabe Wiederholung' - ); - else + if ($modifier_request_2) { + $dateStichtag = new DateTime(); + $dateStichtag->sub(DateInterval::createFromDateString($modifier_request_2)); + if (!$dateDeadline || $dateStichtag > $dateDeadline) + $this->sendReminder( + 'Request2', + Studierendenantragstatus_model::STATUS_REQUESTSENT_1, + Studierendenantragstatus_model::STATUS_REQUESTSENT_2, + $dateDeadline, + $dateStichtag, + $modifier_deadline, + 'Reminder Aufforderung: Bekanntgabe Wiederholung' + ); + } else $this->logError('Config "wiederholung_job_request_2_date_modifier" nicht gesetzt'); $this->logInfo('Ende Job sendAufforderungWiederholer'); @@ -479,14 +495,11 @@ class AntragJob extends JOB_Controller return $result; } - protected function sendReminder($name, $status_from, $status_to, $deadline, $date_modifier, $modifier_deadline, $subject) + protected function sendReminder($name, $status_from, $status_to, $deadline, $date_stichtag, $modifier_deadline, $subject) { $this->logInfo('Start Job sendAufforderungWiederholer ' . $name); - $dateStichtag = new DateTime(); - $dateStichtag->sub(DateInterval::createFromDateString($date_modifier)); - - $result = $this->PruefungModel->getAllPrestudentsWhereCommitteeExamFailed($status_from, $dateStichtag, $deadline); + $result = $this->PruefungModel->getAllPrestudentsWhereCommitteeExamFailed($status_from, $date_stichtag, $deadline); if(isError($result)) { diff --git a/application/models/education/Pruefung_model.php b/application/models/education/Pruefung_model.php index 813a74179..83bf9b7f8 100644 --- a/application/models/education/Pruefung_model.php +++ b/application/models/education/Pruefung_model.php @@ -117,8 +117,74 @@ class Pruefung_model extends DB_Model return $this->db->get_compiled_select($this->dbTable); } + /** + * @return stdClass + */ + public function loadWhereCommitteeExamsFailed() + { + $this->dbTable = 'lehre.tbl_pruefung p'; + + $this->addSelect('p.datum'); + + $this->addJoin('lehre.tbl_note n', 'note'); + + $this->db->where("n.positiv", false); + $this->db->where_in("p.pruefungstyp_kurzbz", ['kommPruef','zusKommPruef']); + + return $this->load(); + } + /** + * @return void + */ + protected function withDetailsForStudierendenAntrag() + { + $this->load->config('studierendenantrag'); + + $sprache_index = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1"; + + $this->addSelect('pers.vorname'); + $this->addSelect('pers.nachname'); + $this->addSelect('pers.person_id'); + $this->addSelect('s.matrikelnr'); + $this->addSelect('g.bezeichnung'); + $this->addSelect('g.studiengang_kz'); + $this->addSelect('o.bezeichnung_mehrsprachig[(' . $sprache_index . ')] AS orgform', false); + $this->addSelect('ps.prestudent_id'); + $this->addSelect('lv.bezeichnung as lvbezeichnung'); + $this->addSelect('le.studiensemester_kurzbz'); + $this->addSelect('a.typ'); + $this->addSelect('campus.get_status_studierendenantrag(a.studierendenantrag_id) status'); + + $this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->addJoin('public.tbl_student s', 'student_uid'); + $this->addJoin('public.tbl_prestudent ps', 'prestudent_id'); + $this->addJoin('public.tbl_person pers', 'person_id'); + $this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); + $this->addJoin('public.tbl_studiengang g', 'ps.studiengang_kz=g.studiengang_kz'); + $this->addJoin('bis.tbl_orgform o', 'g.orgform_kurzbz=o.orgform_kurzbz'); + $this->addJoin('campus.tbl_studierendenantrag a', 'ps.prestudent_id=a.prestudent_id and a.typ=' . $this->escape(Studierendenantrag_model::TYP_WIEDERHOLUNG), 'LEFT'); + + $this->db->where_in("get_rolle_prestudent(ps.prestudent_id, null)", $this->config->item('antrag_prestudentstatus_whitelist')); + + $this->db->where("g.aktiv", true); + + $statusgruende = $this->config->item('status_gruende_wiederholer'); + if (is_array($statusgruende) && !isEmptyArray($statusgruende)) { + foreach ($statusgruende as $k => $v) { + $statusgruende[$k] = $this->db->escape($v); + } + $this->db->where('lv.studiengang_kz NOT IN( + SELECT ps1.studiengang_kz + FROM + public.tbl_prestudent ps1 + JOIN public.tbl_prestudentstatus pss USING (prestudent_id) + WHERE pss.statusgrund_id in (' . implode(',', $statusgruende) . ') + AND ps.prestudent_id = ps1.prestudent_id)', null, false); + } + } /** * @param integer $prestudent_id student_uid @@ -127,23 +193,23 @@ class Pruefung_model extends DB_Model */ public function loadWhereCommitteeExamFailedForPrestudent($prestudent_id) { + $this->withDetailsForStudierendenAntrag(); - $sql = $this->loadWhereThreeExamsFailed(); + $this->db->where('ps.prestudent_id', $prestudent_id); - $statusgruende = $this->config->item('status_gruende_wiederholer'); - if (!is_array($statusgruende)) - $statusgruende = []; - - return $this->execQuery('select * from ( ' . $sql . ') temp where count >= 3 AND prestudent_id = ?', [ - Studierendenantrag_model::TYP_WIEDERHOLUNG, - $statusgruende, - $prestudent_id - ]); + return $this->loadWhereCommitteeExamsFailed(); } + /** + * @param string $status + * @param \DateTime $maxDate + * @param \DateTime $minDate + * + * @return stdClass + */ public function getAllPrestudentsWhereCommitteeExamFailed($status, $maxDate, $minDate) { - $this->load->model('education/Studierendenantrag_model', 'StudierendenantragModel'); + $this->withDetailsForStudierendenAntrag(); if ($maxDate) $this->db->where("p.datum < ", $maxDate->format('c')); @@ -170,12 +236,6 @@ class Pruefung_model extends DB_Model $this->db->where('campus.get_status_studierendenantrag(a.studierendenantrag_id)', $status); } - $sql = $this->loadWhereThreeExamsFailed(); - - $statusgruende = $this->config->item('status_gruende_wiederholer'); - if (!is_array($statusgruende)) - $statusgruende = []; - - return $this->execQuery('select * from ( ' . $sql . ') temp where count >= 3', [Studierendenantrag_model::TYP_WIEDERHOLUNG, $statusgruende]); + return $this->loadWhereCommitteeExamsFailed(); } } diff --git a/application/views/lehre/Antrag/Leitung/List.php b/application/views/lehre/Antrag/Leitung/List.php index 3dffacf3f..9c0749dae 100644 --- a/application/views/lehre/Antrag/Leitung/List.php +++ b/application/views/lehre/Antrag/Leitung/List.php @@ -13,6 +13,7 @@ $sitesettings = array( 'primevue3' => true, 'phrases' => array( 'global', + 'ui', 'studierendenantrag', 'lehre', 'person', diff --git a/public/css/cis_bs5.css b/public/css/cis_bs5.css index 9ee7cd848..48a5bfb1b 100644 --- a/public/css/cis_bs5.css +++ b/public/css/cis_bs5.css @@ -59,8 +59,41 @@ h6, .h6 { .fhc-container { padding: 0 15px; + max-width: 100%; } .tabulator { font-size: var(--bs-body-font-size); } + +.fhc-container .tabulator { + border-left: 1px solid #dee2e6; +} +.fhc-container .tabulator .tabulator-row { + border-bottom: none; +} +.fhc-container .tabulator .tabulator-row .tabulator-frozen, +.fhc-container .tabulator .tabulator-row .tabulator-cell { + border-bottom: 1px solid #dee2e6; +} +.fhc-container .tabulator .tabulator-row.tabulator-row-even { + background-color: transparent; +} +.fhc-container .tabulator .tabulator-headers .tabulator-frozen, +.fhc-container .tabulator .tabulator-row.tabulator-row-odd .tabulator-frozen, +.fhc-container .tabulator .tabulator-row.tabulator-row-odd .tabulator-cell { + background-color: #fff; +} +.fhc-container .tabulator .tabulator-row.tabulator-row-even .tabulator-frozen, +.fhc-container .tabulator .tabulator-row.tabulator-row-even .tabulator-cell { + background-color: #f2f2f2; +} +.fhc-container .tabulator .tabulator-row.tabulator-selectable:hover .tabulator-frozen, +.fhc-container .tabulator .tabulator-row.tabulator-selectable:hover .tabulator-cell { + background-color: #ececec; +} + +.fhc-container .tabulator .tabulator-col, +.fhc-container .tabulator .tabulator-cell { + border-right: 1px solid #dee2e6; +} diff --git a/public/js/components/Studierendenantrag/Leitung.js b/public/js/components/Studierendenantrag/Leitung.js index 747ad7123..da883acbc 100644 --- a/public/js/components/Studierendenantrag/Leitung.js +++ b/public/js/components/Studierendenantrag/Leitung.js @@ -347,6 +347,7 @@ export default { @action:objectionDeny="actionoObjectionDeny" @action:objectionApprove="actionObjectionApprove" @action:cancel="actionCancel" + @reload="reload" > diff --git a/public/js/components/Studierendenantrag/Leitung/Table.js b/public/js/components/Studierendenantrag/Leitung/Table.js index 8cbfdd9d7..ea8dae107 100644 --- a/public/js/components/Studierendenantrag/Leitung/Table.js +++ b/public/js/components/Studierendenantrag/Leitung/Table.js @@ -86,8 +86,8 @@ export default { this.table = new Tabulator(this.$refs.table, { placeholder:"Keine zu bearbeitenden Datensätze", movableColumns: true, - height: '50vh', - layout: "fitDataStretch", // TODO(chris): wont work when changed + maxHeight: '50vh', + layout: "fitDataFill", ajaxURL: this.ajaxUrl, persistence: { // NOTE(chris): do not store column titles sort: true, //persist column sorting @@ -214,6 +214,10 @@ export default { } }, { field: 'actions', + frozen: true, + title: this.p.t('ui', 'aktion'), + headerFilter: false, + headerSort: false, formatter: (cell, formatterParams, onRendered) => { let container = document.createElement('div'), data = cell.getData(); @@ -324,11 +328,6 @@ export default { container.append(button); } - // TODO(chris): not yet perfect - onRendered(() => { - cell.getColumn().setWidth(true); - }); - return container; } }] @@ -338,7 +337,7 @@ export default { let columnData = []; for (let col of columns) { let def = col.getDefinition(); - if (def.title) { + if (def.title && !def.frozen) { columnData.push({ title: def.title, visible: col.isVisible(), diff --git a/public/js/mixins/Phrasen.js b/public/js/mixins/Phrasen.js index bf11f8435..6c27f87bb 100644 --- a/public/js/mixins/Phrasen.js +++ b/public/js/mixins/Phrasen.js @@ -59,13 +59,18 @@ const phrasen = { return ''; } if (!categories[category]) { - - if (window.FHC_JS_PHRASES_STORAGE_OBJECT !== undefined) - categories[category] = extractCategory(FHC_JS_PHRASES_STORAGE_OBJECT, category); + + var initialval = ''; + if (window.FHC_JS_PHRASES_STORAGE_OBJECT !== undefined) { + var tmp_category = extractCategory(FHC_JS_PHRASES_STORAGE_OBJECT, category); + if(tmp_category[phrase] !== undefined ) { + initialval = tmp_category[phrase]; + } + } if (!categories[category] || Object.keys(categories[category]).length === 0) { categories[category] = undefined; - let val = Vue.ref(''); + let val = Vue.ref(initialval); loadLazy(category, val, phrase, params); return val; } diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index d405692ba..0a8407ad7 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -18936,6 +18936,9 @@ array( ) ) ), +/* + // es kann fuer jede Kombination Typ und Status eine Phrase der Form info__ 'core', 'category' => 'studierendenantrag', @@ -18956,6 +18959,7 @@ array( ) ) ), +*/ array( 'app' => 'core', 'category' => 'studierendenantrag', @@ -21427,7 +21431,7 @@ array( 'phrases' => array( array( 'sprache' => 'German', - 'text' => 'Die Abmeldung vom Studium kann hier durchführt werden.', + 'text' => 'Die Abmeldung vom Studium kann hier durchgeführt werden.', 'description' => '', 'insertvon' => 'system' ),