From 298dbbf400ba7301f6e664446ccfeb3e52c7c0b4 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Thu, 2 Apr 2026 10:58:49 +0200 Subject: [PATCH 1/6] use context vm for tabulator event, refactor function toggleRowClick, delete unused commented sections --- public/js/components/Vertraege/Vertraege.js | 142 +++----------------- 1 file changed, 15 insertions(+), 127 deletions(-) diff --git a/public/js/components/Vertraege/Vertraege.js b/public/js/components/Vertraege/Vertraege.js index d4d65e428..30dc593c7 100644 --- a/public/js/components/Vertraege/Vertraege.js +++ b/public/js/components/Vertraege/Vertraege.js @@ -20,9 +20,6 @@ export default { ContractStati }, inject: { -/* cisRoot: { - from: 'cisRoot' - },*/ hasSchreibrechte: { from: 'hasSchreibrechte', default: false @@ -145,6 +142,8 @@ export default { return options; }, tabulatorEvents() { + const vm = this; + const events = [ { event: 'tableBuilt', @@ -177,28 +176,11 @@ export default { setHeader('actions', this.$p.t('global', 'aktionen')); } }, -/* { - //is just enabled for ADDON Injection KU: MultiprintHonorarvertrag - //(maybe enable also for ADDON FH Burgenland: MultiAccept later) - event: 'rowClick', - handler: (e, row) => { - if (this.dataPrintHonorar != null && this.dataPrintHonorar.multiselect != null) { - const selectedContract = row.getData().vertrag_id; - const status = row.getData().status; - const bezeichnung = row.getData().bezeichnung; - - this.toggleRowClick(selectedContract, status, bezeichnung); - } - } - },*/ { event: 'rowClick', - handler: (e, row) => { - if (!this.dataPrintHonorar?.multiselect) return; - + handler: function (e, row) { const { vertrag_id, status, bezeichnung, vertragstyp_bezeichnung } = row.getData(); - - this.toggleRowClick(e, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung); + vm.toggleRowClick(e, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung); } }, { @@ -242,8 +224,6 @@ export default { person_id() { this.$refs.table.reloadTable(); this.arraySelectedContracts = []; -/* if(this.dataPrintHonorar?.multiselect) - this.dataPrintHonorar.multiselect = [];*/ }, }, methods: { @@ -270,7 +250,6 @@ export default { ) .then(result => { this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); - //window.scrollTo(0, 0); this.reload(); this.contractSelected.vertrag_id = null; }) @@ -518,19 +497,9 @@ export default { 'content/pdfExport.php?xml=' + this.dataPrintHonorar.xml + '&xsl=' + this.dataPrintHonorar.xsl + '&mitarbeiter_uid=' + this.mitarbeiter_uid + vertragString + '&output=pdf&uid=' + this.mitarbeiter_uid; window.open(linkToPdf, '_blank'); }, -/* toggleRowClick(contractId, status, bezeichnung) { - const index = this.arraySelectedContracts.findIndex( - ([id]) => id === contractId - ); - if (index !== -1) { - this.arraySelectedContracts.splice(index, 1); - } else { - this.arraySelectedContracts.push([contractId, status, bezeichnung]); - } - },*/ toggleRowClick(event, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung) { - if (!this.dataPrintHonorar?.multiselect) return; + const isMulti = this.dataPrintHonorar?.multiselect === true; const isCtrl = event.ctrlKey || event.metaKey; const entry = { @@ -540,28 +509,29 @@ export default { vertragstyp_bezeichnung }; - // Single click - if (!isCtrl) { + // allow MultiSelect just in case event multiActionPrintHonorarvertrag + const allowMultiClick = isMulti && isCtrl; + + if (!allowMultiClick) { this.arraySelectedContracts = [entry]; + + //just mark last selected row as selected + this.$refs.table.tabulator.deselectRow(); + this.$refs.table.tabulator.selectRow(vertrag_id); return; } - // CTRL / CMD → toggle const index = this.arraySelectedContracts.findIndex( e => e.vertrag_id === vertrag_id ); if (index === -1) { this.arraySelectedContracts.push(entry); - //this.arraySelectedContracts.push([entry.vertrag_id, entry.status, entry.bezeichnung, entry.vertragstyp_bezeichnung]); } else { this.arraySelectedContracts.splice(index, 1); } - }, -/* clearSelection(){ - this.arraySelectedContracts = []; - this.$refs.table.tabulator.deselectRow(); - }*/ + + } }, created() { Promise.all([ @@ -587,88 +557,6 @@ export default { }); this.getFormattedDate(); }, - /* - TODO(Manu) delete after check - -
- - -
- -
- - -
-
- - - - -
-
- - -
-
- - -
-
- - -
-
- - -
- */ template: `
From 21d80905a23337bb4f6157737f89236d305c8e60 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Mon, 13 Apr 2026 13:04:46 +0200 Subject: [PATCH 2/6] akzeptierte dokumente anzeigen, auch wenn kein dokument vorhanden ist --- .../api/frontend/v1/stv/Dokumente.php | 46 ++++++------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index b8c7830bd..913a57dc4 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -78,52 +78,32 @@ class Dokumente extends FHCAPI_Controller $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL); $resultPreDoc = $this->_getPrestudentDokumente($prestudent_id); - - $arrayAccepted = []; $person_id = $this->_getPersonId($prestudent_id); - $docNames = array_map(function ($item) { - return $item->dokument_kurzbz; - }, $resultPreDoc); + $mergedArray = []; - foreach($docNames as $doc) + foreach ($resultPreDoc as $pre) { - $result = $this->AkteModel->getAktenFAS($person_id, $doc, $studiengang_kz, $prestudent_id, true); + $result = $this->AkteModel->getAktenFAS($person_id, $pre->dokument_kurzbz, $studiengang_kz, $prestudent_id, true); if (isError($result)) - { return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); - } + if (hasData($result)) { - $data = getData($result); - foreach ($data as $value) + foreach (getData($result) as $doc) { - array_push($arrayAccepted, $value); + $merged = clone $doc; + $merged->docdatum = $pre->docdatum; + $merged->insertvonma = $pre->insertvonma; + $merged->bezeichnung = $pre->bezeichnung; + $mergedArray[] = $merged; } } - } - - //Mapping with document_kurzbz - $preDocMap = []; - foreach ($resultPreDoc as $pre) { - $preDocMap[$pre->dokument_kurzbz] = $pre; - } - - $mergedArray = []; - foreach ($arrayAccepted as $doc) { - $merged = clone $doc; - - if (isset($preDocMap[$doc->dokument_kurzbz])) { - $merged->docdatum = $preDocMap[$doc->dokument_kurzbz]->docdatum; - $merged->insertvonma = $preDocMap[$doc->dokument_kurzbz]->insertvonma; - $merged->bezeichnung = $preDocMap[$doc->dokument_kurzbz]->bezeichnung; - } else { - $merged->akzeptiertdatum = null; - $merged->akzeptiertvon = null; + else + { + $mergedArray[] = $pre; } - - $mergedArray[] = $merged; } $this->terminateWithSuccess($mergedArray); From 26db4a5e7a17ed9f21ac9b99ba1198199f8df4fb Mon Sep 17 00:00:00 2001 From: ma0068 Date: Mon, 20 Apr 2026 09:31:52 +0200 Subject: [PATCH 3/6] adding redraw tabulator and fallback to avoid empty column --- public/js/components/Messages/Details/TableMessages.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/js/components/Messages/Details/TableMessages.js b/public/js/components/Messages/Details/TableMessages.js index aefa8bb2a..02b941fcf 100644 --- a/public/js/components/Messages/Details/TableMessages.js +++ b/public/js/components/Messages/Details/TableMessages.js @@ -195,7 +195,7 @@ export default { ], formatter: (cell, formatterParams) => { const key = formatterParams[cell.getValue()]; - return this.$p.t('messages', key); + return this.$p?.t?.('messages', key) || key; }, }, { @@ -307,6 +307,7 @@ export default { handler: async() => { await this.$p.loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz']); + this.$refs.table.tabulator.redraw(true); //for immediate translation of status const setHeader = (field, text) => { const col = this.$refs.table.tabulator.getColumn(field); if (!col) return; From 090e5354664d97bf6fedf8487005a1b338c3a9aa Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Tue, 5 May 2026 11:04:48 +0200 Subject: [PATCH 4/6] add header filters, increase height of tables, use correct category for phrase lehreinheit_id --- .../js/components/Vertraege/List/Details.js | 26 ++++++++--------- public/js/components/Vertraege/List/Status.js | 19 +++++++------ .../components/Vertraege/List/Unassigned.js | 28 ++++++++++--------- public/js/components/Vertraege/Vertraege.js | 21 +++++++------- 4 files changed, 50 insertions(+), 44 deletions(-) diff --git a/public/js/components/Vertraege/List/Details.js b/public/js/components/Vertraege/List/Details.js index 8df6a6985..c43f8c893 100644 --- a/public/js/components/Vertraege/List/Details.js +++ b/public/js/components/Vertraege/List/Details.js @@ -41,8 +41,8 @@ export default { ), ajaxResponse: (url, params, response) => response.data, columns: [ - {title: "Typ", field: "type"}, - {title: "Betrag", field: "betrag", + {title: "Typ", field: "type", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, + {title: "Betrag", field: "betrag", headerFilter: true, formatter: function(cell) { let value = cell.getValue(); if (value == null) { @@ -51,14 +51,14 @@ export default { return parseFloat(value).toFixed(2); } }, - {title: "Bezeichnung", field: "bezeichnung"}, - {title: "Studiensemester", field: "studiensemester_kurzbz"}, - {title: "Pruefung_id", field: "pruefung_id", visible: false}, - {title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false}, - {title: "projektarbeit_id", field: "projektarbeit_id", visible: false}, - {title: "lehreinheit_id", field: "lehreinheit_id", visible: true}, - {title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false}, - {title: "vertrag_id", field: "vertrag_id", visible: false}, //just for testing + {title: "Bezeichnung", field: "bezeichnung", headerFilter: true}, + {title: "Studiensemester", field: "studiensemester_kurzbz", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, + {title: "Pruefung_id", field: "pruefung_id", visible: false, headerFilter: true}, + {title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false, headerFilter: true}, + {title: "projektarbeit_id", field: "projektarbeit_id", visible: false, headerFilter: true}, + {title: "lehreinheit_id", field: "lehreinheit_id", visible: true, headerFilter: true}, + {title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false, headerFilter: true}, + {title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true}, //just for testing { title: 'Aktionen', field: 'actions', minWidth: 50, @@ -110,10 +110,10 @@ export default { ], layout: 'fitColumns', layoutColumnsOnNewData: false, - height: '200', + height: '250', selectableRowsRangeMode: 'click', selectableRows: true, - persistenceID: 'core-contracts-details-2026021701' + persistenceID: 'core-contracts-details-2026050501' }, tabulatorEvents: [ { @@ -137,7 +137,7 @@ export default { setHeader('type', this.$p.t('global', 'typ')); setHeader('bezeichnung', this.$p.t('ui', 'bezeichnung')); - setHeader('lehreinheit_id', this.$p.t('ui', 'lehreinheit_id')); + setHeader('lehreinheit_id', this.$p.t('lehre', 'lehreinheit_id')); setHeader('betrag', this.$p.t('ui', 'betrag')); setHeader('studiensemester_kurzbz', this.$p.t('lehre', 'studiensemester')); setHeader('mitarbeiter_uid', this.$p.t('ui', 'mitarbeiter_uid')); diff --git a/public/js/components/Vertraege/List/Status.js b/public/js/components/Vertraege/List/Status.js index 531b2f553..53af7bc40 100644 --- a/public/js/components/Vertraege/List/Status.js +++ b/public/js/components/Vertraege/List/Status.js @@ -47,12 +47,13 @@ export default { this.endpoint.getStatiOfContract(this.person_id, this.vertrag_id) ), ajaxResponse: (url, params, response) => response.data, - persistenceID: 'core-contracts-status-2026021701', + persistenceID: 'core-contracts-status-2026050501', columns: [ - {title: "Status", field: "bezeichnung"}, + {title: "Status", field: "bezeichnung", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, { title: "Datum", field: "datum", + headerFilter: true, formatter: function (cell) { const dateStr = cell.getValue(); const date = new Date(dateStr); // Convert to Date object @@ -66,14 +67,15 @@ export default { }); } }, - {title: "vertrag_id", field: "vertrag_id", visible: false}, - {title: "Vertragsstatus", field: "vertragsstatus_kurzbz", visible: false}, - {title: "User", field: "mitarbeiter_uid", visible: false}, - {title: "insertvon", field: "insertvon", visible: false}, + {title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true}, + {title: "Vertragsstatus", field: "vertragsstatus_kurzbz", visible: false, headerFilter: true}, + {title: "User", field: "mitarbeiter_uid", visible: false, headerFilter: true}, + {title: "insertvon", field: "insertvon", visible: false, headerFilter: true}, { title: "insertamum", field: "insertamum", visible: false, + headerFilter: true, formatter: function (cell) { const dateStr = cell.getValue(); const date = new Date(dateStr); @@ -87,11 +89,12 @@ export default { }); } }, - {title: "updatevon", field: "updatevon", visible: false}, + {title: "updatevon", field: "updatevon", visible: false, headerFilter: true}, { title: "updateamum", field: "updateamum", visible: false, + headerFilter: true, formatter: function (cell) { const dateStr = cell.getValue(); const date = new Date(dateStr); @@ -148,7 +151,7 @@ export default { ], layout: 'fitColumns', layoutColumnsOnNewData: false, - height: '200', + height: '250', selectableRowsRangeMode: 'click', selectableRows: true, }, diff --git a/public/js/components/Vertraege/List/Unassigned.js b/public/js/components/Vertraege/List/Unassigned.js index 655a2b078..1b4b728e7 100644 --- a/public/js/components/Vertraege/List/Unassigned.js +++ b/public/js/components/Vertraege/List/Unassigned.js @@ -30,10 +30,11 @@ export default { ), ajaxResponse: (url, params, response) => response.data, columns: [ - {title: "Typ", field: "type", width: 100}, + {title: "Typ", field: "type", width: 100, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, { title: "Betrag", field: "betrag1", + headerFilter: true, formatter: function(cell) { let value = cell.getValue(); if (value == null) { @@ -41,28 +42,29 @@ export default { } return parseFloat(value).toFixed(2); }}, - {title: "Bezeichnung", field: "bezeichnung", width: 150}, - {title: "Studiensemester", field: "studiensemester_kurzbz", width: 160}, - {title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false}, - {title: "projektarbeit_id", field: "projektarbeit_id", visible: false}, - {title: "lehreinheit_id", field: "lehreinheit_id", visible: true}, - {title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false}, - {title: "Vertragsstunden", field: "vertragsstunden", visible: false}, - {title: "vertrag_id", field: "vertrag_id", visible: false}, //just for testing + {title: "Bezeichnung", field: "bezeichnung", width: 150, headerFilter: true}, + {title: "Studiensemester", field: "studiensemester_kurzbz", width: 160, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, + {title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false, headerFilter: true}, + {title: "projektarbeit_id", field: "projektarbeit_id", visible: false, headerFilter: true}, + {title: "lehreinheit_id", field: "lehreinheit_id", visible: true, headerFilter: true}, + {title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false, headerFilter: true}, + {title: "Vertragsstunden", field: "vertragsstunden", visible: false, headerFilter: true}, + {title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true}, //just for testing { title: "VertragsstundenStudiensemester", field: "vertragsstunden_studiensemester_kurzbz", - visible: false + visible: false, + headerFilter: true }, ], layout: 'fitColumns', layoutColumnsOnNewData: false, - height: 150, + height: 250, selectableRowsRangeMode: 'click', selectableRows: true, selectableRowsRollingSelection: false, //only allow multiselect with STRG index: "lehreinheit_id", - persistenceID: 'core-contracts-unassigned-2026021701' + persistenceID: 'core-contracts-unassigned-2026050501' }, tabulatorEvents: [ { @@ -100,7 +102,7 @@ export default { setHeader('type', this.$p.t('global', 'typ')); setHeader('bezeichnung', this.$p.t('ui', 'bezeichnung')); - setHeader('lehreinheit_id', this.$p.t('ui', 'lehreinheit_id')); + setHeader('lehreinheit_id', this.$p.t('lehre', 'lehreinheit_id')); setHeader('betrag1', this.$p.t('ui', 'betrag')); setHeader('studiensemester_kurzbz', this.$p.t('lehre', 'studiensemester')); setHeader('mitarbeiter_uid', this.$p.t('ui', 'mitarbeiter_uid')); diff --git a/public/js/components/Vertraege/Vertraege.js b/public/js/components/Vertraege/Vertraege.js index 30dc593c7..b166e71ba 100644 --- a/public/js/components/Vertraege/Vertraege.js +++ b/public/js/components/Vertraege/Vertraege.js @@ -51,9 +51,9 @@ export default { ), ajaxResponse: (url, params, response) => response.data, columns: [ - {title: "Bezeichnung", field: "bezeichnung", width: 300}, + {title: "Bezeichnung", field: "bezeichnung", width: 300, headerFilter: true}, { - title: "Betrag", field: "betrag", width: 100, + title: "Betrag", field: "betrag", width: 100, headerFilter: true, formatter: function (cell) { let value = cell.getValue(); @@ -63,12 +63,13 @@ export default { return parseFloat(value).toFixed(2); } }, - {title: "Vertragstyp", field: "vertragstyp_bezeichnung", width: 125}, - {title: "Status", field: "status", width: 100}, + {title: "Vertragstyp", field: "vertragstyp_bezeichnung", width: 125, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, + {title: "Status", field: "status", width: 100, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, { title: "Vertragsdatum", field: "vertragsdatum", width: 128, + headerFilter: true, formatter: function (cell) { const dateStr = cell.getValue(); const date = new Date(dateStr); @@ -79,11 +80,11 @@ export default { }); } }, - {title: "VertragId", field: "vertrag_id", visible: false}, - {title: "Vertragsstunden", field: "vertragsstunden", visible: false}, - {title: "VertragsstundenStudiensemester", field: "vertragsstunden_studiensemester_kurzbz", visible: false}, - {title: "Anmerkung", field: "anmerkung", visible: false}, - {title: "isAbgerechnet", field: "isabgerechnet", visible: false}, + {title: "VertragId", field: "vertrag_id", visible: false, headerFilter: true}, + {title: "Vertragsstunden", field: "vertragsstunden", visible: false, headerFilter: true}, + {title: "VertragsstundenStudiensemester", field: "vertragsstunden_studiensemester_kurzbz", visible: false, headerFilter: true}, + {title: "Anmerkung", field: "anmerkung", visible: false, headerFilter: true}, + {title: "isAbgerechnet", field: "isabgerechnet", visible: false, headerFilter: true}, { title: 'Aktionen', field: 'actions', minWidth: 150, @@ -137,7 +138,7 @@ export default { columns: true, filter: false //to avoids js errors }, - persistenceID: 'core-contracts-2026021701', + persistenceID: 'core-contracts-2026050501', }; return options; }, From 50b229090bcf3b86f560751db2de22a7db4da522 Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Tue, 5 May 2026 13:04:11 +0200 Subject: [PATCH 5/6] prefetch phrases and then render filter component instead of redrawing the table --- .../js/components/Messages/Details/TableMessages.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/public/js/components/Messages/Details/TableMessages.js b/public/js/components/Messages/Details/TableMessages.js index 02b941fcf..d523d5362 100644 --- a/public/js/components/Messages/Details/TableMessages.js +++ b/public/js/components/Messages/Details/TableMessages.js @@ -30,6 +30,7 @@ export default { personId: null, layoutColumnsOnNewData: false, height: '400', + arePhrasesLoaded: false } }, methods: { @@ -305,9 +306,6 @@ export default { { event: 'tableBuilt', handler: async() => { - await this.$p.loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz']); - - this.$refs.table.tabulator.redraw(true); //for immediate translation of status const setHeader = (field, text) => { const col = this.$refs.table.tabulator.getColumn(field); if (!col) return; @@ -358,6 +356,12 @@ export default { });*/ }, created(){ + this.$p + .loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz']) + .then(() => { + this.arePhrasesLoaded = true; + }); + if(this.typeId != 'person_id' && Array.isArray(this.id) && this.id.length === 1) { const params = { id: this.id, @@ -382,6 +386,7 @@ export default {
Date: Tue, 5 May 2026 14:36:07 +0200 Subject: [PATCH 6/6] bugfix download booking receipt failed. only fetch oehbeitrag from bis.tbl_oehbeitrag if a user is logged in --- include/konto.class.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/konto.class.php b/include/konto.class.php index da76c147f..d3167d5f5 100644 --- a/include/konto.class.php +++ b/include/konto.class.php @@ -1004,6 +1004,11 @@ class konto extends basis_db private function _getOEHBeitrag() { + if(!is_user_logged_in()) + { + return false; + } + $variablen_obj = new variable(); $variablen_obj->loadVariables(get_uid());