diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php index af598a345..43dc18d1c 100644 --- a/application/controllers/api/frontend/v1/Abgabe.php +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -511,10 +511,11 @@ class Abgabe extends FHCAPI_Controller return $projektarbeit->projektarbeit_id; }; $projektarbeiten_ids = array_map($mapFunc, $projektarbeiten->retval); - - $ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids); - $projektabgaben = $this->getDataOrTerminateWithError($ret, 'general'); + if(count($projektarbeiten_ids) > 0) { + $ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids); + $projektabgaben = $this->getDataOrTerminateWithError($ret, 'general'); + } forEach($projektarbeiten->retval as $pa) { @@ -846,9 +847,10 @@ class Abgabe extends FHCAPI_Controller private function getProjektbetreuerEmailByProjektarbeitID($projektarbeit_id) { $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id); - $email = $this->getDataOrTerminateWithError($result, 'general'); - - return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email; + if(count($result->retval) > 0) { + $email = getData($result); + return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email; + } else return ''; } diff --git a/application/controllers/api/frontend/v1/Documents.php b/application/controllers/api/frontend/v1/Documents.php index 7b2fc4a15..13c0a2eba 100644 --- a/application/controllers/api/frontend/v1/Documents.php +++ b/application/controllers/api/frontend/v1/Documents.php @@ -208,7 +208,6 @@ class Documents extends FHCAPI_Controller $this->load->model('system/Vorlage_model', 'VorlageModel'); $result = $this->VorlageModel->load($xsl); - $this->addMeta("ress", $result); $vorlage = current($this->getDataOrTerminateWithError($result)); if (!$vorlage) show_404(); @@ -221,7 +220,7 @@ class Documents extends FHCAPI_Controller 'gedruckt' => true, 'insertamum' => date('c'), 'insertvon' => getAuthUID(), - 'uid' => $this->input->post_get('uid') ?: '', + 'uid' => $this->input->post_get('uid') ?: null, 'archiv' => true, 'signiert' => !!$sign_user, 'stud_selfservice' => $vorlage->stud_selfservice @@ -251,6 +250,9 @@ class Documents extends FHCAPI_Controller 'studiensemester_kurzbz' => $ss, 'student_uid' => $akteData['uid'] ]); + + if (!hasData($result)) $this->terminateWithError($this->p->t("stv", "error_noLehrverbandAssigned")); + $res = current($this->getDataOrTerminateWithError($result)); $studiengang_kz = $res->studiengang_kz; @@ -332,6 +334,7 @@ class Documents extends FHCAPI_Controller if ($prestudent_id) { $this->load->model('crm/prestudent_model', 'PrestudentModel'); $this->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT'); + $this->PrestudentModel->addSelect('tbl_prestudent.*, UPPER(typ || kurzbz) AS kuerzel'); $result = $this->PrestudentModel->load($prestudent_id); $prestudent = current($this->getDataOrTerminateWithError($result)); diff --git a/application/controllers/jobs/AbgabetoolJob.php b/application/controllers/jobs/AbgabetoolJob.php index 9b59a72e7..b81053032 100644 --- a/application/controllers/jobs/AbgabetoolJob.php +++ b/application/controllers/jobs/AbgabetoolJob.php @@ -495,6 +495,10 @@ class AbgabetoolJob extends JOB_Controller // get all new or changed termine in interval $result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes); $retval = getData($result); + if(!$retval) { + $this->_ci->logInfo("Keine Emails an Betreuer über neue oder veränderte Termine versandt"); + return; + } // group changed/new abgaben for projektarbeiten $projektarbeiten = []; @@ -557,6 +561,8 @@ class AbgabetoolJob extends JOB_Controller $anredeFillString = $data->anrede == "Herr" ? "r" : ""; $fullFormattedNameString = $data->first; + $relevantCounter = 0; // workaround to check if a betreuer needs to have any notification about relevant + // abgaben at all to avoid sending empty emails since we filter on certain conditions forEach($tupelArr as $tupel) { $projektarbeit_id = $tupel[0]; $betreuerRow = $tupel[1]; @@ -575,6 +581,8 @@ class AbgabetoolJob extends JOB_Controller continue; } + $relevantCounter++; + // format the Student Name $s = $relevantAbgaben[0]; $nameParts = []; @@ -633,6 +641,11 @@ class AbgabetoolJob extends JOB_Controller // done with building the change list, now send it $betreuerRow = $tupelArr[0][1]; + if($relevantCounter == 0) { + $this->_ci->logInfo('No Relevant Abgaben to notify Betreuer PersonID: "'.$betreuerRow->person_id.'".'); + continue; + } + $path = $this->_ci->config->item('URL_MITARBEITER'); $url = CIS_ROOT.$path; diff --git a/include/lehrelisthelper.class.php b/include/lehrelisthelper.class.php index b1821391f..f511b27cc 100644 --- a/include/lehrelisthelper.class.php +++ b/include/lehrelisthelper.class.php @@ -270,6 +270,8 @@ class LehreListHelper } else if ($row->bisio_id != '' && $row->status != 'Incoming' && ($row->von > $stsemdatumvon || $row->von == '')) { // if bis datum is not yet known but von is available already $zusatz .= '(o)(ab '.$datum->formatDatum($row->von, 'd.m.Y').')'; + } else if ($row->bisio_id != '' && $row->status != 'Incoming' && ($row->von <= $stsemdatumvon || $row->von == '') && ($row->bis == '' || $row->bis > date('Y-m-d'))){ + $zusatz .= '(o)(ab '.$datum->formatDatum($row->von, 'd.m.Y').')'; } diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js b/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js index d5caf97a6..bb5c6a710 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js @@ -180,7 +180,7 @@ export const AbgabetoolAssistenz = { // frozen: true, // width: 40 // }, - {title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4details'))), field: 'details', headerFilter: false, headerSort: false, formatter: this.formAction, tooltip:false, minWidth: 150, cssClass: 'sticky-col'}, + {title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4details'))), field: 'details', headerFilter: false, headerSort: false, formatter: this.formAction, tooltip:false, minWidth: 100, cssClass: 'sticky-col'}, {title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4personenkennzeichen'))), headerFilter: true, field: 'pkz', formatter: this.pkzTextFormatter, widthGrow: 1, tooltip: false}, {title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4vorname'))), field: 'student_vorname', headerFilter: true, formatter: this.centeredTextFormatter,widthGrow: 1}, {title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4nachname'))), field: 'student_nachname', headerFilter: true, formatter: this.centeredTextFormatter, widthGrow: 1}, @@ -226,7 +226,7 @@ export const AbgabetoolAssistenz = { field: 'qgate2Status', formatter: this.centeredTextFormatter, widthGrow: 1, width: 220, tooltip: false}, ], persistence: false, - persistenceID: "abgabetool_2026_02_26" + persistenceID: "abgabetool_2026_03_16" }, abgabeTableEventHandlers: [ { @@ -645,7 +645,7 @@ export const AbgabetoolAssistenz = { actionButtons.className = "d-flex gap-3"; // you can keep Bootstrap gap if loaded actionButtons.style.display = "flex"; actionButtons.style.alignItems = "stretch"; // buttons stretch to full height - actionButtons.style.justifyContent = "center"; + actionButtons.style.justifyContent = "start"; actionButtons.style.height = "100%"; // full grid cell height const val = cell.getValue(); @@ -675,8 +675,20 @@ export const AbgabetoolAssistenz = { createButton('fa fa-timeline', 'abgabetool/c4termineTimeLine', () => this.openTimeline(val)) ); + if(val.latestTerminWithUpload) { + actionButtons.append( + createButton('fa fa-download', 'abgabetool/c4downloadLatestAbgabe', () => this.downloadAbgabe(val.latestTerminWithUpload.paabgabe_id, val.student_uid, val.projektarbeit_id)) + ) + } + return actionButtons; }, + downloadAbgabe(paabgabe_id, student_uid, projektarbeit_id) { + const url = `/api/frontend/v1/Abgabe/getStudentProjektarbeitAbgabeFile?paabgabe_id=${paabgabe_id}&student_uid=${student_uid}&projektarbeit_id=${projektarbeit_id}`; + + window.open(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url) + // this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid)) + }, undoSelection(cell) { // checks if cells row is selected and unselects -> imitates columns which dont trigger row selection @@ -780,6 +792,8 @@ export const AbgabetoolAssistenz = { // TODO: mehrsprachig englisch projekt.note_bez = opt.bezeichnung } + + const latestTerminWithUpload = this.findLatestTerminWithUpload(projekt) return { ...projekt, @@ -787,6 +801,7 @@ export const AbgabetoolAssistenz = { details: { student_uid: projekt.student_uid, projektarbeit_id: projekt.projektarbeit_id, + latestTerminWithUpload: latestTerminWithUpload ?? null }, pkz: this.buildPKZ(projekt), beurteilung: projekt.beurteilungLink ?? null, @@ -800,6 +815,15 @@ export const AbgabetoolAssistenz = { } }) }, + findLatestTerminWithUpload(projekt) { + const withAbgabedatumSorted = projekt?.abgabetermine?.filter(t => t.abgabedatum != null)?.sort((a,b) => a < b) + + if(withAbgabedatumSorted.length) { + return withAbgabedatumSorted[0] + } + + return null + }, createInfoString(data) { let str = ''; @@ -1413,9 +1437,12 @@ export const AbgabetoolAssistenz = {