Compare commits

...
Author SHA1 Message Date
Ivymaster c91a6c6376 Reverted to original eventLoader 2026-09-09 13:09:48 +02:00
Ivymaster ed02955b49 BUG: Fixed issue with event reload span 2026-09-09 13:08:49 +02:00
Ivymaster 63af8efb44 Conflict resolved 2026-09-07 18:00:00 +02:00
Andreas Österreicher f2d4840af6 Merge branch 'feature-78052/tempus-tag-events' into feature-68298/Tempus_Grundstruktur 2026-09-07 15:04:23 +02:00
Ivymaster cde51fa165 BUG: Reintroduced status icon on tempus calender event 2026-09-07 14:31:40 +02:00
Ivymaster 22fd4f199e BUG: Rework of setEmp in tempus component 2026-09-03 11:27:11 +02:00
Ivymaster 3e9788dcbf BUG: Removed duplicates of setEmp in tempus component 2026-09-03 11:21:03 +02:00
Ivymaster faa8f0446c Conflicts resolved 2026-09-03 11:11:10 +02:00
ma0048 4c2cd86b6d restore deleted setemp function 2026-09-03 11:06:25 +02:00
Ivymaster 563fda603a BUG: Room suggestions preview 2026-09-03 11:02:02 +02:00
ma0048 492c9a0140 fix: rebuild Raumvorschlag after adding event 2026-09-02 15:28:05 +02:00
Ivymaster 02ff8d0e3c Conflicts resolved 2026-09-02 15:01:56 +02:00
ma0048 90f62a7a9e - merged master
- added raumvorschlag slots
2026-09-02 10:54:36 +02:00
Ivymaster 669e03b915 Conflicts resolved 2026-09-01 13:19:17 +02:00
Ivymaster 3c333af184 Minor bug fixes 2026-09-01 13:15:29 +02:00
ma0048 eeb49e1967 Merge remote-tracking branch 'origin/feature-78287/tempus_raumzuordnung' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	application/libraries/KalenderLib.php
#	application/libraries/RaumvorschlagLib.php
2026-09-01 13:08:38 +02:00
ma0048 1d61652b67 Merge remote-tracking branch 'origin/feature-78211/tempus_kollisionscheck_auf_lehreinheit_id_umbauen_' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	application/libraries/KalenderLib.php
2026-09-01 12:59:22 +02:00
ma0048 8a448fde3c Merge remote-tracking branch 'origin/feature-78288/tempus_usability' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	public/css/components/horizontalsplit.css
#	public/js/components/Tempus/Filters/searchbarOptions.js
2026-09-01 12:48:07 +02:00
ma0048 1361c3fc00 Merge remote-tracking branch 'origin/feature-78286/tempus_berechtigungen' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	application/controllers/api/frontend/v1/tempus/Coursepicker.php
#	application/libraries/KalenderLib.php
2026-09-01 12:42:16 +02:00
ma0048 d727012806 Merge remote-tracking branch 'origin/feature-78285/tempus_stundenraster_ausschalten_nur_mit_eigener_berechtigung' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	system/dbupdate_3.4.php
2026-09-01 12:32:38 +02:00
ma0048 b91ba9fdbb Merge remote-tracking branch 'origin/feature-78324/tempus_coursepicker_lektor' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	application/controllers/api/frontend/v1/tempus/Coursepicker.php
#	public/js/components/Tempus/Coursepicker.js
2026-09-01 12:28:32 +02:00
ma0048 e311d7ee00 Merge remote-tracking branch 'origin/feature-78289/tempus_parken_features' into feature-68298/Tempus_Grundstruktur 2026-09-01 12:22:25 +02:00
ma0048 357a51bdcb Merge remote-tracking branch 'origin/feature-78317/tempus_delete_status' into feature-68298/Tempus_Grundstruktur 2026-09-01 12:21:53 +02:00
ma0048 61ef27e5eb Merge branch 'feature-77949/tempus_synchronisation' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	application/libraries/KalenderLib.php
#	system/dbupdate_3.4.php
2026-09-01 12:20:12 +02:00
ma0048 a26b75bc3c Merge remote-tracking branch 'origin/feature-78179/tempus_listenansicht_datumfilter' into feature-68298/Tempus_Grundstruktur 2026-09-01 12:17:16 +02:00
Ivymaster 61d7268f90 Conflicts resolved 2026-09-01 11:52:25 +02:00
ma0048 fb36b2a548 - merged master
- updaed Verbandsbaum to work with the new version
2026-08-31 14:58:27 +02:00
ma0048 51886960bb Merge branch 'master' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	application/controllers/api/frontend/v1/lv/StgTree.php
#	public/js/components/Stv/Studentenverwaltung/Verband.js
#	system/dbupdate_3.4.php
#	tests/cypress/.gitignore
2026-08-31 12:49:28 +02:00
ma0048 98be0b43b7 - permissions geandert 2026-08-27 08:08:34 +02:00
ma0048 4cbf37d727 - ueberpruefung der berechtigung auf den studiengang von der lv beim verschieben/hinzufuegen/loeschen der lehreinheit 2026-08-27 08:07:39 +02:00
ma0048 623e8007b0 - sichtbarkeitsstatus hinzugefuegt
- tage ausblendbar
- lektor zur lvverwaltung verlinkt
- vertical splitter hinzugefuegt
- anzahl der einheiten hinzugefuegt
2026-08-26 09:01:47 +02:00
Harald Bamberger 6d641bbd06 pass in uid by reference 2026-08-24 13:56:55 +02:00
Harald Bamberger 3455aed3f5 Merge branch 'bhdev_master_stundenplan' 2026-08-24 13:46:09 +02:00
Harald Bamberger f84d12277d remove debug code 2026-08-24 07:31:47 +02:00
Harald Bamberger 9bf5bc2ad9 more generic bugfix, to use studentlehrverband only with date_range for the same studiensemester_kurzbz 2026-08-24 07:26:12 +02:00
Harald Bamberger 27765606e3 bufix akadGrad by sex if exists 2026-08-20 19:31:37 +02:00
Harald Bamberger 75d2cabdbe bugfix lv-plan 2026-08-20 15:10:26 +02:00
Harald Bamberger bae9d6d9a0 Merge branch 'feature-78257/StudVW_Und_Tags_Finetuning' 2026-08-19 17:11:12 +02:00
Harald Bamberger 43d6a882ce add padding to tags buttons, remove orphanded template closing tag 2026-08-19 17:07:25 +02:00
Harald Bamberger 7f3b4100ab Merge branch 'master' into feature-78257/StudVW_Und_Tags_Finetuning 2026-08-19 15:07:07 +02:00
Harald Bamberger 9f54ecce54 Merge branch 'epic/LVEvaluierung-Neu' 2026-08-19 13:59:00 +02:00
Cristina 7af0f4a478 Merge remote-tracking branch 'origin/epic/LVEvaluierung-Neu' into epic/LVEvaluierung-Neu 2026-08-19 13:35:25 +02:00
Cristina 0f843db33d Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-19 13:34:53 +02:00
Cristina 3e59648d5b Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-19 12:55:38 +02:00
Cristina 5923991848 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-19 12:55:03 +02:00
Harald Bamberger 55a6ec9d0d fix handling of grundbetrag and betrag_valorisiert 2026-08-19 11:48:22 +02:00
chfhtw 78505589c8 Bugfix: racecondition renderers 2026-08-19 09:45:15 +02:00
Harald Bamberger 0e985113ec Merge branch 'feature-77666/Details_anzeigen_der_Valorisierung_pro_Person' 2026-08-19 08:20:42 +02:00
Harald Bamberger 8d9113d5c8 Merge branch 'master' into feature-77666/Details_anzeigen_der_Valorisierung_pro_Person 2026-08-19 08:06:16 +02:00
Harald Bamberger 7ce81ad4bd Merge branch 'feature-78292/dv_gehaltsbestandteil_ersteinstufung' 2026-08-19 07:57:07 +02:00
Harald Bamberger ea56ec8daa change wording 2026-08-19 07:50:50 +02:00
Harald Bamberger bf5ee2f64b Merge branch 'feature-78139/CIS4_Dashboard_ausgeblendete_Widgets' 2026-08-18 17:51:40 +02:00
Harald Bamberger 55d6d90fa6 Merge branch 'master' into feature-78139/CIS4_Dashboard_ausgeblendete_Widgets 2026-08-18 17:47:13 +02:00
Harald Bamberger 6adc55a843 Merge branch 'feature/78128-quick-copy-full-name-and-title' 2026-08-18 17:39:44 +02:00
Harald Bamberger 52c1fba17b Merge branch 'bugfix/78127-degree-programs-page-localization-ineffective' 2026-08-18 16:53:49 +02:00
Cristina 5e15d4b219 Add Distinct to getLeitung in Studiengang_model.php
Avoid multiple records for same active STGL.
e.g. double entries
2026-08-18 16:51:39 +02:00
Harald Bamberger 00954f680b Merge branch 'bugfix/78392-missing-searchbar-is-mobile-injectable' 2026-08-18 16:48:43 +02:00
Harald Bamberger 92d27fc242 Merge branch 'master' into feature/78128-quick-copy-full-name-and-title 2026-08-18 14:52:41 +02:00
Harald Bamberger f6bb27cdb0 Merge branch 'master' into bugfix/78127-degree-programs-page-localization-ineffective 2026-08-18 14:49:16 +02:00
Harald Bamberger 558963cd74 Merge branch 'master' into feature-78139/CIS4_Dashboard_ausgeblendete_Widgets 2026-08-18 14:42:44 +02:00
Harald Bamberger 0b5c0f27a5 Merge branch 'bugfix/77738-persisting-lv-menu' 2026-08-14 11:58:42 +02:00
adisposkofh f846bb221a refetching lv menu after a different calendar event is selected 2026-08-14 11:47:31 +02:00
Werner Masik d8355ba3f5 added Funktionsänderung to gehaltsanpassungtyp 2026-08-13 14:56:04 +02:00
ma0048 8184555e12 location hinzugefuegt
raumlose planung aktivierbar/deaktivierbar
automatische zuteilung zum priorraum aktivierbar/deaktivierbar
raum zuteilung ueber dialog aktivierbar/deaktivierbar
2026-08-13 13:36:35 +02:00
ma0068 afb8011347 bugfix manual rebuilding of Tag ZGV Missing 2026-08-13 12:57:49 +02:00
Harald Bamberger 6d5a4531e1 use tbl_studentlehrverband.semester instead of tbl_student.semester 2026-08-12 16:58:21 +02:00
Werner Masik d85a3cb08f extract DB migration for gehaltsanpassungtyp into separate file 2026-08-12 15:18:35 +02:00
ma0068 15beaa9be8 Merge branch 'feature-78257/StudVW_Und_Tags_Finetuning' of github.com:FH-Complete/FHC-Core into feature-78257/StudVW_Und_Tags_Finetuning 2026-08-12 12:42:10 +02:00
ma0068 574057da88 add masterzgv to CoremissingZgvLib 2026-08-12 12:41:39 +02:00
Harald Bamberger c81b5338de Merge branch 'master' into feature-78292/dv_gehaltsbestandteil_ersteinstufung 2026-08-12 11:39:49 +02:00
ma0048 b2aa4c4922 stundenraster mit eigener berechtigung basis/tempus_stundenraster deaktivierbar 2026-08-12 11:39:17 +02:00
Harald Bamberger c433ff5c3a remove public/vendor symlink since created by composer install 2026-08-12 11:39:16 +02:00
Harald Bamberger ab2a0e93ed add public/vendor to .gitignore 2026-08-12 11:38:02 +02:00
ma0048 b5ac68840b fixed bug after column rename 2026-08-12 11:31:05 +02:00
ma0048 33b50bf479 course picker
- kurse vom lektor koennen angezeigt werden
- searchbar button hinzuefuegt um kurse vom lektor im course picker zu laden
2026-08-12 11:10:07 +02:00
Harald Bamberger d139c4ed66 Merge branch 'bug-78432/StudVw_Baum_fehlende_Route' 2026-08-12 10:23:23 +02:00
chfhtw dd410a74ba Add missing routes for StudVw 2026-08-12 10:14:02 +02:00
ma0048 b0cb79d316 - geparkte Stunden im Parkfenster koennen entfernt werden
- sprung zur Woche
- farbe der lv
2026-08-12 08:26:40 +02:00
Harald Bamberger a5797a0bde Merge branch 'master' into feature-78257/StudVW_Und_Tags_Finetuning 2026-08-11 18:00:17 +02:00
Harald Bamberger 5c69ede19e Merge branch 'feature-78257/StudVW_Finetuning' 2026-08-11 17:53:06 +02:00
Harald Bamberger a5257eb934 rearange tiles, use placeholder if uid is not set 2026-08-11 17:50:33 +02:00
Harald Bamberger 317da29376 Merge branch 'master' into feature-78257/StudVW_Finetuning 2026-08-11 16:26:36 +02:00
adisposkofh 772b8c603c fixed issue with ineffective localization of courses in 'degree programs' page 2026-08-11 15:50:24 +02:00
Cristina 37d5f2da5d Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-11 15:45:27 +02:00
Cristina 27c39cfdca Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-11 15:45:08 +02:00
chfhtw 30c4e565dd bugfix: sprache index in studentlistlib corrected 2026-08-11 15:08:34 +02:00
ma0048 015c8ca0f1 kollisionscheck auf lehreinheit_id umgebaut
raumvorschlag by lehreinheit hinzuegfuegt
2026-08-11 11:48:29 +02:00
Werner Masik d66fe72cc9 add field for salary adaption type (Ersteinstufung, indiv. Erhöhung, ..) 2026-08-11 11:18:36 +02:00
Harald Bamberger 684d4f890a Merge branch 'master' into feature-78257/StudVW_Finetuning 2026-08-11 10:49:05 +02:00
Harald Bamberger 10218305db Merge branch 'bug-78116/StudStatus_sendStglSammelmail_empty_list' 2026-08-11 10:40:26 +02:00
ma0068 31bae9b693 use function getStgAndDetails instead of getStgAndSem 2026-08-11 09:48:17 +02:00
adisposkofh 59ac56374e removed redundant response meta used for dev 2026-08-11 09:44:41 +02:00
adisposkofh a397460e0e Merge branch 'master' into feature/78128-quick-copy-full-name-and-title 2026-08-11 09:43:27 +02:00
Harald Bamberger c3c23d28bb Merge branch 'feature-76995/StudStatusModal_Hinweis_Beratungsgespraech_bei_Abmeldung' 2026-08-11 09:22:26 +02:00
Harald Bamberger 9f0b387ab6 use phrase ui/cancel instead of ui/abbrechen 2026-08-11 09:21:48 +02:00
Harald Bamberger 3a97f20122 add v-bind syntax to avoid prop type warning 2026-08-11 09:08:32 +02:00
Harald Bamberger 046a552f34 Merge branch 'master' into feature-76995/StudStatusModal_Hinweis_Beratungsgespraech_bei_Abmeldung 2026-08-11 08:11:55 +02:00
Harald Bamberger e8a534f0fe Cis MyLv Endpoints only require logged in user 2026-08-11 07:52:02 +02:00
Harald Bamberger 1f21ed7364 Merge branch 'feature-69378/Studienverlauf_verlinken_im_neuen_FAS' 2026-08-10 18:22:28 +02:00
Harald Bamberger 774a1b81c4 grades: change layout semester mode dropdown and gradelist link, details: remove css class from noImage img tag 2026-08-10 18:21:24 +02:00
Harald Bamberger f566ea1ac3 Merge branch 'master' into feature-69378/Studienverlauf_verlinken_im_neuen_FAS 2026-08-10 18:06:00 +02:00
adisposkofh 108f91ea1a quick copy option on full name and title in profile and other lv plan 2026-08-10 17:09:31 +02:00
Harald Bamberger 4a92511b9b Merge branch 'tabulator-localization-minor-fixes' 2026-08-10 17:04:31 +02:00
adisposkofh dc5a846c10 defaulting searchbar isMobile injectable to false when not provided 2026-08-10 16:24:58 +02:00
adisposkofh 364477f0e9 merged master into 2026-08-10 15:58:21 +02:00
adisposkofh d2ca33e757 Merge branch 'master' into tabulator-localization-minor-fixes 2026-08-10 15:57:12 +02:00
Harald Bamberger 8bfd90e159 Merge branch 'master' into feature-69378/Studienverlauf_verlinken_im_neuen_FAS 2026-08-10 14:48:41 +02:00
Harald Bamberger 8d8a4e8ca6 Merge branch 'feature/76688-general-tabulator-issues_77080-persistence' 2026-08-10 14:29:40 +02:00
ma0068 06895510e0 add reloadList if language is changed 2026-08-10 14:25:07 +02:00
ma0068 83b06b6c50 - Redesign Tags
- use Slot in Filter Component
- use Phrase  for relaoding Tag in Detail Header
2026-08-10 14:04:45 +02:00
Harald Bamberger d710b4a9e4 Merge branch 'master' into feature/76688-general-tabulator-issues_77080-persistence 2026-08-10 13:11:12 +02:00
Werner Masik bd99f3f927 add db schema for gehaltsanpassungtyp 2026-08-10 12:20:30 +02:00
Cristina eeb1529b64 Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-10 12:07:45 +02:00
Cristina 98c3707802 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-10 12:07:01 +02:00
adisposkofh 43e9dad17d double checking if tabulator header filter inputs are filled in on preset application 2026-08-10 11:06:17 +02:00
ma0048 b58b4446a9 todelete auf to_delete umebannnt
to_delete_live & to_delete_preview hinugefuegt
history logik umbau
2026-08-10 10:57:34 +02:00
ma0048 c6f85b493a loader hinzugefuegt 2026-08-10 10:54:28 +02:00
Harald Bamberger a27fa50e42 Merge branch 'studvw_lvvw_2026_08_rc_77973_76688' 2026-08-10 09:16:11 +02:00
Harald Bamberger 196e9be728 comment in groups in lvvw treemenu to have them for drag and drop, add language and isMobile injects to prevent warnings from searchbar component, studvw clear selection when degree program changes, update fontawesome from 6.1.1 to 6.7.2 and primeicons from 5.0.0 to 6.0.1 to prevent glyph bbox warnings in ff browser console 2026-08-10 06:48:53 +02:00
Harald Bamberger a00f6363d9 add legacy bis links to app menu and needed phrases, consistently use appMenuLvPlanungItems computed for LvPlanung app menu extra items 2026-08-07 17:11:38 +02:00
adisposkofh a65b0d693f implemented spinner while tabulator preset is being applied 2026-08-07 12:02:52 +02:00
Harald Bamberger 736e897928 fix automated tags not found in stv search 2026-08-06 16:23:54 +02:00
Harald Bamberger 21f8bb39b5 reload list after rebuild tags for degree program or selection 2026-08-06 16:04:35 +02:00
Harald Bamberger cd87ecc2d9 fix assign batchUser 2026-08-06 15:00:35 +02:00
adisposkofh a3ae14b3f5 Merge branch 'master' into feature/76688-general-tabulator-issues_77080-persistence 2026-08-06 14:08:55 +02:00
adisposkofh 6cf4458dcd fixed ordering of columns in column filter while preset ios applied 2026-08-06 14:06:25 +02:00
Harald Bamberger 59b8d195c1 reaply TagHelper from 77417 to fix adding tags without reloading stv studentlist 2026-08-06 13:52:59 +02:00
Ivymaster 1b23662a54 Add kalender column rename from eindeutige_gruppen_id to eindeutige_kalender_gruppen_id 2026-08-06 13:46:11 +02:00
Ivymaster 96526be231 Add kalender column rename from eindeutige_gruppen_id to eindeutige_kalender_gruppen_id 2026-08-06 13:43:20 +02:00
ma0068 7926a2b201 add Tile PrestudentID to FHC Header 2026-08-06 13:26:33 +02:00
Ivymaster a912fcf019 Add kalender column rename from eindeutige_gruppen_id to eindeutige_kalender_gruppen_id 2026-08-06 13:20:51 +02:00
Harald Bamberger b6aa459b98 Merge branch 'feature-777242/StudVW_alternative_Contacting_ma0080' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-06 11:56:18 +02:00
Harald Bamberger 53a9fab70b use neutral phrase for webmail 2026-08-06 09:43:02 +02:00
Harald Bamberger 5182f13bdb add checked indicator to webmail client links when clicked 2026-08-06 09:34:16 +02:00
Harald Bamberger 804dfc9327 refactor and add localStorage for webmail mode 2026-08-06 08:14:05 +02:00
Harald Bamberger 74e2d1dcc5 ensure tabulator is rendered after required phrases are loaded, apply optionalTabulatorOptions column visibility if set and localstorage does not already contain user preferences 2026-08-06 07:46:16 +02:00
Cristina e5c8807f17 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-05 15:13:35 +02:00
ma0048 626bc121d1 listenansicht datepicker range hinzugefuegt 2026-08-05 14:45:28 +02:00
Harald Bamberger af9e34a8ae Merge branch 'feature/76688-general-tabulator-issues_77080-persistence' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-05 13:48:03 +02:00
Harald Bamberger 10a97a80de add missing nav-language component import 2026-08-05 13:35:51 +02:00
ma0048 785246f58f fixed Sync Bug - Planning -> Voransicht -> Live -> Planning -> Voransicht -> Delete lässt einträge in der History auf Live 2026-08-05 12:35:41 +02:00
ma0048 a74f679917 fixed Sync Bug - Planning -> Voransicht -> Live -> Planning -> Voransicht -> Delete lässt einträge in der History auf Live 2026-08-05 12:14:53 +02:00
ma0048 6282cb0402 hinzugefuegt:
- alle anzeigen option
- jetzt starten knopf
- oe rekursiv
2026-08-05 11:12:33 +02:00
Ivymaster a5715571e8 BUG: Fix for issue with reload of modified events 2026-08-05 08:56:26 +02:00
Ivymaster 0df66047fe BUG: Fix for irelavant req that falls in cache range 2026-08-04 17:38:24 +02:00
Ivymaster 36a11ec2fd WIP: Adding custom tempus event loader 2026-08-04 17:03:47 +02:00
Harald Bamberger abd2f831f2 Merge branch 'studvw_lvvw_2026_08_rc' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-04 16:58:03 +02:00
Harald Bamberger 9d7f48f52c Merge branch 'master' into studvw_lvvw_2026_08_rc 2026-08-04 16:57:43 +02:00
Harald Bamberger dd1a5064e4 tabs: add padding to prevent minimal horizontal scrolling 2026-08-04 16:54:53 +02:00
Harald Bamberger a3ca578b3d Merge branch 'studvw_lvvw_2026_08_rc' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-04 16:13:55 +02:00
Harald Bamberger e37321eeff Merge branch 'master' into studvw_lvvw_2026_08_rc 2026-08-04 16:13:36 +02:00
adisposkofh 505c71b18c reworked applying tabulator presets for efficiency 2026-08-04 16:10:40 +02:00
Harald Bamberger efde2e9601 Merge branch 'feature-76201/StudVWTabsBeibehalten' 2026-08-04 16:05:56 +02:00
Harald Bamberger 8f34142599 Merge branch 'master' into feature-76201/StudVWTabsBeibehalten 2026-08-04 16:04:01 +02:00
Harald Bamberger 6570cc1fd7 Merge branch 'bug-76780/StudVW_Messages_MultiAction_lock_SendButton_and_Modal_during_Sending' 2026-08-04 15:52:44 +02:00
Harald Bamberger fed0afd426 Merge branch 'master' into bug-76780/StudVW_Messages_MultiAction_lock_SendButton_and_Modal_during_Sending 2026-08-04 15:46:03 +02:00
Harald Bamberger 2c2c6efc5e Merge branch 'studvw_lvvw_2026_08_rc' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-04 15:41:37 +02:00
Harald Bamberger 0419286557 Merge branch 'master' into studvw_lvvw_2026_08_rc 2026-08-04 15:41:05 +02:00
Harald Bamberger 08f6bee2e4 Merge branch 'feature-775595/StudVW_Notizen_konfigurierbar' 2026-08-04 15:34:30 +02:00
Harald Bamberger cfa4dd8b8a add padding to filtercomponent tabulator-tableholder to prevent scrollbar covering a row in tables with few rows 2026-08-04 15:33:36 +02:00
Harald Bamberger ab637ded26 stv config: change default for notes showErweitert to false 2026-08-04 15:12:17 +02:00
Harald Bamberger 4c072aa819 Merge branch 'master' into feature-775595/StudVW_Notizen_konfigurierbar 2026-08-04 14:49:08 +02:00
Harald Bamberger f693f9d17c add padding to tabulator container, e.g. to make resizing of last column possible 2026-08-04 14:45:53 +02:00
Ivymaster 45b0268105 BUG: Added reload of events on lang change, for tag display update 2026-08-04 11:35:06 +02:00
chfhtw 2f86a1b017 Changing the edit button into a toggle 2026-08-04 10:46:08 +02:00
chfhtw 75ddbdf7c1 Recovery items on top 2026-08-04 10:24:29 +02:00
chfhtw d824334538 Hiding widgets should look like deleting and recovering is moved to the "add widget" popup 2026-08-04 09:42:18 +02:00
chfhtw 13515b2522 Bugfix: after a drag and drop operation, when resizing the page, the moved item stays in the drop position even if it has had a position in the resized layout 2026-08-04 09:40:47 +02:00
Harald Bamberger ecfe648bf5 Merge branch 'master' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-03 19:36:18 +02:00
Harald Bamberger bddd7b5d65 Merge branch 'bugfix/78150-other-lv-plan-displays-locked-profile-pics' 2026-08-03 19:31:12 +02:00
Harald Bamberger 2686aee158 avoid multiple assignments to one variable 2026-08-03 19:30:49 +02:00
Harald Bamberger b7a2198057 Merge branch 'feature/76688-general-tabulator-issues_77080-persistence' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-03 17:04:34 +02:00
Harald Bamberger bf6b588675 only select active rows with ctrl + a 2026-08-03 17:02:43 +02:00
adisposkofh b427788e04 renamed tabulator presets-related phrases 2026-08-03 17:02:40 +02:00
Harald Bamberger e7e561a4ba Merge branch 'feature/76688-general-tabulator-issues_77080-persistence' into studvw_lvvw_2026_08_rc_77973_76688 2026-08-03 16:29:21 +02:00
adisposkofh d9972c0d32 Merge branch 'feature/76688-general-tabulator-issues_77080-persistence' of github.com:FH-Complete/FHC-Core into feature/76688-general-tabulator-issues_77080-persistence 2026-08-03 16:28:16 +02:00
adisposkofh 6c03110442 removed redundant collapse-auto directives from table presets 2026-08-03 16:27:50 +02:00
adisposkofh f717fb462f fixed issue with tabulator applying preset before table is built 2026-08-03 16:27:26 +02:00
Harald Bamberger 640a7285e1 activate presets for stv list table and add default preset 2026-08-03 16:08:22 +02:00
Harald Bamberger e9fc0629f5 Merge branch 'feature/76688-general-tabulator-issues_77080-persistence' into studvw_lvvw_2026_08_rc_77973 2026-08-03 16:06:34 +02:00
Harald Bamberger 6f0279d451 Merge branch 'master' into feature/76688-general-tabulator-issues_77080-persistence 2026-08-03 14:58:07 +02:00
Harald Bamberger 2d73f97a25 Merge branch 'studvw_lvvw_2026_08_rc' into studvw_lvvw_2026_08_rc_77973 2026-08-03 14:49:42 +02:00
Harald Bamberger dcd6163198 fix typo 2026-08-03 14:49:11 +02:00
ma0048 3e34ea3917 fixed drops in pauses 2026-08-03 14:27:39 +02:00
ma0048 8636364c08 Merge branch 'feature-68298/Tempus_Grundstruktur' into feature-77949/tempus_synchronisation
# Conflicts:
#	system/dbupdate_3.4.php
2026-08-03 12:31:07 +02:00
Harald Bamberger 9f68fe6b3b Merge branch 'feature-77973/StudVw-Feedback_Finetuning_bhmod' into studvw_lvvw_2026_08_rc 2026-08-03 11:18:34 +02:00
Harald Bamberger 7c9f6d89d6 move setting index_bezeichnung_mehrsprachig to StudentListLib 2026-08-03 10:43:53 +02:00
ma0048 5ff43e0abd getoffenestunden archived, deleted, todelete nicht beruecksichtigen 2026-08-03 09:46:29 +02:00
Ivymaster 7759884d8d Add max daily event amount limit for month view 2026-08-03 09:42:23 +02:00
Ivymaster 9352d5cd46 Add disabling of collision check for month view 2026-08-03 09:40:10 +02:00
Harald Bamberger ea3d01d23b rebuild tags for degree programm or selection - split in multiple requests and render progressbar in loading modal 2026-08-03 08:37:45 +02:00
Harald Bamberger c4ffc7283d Merge branch 'master' into bug-76780/StudVW_Messages_MultiAction_lock_SendButton_and_Modal_during_Sending 2026-07-31 17:06:30 +02:00
Harald Bamberger 0fa663145d Merge branch 'master' into studvw_lvvw_2026_08_rc 2026-07-31 17:04:26 +02:00
Harald Bamberger b49831cae8 Merge branch 'bug-77253/StudVw_Abschlusspuefung_ImproveDropDownAkadGrad' 2026-07-31 16:59:30 +02:00
Harald Bamberger c616e9d450 Merge branch 'master' into bug-77253/StudVw_Abschlusspuefung_ImproveDropDownAkadGrad 2026-07-31 16:42:28 +02:00
Harald Bamberger 9b0607ca74 use refactored routes 2026-07-31 16:34:32 +02:00
Harald Bamberger 3d728fd884 Merge branch 'master' into studvw_lvvw_2026_08_rc 2026-07-31 15:51:35 +02:00
Ivymaster cc8e7493e2 Added removal of mounted click listeners for detached divs 2026-07-31 13:29:04 +02:00
chfhtw 2b4aef5633 Merge branch 'feature-77417/studvw-tags-formatter-and-header-filter' into studvw_lvvw_2026_08_rc 2026-07-31 12:52:29 +02:00
Harald Bamberger dca30dccf3 Merge branch 'bug-78215/LVPlanEintraege_in_Sommerluecke_werden_nicht_immer_angezeigt' 2026-07-31 11:05:54 +02:00
Harald Bamberger b9d4aefd5e add meta info 2026-07-31 11:02:46 +02:00
ma0048 cc3b47a10e Raumzuteilung Entfernen / Hinzufuegen von Raeumen
Lehreinheiten entfernen
2026-07-31 10:34:15 +02:00
Harald Bamberger 69048f8f48 bugfix semester calculation between semesters 2026-07-31 09:51:04 +02:00
Ivymaster bb6dfd4d64 BUG: Fix for concatinating date range in calendar month mode 2026-07-30 17:24:44 +02:00
Ivymaster 4bc858dc48 BUG: Fix for concatinating date range in calendar week mode 2026-07-30 17:18:55 +02:00
Ivymaster 98cf44de7f BUG: Fix exc tempus tag modal closing, and tag translations 2026-07-29 17:18:51 +02:00
adisposkofh 36fe0a0f3c including non-localized column title in column filter collapsible 2026-07-29 15:26:07 +02:00
adisposkofh c5e296d557 replacing language injectable with computed property 2026-07-29 13:48:08 +02:00
adisposkofh d1ca6eb988 reworked other lv plan view data controller using profil library 2026-07-29 11:28:13 +02:00
adisposkofh be4db980ad fixed issue with displayed locked profile images in other lv plan 2026-07-29 11:17:03 +02:00
ma0048 0ef905c6f2 use language index 2026-07-29 11:15:24 +02:00
ma0048 21f0b18af4 merged #75959 and added horizontalsplit to lvverwaltung 2026-07-29 10:52:02 +02:00
adisposkofh 6a786df198 disabling columns, header filters, sort persistence in tabulator where presets are used 2026-07-29 09:56:00 +02:00
ma0048 4e16220da1 Merge remote-tracking branch 'origin/feature-75959/StudVw_Automatische_Tags' into studvw_lvvw_2026_08_rc
# Conflicts:
#	application/controllers/api/frontend/v1/stv/Students.php
2026-07-29 09:53:48 +02:00
Harald Bamberger 5ce02d747c lvvw apps menu fix reports links using studiengang_kz 2026-07-29 08:50:50 +02:00
Harald Bamberger 9c31b27339 set vuejs app names 2026-07-28 16:23:56 +02:00
Harald Bamberger aa52c32d40 Merge branch 'feature-77372/lv_verwaltung_release_fine_tuning' into studvw_lvvw_2026_08_rc 2026-07-28 15:50:06 +02:00
Harald Bamberger 02a97fb0e2 Merge branch 'feature-76160/StudVw_Verbandsbaum_durch_Extensions_erweiterbar_machen' into studvw_2026_08_rc 2026-07-28 15:35:54 +02:00
adisposkofh 2107c0839f removed obsolete testing lines in lvv 2026-07-28 12:49:40 +02:00
adisposkofh b277725cc3 displaying name of applied tabulator preset (w/ 'modified' marker as necessary) 2026-07-28 12:48:28 +02:00
Harald Bamberger aade60179d Merge branch 'master' into studvw_2026_05_rc_tags 2026-07-28 11:46:32 +02:00
ma0048 f907a12d19 - added room selection for reservations
- fixed reservation bug without a room
- added KW search to the course picker
- fixed room updates so no assigned rooms are lost
2026-07-28 09:20:20 +02:00
adisposkofh e029b09add persisting tabulator preset in local storage 2026-07-27 16:53:07 +02:00
adisposkofh 47b9e6c086 removed redundant declared emit in tabulator presets 2026-07-27 16:11:47 +02:00
adisposkofh 2fa8fd1703 resolved warning; checking tabulator init before calling getLang in custom module 2026-07-27 16:08:17 +02:00
adisposkofh 89ea4187fa merged master into 2026-07-27 15:58:08 +02:00
chfhtw 0e099b2752 Remove deprecated files and lv_favorites variable 2026-07-24 14:05:50 +02:00
ma0048 32a7e28c80 fix: correct drop time when dropping onto an existing event 2026-07-24 12:37:38 +02:00
chfhtw d7f383b969 stud & lv verwaltung: add component to each route (childroutes should inherit those but a warning is thrown) 2026-07-24 10:57:40 +02:00
Ivymaster 1f2da90eb3 Add extraction of sidebar menu component from tempus component 2026-07-24 09:57:40 +02:00
Ivymaster 12ddcfff48 Add extraction of app and verband menu components from tempus component 2026-07-24 09:33:36 +02:00
Ivymaster e08ae7b331 Add extraction of header component from tempus component 2026-07-24 09:26:05 +02:00
Ivymaster 4a9f41160f Add smoke test for calendar event tag assignment 2026-07-24 09:16:40 +02:00
ma0048 a22a8acf83 fixed drag and drop 2026-07-24 09:12:12 +02:00
chfhtw 5c7df11ff3 Phrase corrected 2026-07-23 15:05:26 +02:00
chfhtw c83674fc41 StudentListLib: store where clauses and add it in later in execute function to prevent errors like in Task:78115 2026-07-23 15:05:11 +02:00
ma0068 dcd17bb34f add Compatibility Mode for SOGO
add logic for BCC to default Mail Client Version
add phrases
2026-07-23 11:25:22 +02:00
Harald Bamberger ed1925b517 Merge branch 'master' into feature-76160/StudVw_Verbandsbaum_durch_Extensions_erweiterbar_machen 2026-07-23 09:11:43 +02:00
Ivymaster 4e21bb37d3 add tagsAssignmentModal extraction from tempus component 2026-07-22 17:01:11 +02:00
chfhtw e7d2d3502b Allow callables in $redirect_method 2026-07-22 16:45:23 +02:00
Ivymaster 4e58705107 add resourcesAssignmentModal extraction from tempus component 2026-07-22 16:36:20 +02:00
Ivymaster b809392f5d add historyModal extraction from tempus component 2026-07-22 16:20:43 +02:00
Ivymaster 817afa545b add tempus kalender tags 2026-07-22 15:52:31 +02:00
ma0068 54168c86b4 add Abstand 2026-07-22 14:41:59 +02:00
ma0068 a8dd995195 rebuild tags for whole studiengang / selection
refactor backend for multiaction rebuildTags
add phrases
refactor haederFilter
2026-07-22 14:11:07 +02:00
ma0048 9b273fa498 tab instead of space 2026-07-22 13:38:16 +02:00
chfhtw f46a3c1f68 LvVerwaltung: add routes for orgform and adapt endpoint to accept lower case orgform_kurzbz 2026-07-22 10:36:38 +02:00
Ivymaster 02a81fd52e BUG: fix for available tempus event resource suggestions 2026-07-22 08:58:58 +02:00
chfhtw ae56a4f2ed Move LvVerwaltung treemenu config to config file and disable groups & verband per default 2026-07-21 14:57:41 +02:00
Harald Bamberger 22b1f2822a fix typo 2026-07-21 14:45:07 +02:00
Harald Bamberger 1fd15e14d5 Merge branch 'master' into feature-76160/StudVw_Verbandsbaum_durch_Extensions_erweiterbar_machen 2026-07-21 14:06:04 +02:00
ma0048 9983a48102 gui fuer kalender sync hinzugefuegt und syncjob angepasst 2026-07-21 13:50:17 +02:00
ma0068 1ae02d8ed8 refactor addTaginTable and deleteTagInTable, add missing logic for automated tags in case of manual adding 2026-07-21 13:35:31 +02:00
ma0068 7cda22f807 use language index for tags 2026-07-21 10:41:27 +02:00
ma0068 68292b60af add Tags Incoming and Preabbrecher 2026-07-20 17:36:54 +02:00
chfhtw 542590b470 Remove comment 2026-07-20 09:26:31 +02:00
chfhtw eb460fdc0a Fix buildApiUrl 2026-07-17 14:05:04 +02:00
chfhtw 65e76e951a Translate treemenu entries 2026-07-17 12:01:17 +02:00
chfhtw 43d69a5683 Add comma for better merging 2026-07-17 12:01:08 +02:00
Harald Bamberger 6c25a3b262 Merge branch 'feature-77537/Studvw_Feedback' into studvw_2026_05_rc_tags 2026-07-17 11:38:46 +02:00
Harald Bamberger 1f6c9e865b Merge branch 'bug-77392/StudVW_Dokumente_Nachreichlogik_fehlendeBezeichnung' into studvw_2026_05_rc_tags 2026-07-17 11:30:23 +02:00
Harald Bamberger 1abfbccb3e Merge branch 'bug-77399/AppMenu_Show_Toasts' into studvw_2026_05_rc_tags 2026-07-17 11:25:11 +02:00
Harald Bamberger 362d1c8bb0 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-07-17 11:22:50 +02:00
Harald Bamberger 25a61a56b7 Merge branch 'master' into studvw_2026_05_rc 2026-07-17 11:22:20 +02:00
Harald Bamberger afb210b0c2 Merge branch 'master' into studvw_2026_05_rc 2026-07-17 11:21:24 +02:00
Ivymaster a30affba3a add tempus cypress tests 2026-07-17 09:10:08 +02:00
Ivymaster e09fea72a4 add resources assignment to tempus kalender entries 2026-07-17 09:09:49 +02:00
chfhtw 0471f838b9 Remove empty lines for better merge compatibility 2026-07-17 07:46:11 +02:00
chfhtw 1c9d9d1ce5 Add additional computed instead of deleted props 2026-07-17 07:44:45 +02:00
chfhtw 379a99cb14 Add empty function to let git detect where to merge 2026-07-17 07:43:22 +02:00
chfhtw 0d29a9ba32 Revert fix for merge compatibility 2026-07-17 07:40:15 +02:00
chfhtw ed44732eef Remove things that where commented out 2026-07-17 07:39:50 +02:00
chfhtw d391d1f09c Move computed to the correct position to avoid merge conflicts 2026-07-16 11:43:51 +02:00
chfhtw a36ed55390 Add new props to beginning to avoid merge conflicts 2026-07-16 11:43:10 +02:00
chfhtw b0f317951b Add lvv_favorites 2026-07-15 16:18:39 +02:00
chfhtw f65135be1e For each treemenu seperate favorites 2026-07-15 16:18:19 +02:00
ma0048 9abaf30ed3 Merge branch 'master' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	public/js/components/Calendar/Base/DragAndDrop.js
#	public/js/components/Calendar/Base/Grid/Line.js
#	public/js/composables/EventLoader.js
2026-07-15 15:48:44 +02:00
ma0048 81c16a3bf2 - wording angepasst lehreinheit -> lvteil
- Kollisionscheck an/aus wird angezeigt
- Shortcut für Ignore-Collision (F9) hinzugefuegt
- coursepicker:
 - design angepasst
 - favorisieren ermoeglicht
 - phrases
- bei lv immer alle raeume/lektoren/gruppen anzeigen unabhaengig vom filter
2026-07-15 14:58:41 +02:00
chfhtw b8d86ba628 Use luxon date formatters in studvw student list 2026-07-15 14:48:55 +02:00
ma0048 e9312dfbb3 lvverwaltung new release 2026-07-15 11:35:37 +02:00
ma0048 b21900d006 Merge remote-tracking branch 'origin/feature-70656/lvverwaltung_gruppen_im_baum_und_drag_and_drop' into feature-77372/lv_verwaltung_release_fine_tuning 2026-07-15 11:27:48 +02:00
chfhtw 11cfa670d6 Add dynamic tabulatorcolumns to lvverwaltung 2026-07-15 11:05:37 +02:00
chfhtw a94fbeba14 Only call reloadTable if a table was loaded 2026-07-15 11:05:37 +02:00
chfhtw e01b816ee8 Add treemenudata routes to lvverwaltung 2026-07-15 11:05:36 +02:00
chfhtw 52c90111cc Add treemenu to lvverwaltung 2026-07-15 11:01:03 +02:00
ma0048 012571d070 Merge remote-tracking branch 'origin/feature-69453/lv_verwaltung_karteireiter_noten' into feature-77372/lv_verwaltung_release_fine_tuning
# Conflicts:
#	public/js/components/Stv/Studentenverwaltung/Details/Noten/Teacher.js
#	public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js
2026-07-15 09:43:53 +02:00
ma0048 a2d10ae09d Merge remote-tracking branch 'origin/feature-69454/lvverwaltung_karteireiter_lv_termine' into feature-77372/lv_verwaltung_release_fine_tuning
# Conflicts:
#	application/controllers/api/frontend/v1/LvPlan.php
#	public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js
2026-07-15 09:32:03 +02:00
ma0048 96bf45ceb0 Merge remote-tracking branch 'origin/feature-75410/lvverwaltung_finetuning' into feature-77372/lv_verwaltung_release_fine_tuning
# Conflicts:
#	system/phrasesupdate.php
2026-07-15 09:26:55 +02:00
ma0048 c233902fe2 Merge remote-tracking branch 'origin/feature-70746/lvverwaltung_lektorentausch' into feature-77372/lv_verwaltung_release_fine_tuning
# Conflicts:
#	application/libraries/LektorLib.php
2026-07-15 09:20:57 +02:00
ma0048 fd8de88abb Merge remote-tracking branch 'origin/bug-69283/scroll_verhalten_lv_verwaltung_anders_als_in_studierendenverwaltung' into feature-77372/lv_verwaltung_release_fine_tuning 2026-07-15 09:17:51 +02:00
ma0048 0ec2c8c543 Merge remote-tracking branch 'origin/bug-69492/bug_lvverwaltung_doppelte_eintraege' into feature-77372/lv_verwaltung_release_fine_tuning 2026-07-15 09:17:29 +02:00
ma0048 29738b6690 Merge remote-tracking branch 'origin/feature-69353/lv_verwaltung_stundensatz_auf_leer_setzen_geht_nicht' into feature-77372/lv_verwaltung_release_fine_tuning 2026-07-15 09:17:19 +02:00
Alexei Karpenko c5c29df6cc Gehaltsbestandteil, Gehaltsbestandteil_model: added gehaltstyp_bezeichnung 2026-07-14 20:51:41 +02:00
chfhtw 0b1d0fbe4c Merge branch 'master' into feature-76160/StudVw_Verbandsbaum_durch_Extensions_erweiterbar_machen 2026-07-14 14:31:51 +02:00
chfhtw 85807f5b8c Allow treemenu entries to become draggables 2026-07-14 14:21:39 +02:00
chfhtw a1950d179b draggable directive: better handling of falsy values, better cleanup, remove attributes on falsy value/effect 2026-07-14 14:21:09 +02:00
Harald Bamberger d4929c8e22 Merge branch 'studvw_2026_05_rc_tags' into feature-77537/Studvw_Feedback 2026-07-14 10:52:31 +02:00
Harald Bamberger 194b74e390 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-07-14 10:52:05 +02:00
Harald Bamberger ee70e43bfb Merge branch 'master' into studvw_2026_05_rc 2026-07-14 10:51:40 +02:00
Harald Bamberger f8d8d501ca Merge branch 'studvw_2026_05_rc_tags' into feature-77537/Studvw_Feedback 2026-07-13 14:42:54 +02:00
Harald Bamberger 7e6d670d82 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-07-13 14:32:51 +02:00
Harald Bamberger f3a3bfcab6 Merge branch 'master' into studvw_2026_05_rc 2026-07-13 14:30:36 +02:00
chfhtw d134509c90 Remove unused routes 2026-07-13 13:13:06 +02:00
chfhtw 4424c7d748 Handle "incoming" menu entry (in inout and prestudent filters) 2026-07-13 13:03:23 +02:00
chfhtw d436d8cb20 Check permissions for prestudent menu entry 2026-07-13 13:02:40 +02:00
Ivymaster 86c06e4756 BUG: issue fix for dropdown reposition errror 2026-07-10 11:50:07 +02:00
ma0068 3689c64b7b make also notizlayout configurable 2026-07-09 11:01:00 +02:00
ma0048 a413ae17b8 suche und filter erweiterungen 2026-07-09 10:58:56 +02:00
ma0068 26ddd404c0 add geschlecht to dropdown and adapt default according to geschlecht 2026-07-09 08:57:17 +02:00
Harald Bamberger 2e33722674 Merge branch 'master' into studvw_2026_05_rc 2026-07-08 16:43:56 +02:00
Harald Bamberger b5e65cf072 Merge branch 'master' into studvw_2026_05_rc 2026-07-08 16:42:04 +02:00
chfhtw b991bbd9a5 Allow extra columns for studvw student list 2026-07-08 11:00:20 +02:00
chfhtw 5bed848aae Merge branch 'master' into feature-76160/StudVw_Verbandsbaum_durch_Extensions_erweiterbar_machen 2026-07-08 09:43:58 +02:00
Ivymaster f3b617d339 add removal of tag header sorting in LV and Student verwaltung 2026-07-07 17:13:51 +02:00
ma0068 a4c5f9946f change doku 2026-07-07 16:56:35 +02:00
Ivymaster 0be3505163 BUG: Add fix for tag dropdown issue during tag column drag 2026-07-07 16:50:44 +02:00
ma0068 81f0b7a4bf make showErweitert configurable 2026-07-07 16:43:01 +02:00
Ivymaster 6c550372a3 add definable tag column in modified helpers 2026-07-07 15:49:16 +02:00
ma0068 c86d6f4bf3 - enable opening in new tab with prevent.default
- rendering of maillinks
- useBCC without CC
2026-07-07 14:31:23 +02:00
ma0048 8172df5782 - migration script:
- auf cli job geandert
 - bisdatum nicht mehr pflicht
 - mehrere orte werden uebernommen
 - mehrere gruppen werden uebernommen

- coursepicker
 - sortierung hinzugefuegt
 - multiweekverplanung ermoeglicht
 - offene stunden berechnungn hinzugefuegt

- roomcollision auf ort array geaendert

- keyboardshortcuts hinzugefuegt
2026-07-07 11:00:25 +02:00
chfhtw c59b24ab4a App urls for studierendenverwaltung (neu: /studvw) 2026-07-03 12:16:30 +02:00
ma0068 c194e94b5c add private email to detailHeader 2026-07-02 16:46:09 +02:00
ma0068 6d23f2b9fa Add Einstiegssemester
- calculate semester_berechnet also for Stati 'Aufgenommener','Bewerber','Wartender'
- show Einstiegssemester in DetailHeader for 'Aufgenommener','Bewerber','Wartender' and 'Interessent'
2026-07-02 15:58:23 +02:00
chfhtw 0b70153da0 throw 404 on endpoints with invalid studiengang 2026-07-02 15:32:20 +02:00
chfhtw 190d797d31 adapt routes and endpoints for getPrestudent, getStudent & getPerson 2026-07-02 14:36:30 +02:00
ma0068 fb1c7f8e90 Rename Lehraufträge to Lehrauftragsverwaltung 2026-07-02 08:12:06 +02:00
chfhtw 6428fccc48 Replace CoreRESTClient calls with $api calls in stv Studiensemester component and add logic to accept lowercase input (because it could come from the url) 2026-07-01 15:45:09 +02:00
ma0068 093e3d5c97 enable deletion of zgv and zgv master date with null and empty string 2026-06-30 15:43:19 +02:00
ma0068 9bc9e57deb add selectable to tabledownload in studentList 2026-06-30 14:28:12 +02:00
chfhtw 483d8f733f adapt routes and endpoints 2026-06-30 14:21:32 +02:00
Ivymaster eb885bfea7 BUG: fix issue with unexpected closing of tag filter dropdown 2026-06-30 14:20:04 +02:00
ma0068 be5aad7c33 only bind hover event if existing dropdown to avoid error 2026-06-30 11:15:32 +02:00
ma0068 b7940a5cce add mouse-over functionality to dropdowns LvPlanung and Notenspiegel 2026-06-30 10:53:15 +02:00
Ivymaster f9b3939d09 BUG: add issue fix for tag dropdown close on column drag 2026-06-30 10:33:24 +02:00
Ivymaster 69b19562f4 BUG: add issue fix for tag ordering 2026-06-30 10:27:16 +02:00
ma0068 9948060ed8 add shortcut str+alt for studentlist, add css for studentNames scrollable 2026-06-30 08:26:41 +02:00
ma0068 06ec020c1c make div for studentNames scrollable, do not show details in alert if ok 2026-06-30 08:25:46 +02:00
ma0068 01f2099c28 remove injection currentSemester, already as prop 2026-06-30 08:24:08 +02:00
chfhtw 9cb5d0895d Rework Treemenu endpoint and libraries 2026-06-29 16:12:32 +02:00
Ivymaster 086b271480 add implementation for custom tag filter in "LVVerwaltung" 2026-06-29 14:47:43 +02:00
Ivymaster 03b2d3d1a4 extracted some code related to tags from component to helper 2026-06-29 14:02:42 +02:00
ma0068 ff38731077 refactor rowSelectionChanged 2026-06-29 13:55:11 +02:00
Ivymaster 5399375bc1 add tags extraction from nested rows 2026-06-29 13:12:29 +02:00
ma0068 3e8445304c detailheader: append tagContainer only for one selected student 2026-06-29 11:40:32 +02:00
Ivymaster b047b95505 extracted repeated code to function in extendedHeaderFilter.js 2026-06-29 11:36:03 +02:00
ma0068 3e48401a04 add uids to success and error alerts 2026-06-29 11:16:10 +02:00
Ivymaster 48f07eb3ca added width buffer for tags display 2026-06-29 09:41:52 +02:00
Ivymaster db5339e4a5 BUG: Fix random issues found during testing 2026-06-27 17:54:24 +02:00
Ivymaster 4ed87b5c2b add custom tag filter 2026-06-27 12:29:28 +02:00
Harald Bamberger d680c3aa2b Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-06-26 15:17:02 +02:00
Harald Bamberger d98bdb9745 Merge branch 'master' into studvw_2026_05_rc 2026-06-26 15:16:37 +02:00
ma0068 90907d4276 add persistance pruefungsantritt_kurzbz to abschlusspruefung 2026-06-26 13:45:14 +02:00
chfhtw 4a283ebf5d rename menu => treemenu 2026-06-25 16:46:18 +02:00
chfhtw e27e64414a Merge branch 'master' into feature-76160/StudVw_Verbandsbaum_durch_Extensions_erweiterbar_machen 2026-06-25 16:34:09 +02:00
Ivymaster c47ac926d2 WIP 2026-06-25 15:23:41 +02:00
ma0068 f751df55b6 update query isPrestudentOutgoing to show only outgoing 2026-06-25 13:27:17 +02:00
ma0068 ecd6588ead edit default permissions: in core controller admin, in stv controller admin and assistance 2026-06-25 12:56:35 +02:00
ma0068 e7c133586b adding of 4 new colours and use shorter labels for automated tags 2026-06-25 08:47:00 +02:00
ma0068 d5ee6f9cc2 adapt query for outgoing students 2026-06-24 15:48:04 +02:00
ma0068 a721c1d14d add default permission assistenz:rw for tag functionality 2026-06-24 15:22:57 +02:00
ma0068 b662fa5fd3 show date of hochgeladenum in case of nachgereicht 2026-06-23 12:55:33 +02:00
ma0068 21886e30a3 refactor query getUnacceptedDocuments 2026-06-22 08:50:10 +02:00
ma0068 2ab2176795 use language index in all getting Functions for Tags 2026-06-19 13:50:19 +02:00
ma0068 df2f142f37 add toasts if no taken selections for Notenspiegel, LVplanung and Studienverlauf 2026-06-18 11:45:01 +02:00
Harald Bamberger c7bac03429 concat escaped string correct 2026-06-17 17:45:18 +02:00
Harald Bamberger 07d3b32279 fix typo 2026-06-17 17:23:05 +02:00
Harald Bamberger 245d0d3369 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-06-17 17:15:37 +02:00
Harald Bamberger d3d04c5a77 Merge branch 'master' into studvw_2026_05_rc 2026-06-17 14:44:25 +02:00
adisposkofh ff58f7a102 minor fix 2026-06-16 17:23:01 +02:00
adisposkofh c0ed296ba7 Revert "phrase typo fix"
This reverts commit a59f6085fe.
2026-06-16 17:21:15 +02:00
adisposkofh 2692806d4f not syncing dev-provided general table presets 2026-06-16 17:19:27 +02:00
adisposkofh a59f6085fe phrase typo fix 2026-06-16 16:59:36 +02:00
Harald Bamberger cce1c50495 override permission for all methods not only the overwritten ones 2026-06-15 16:46:31 +02:00
ma0048 6565399633 - added room suggestion priority
- return erro codes
- config for from/to without grid
- bug fixes and optimizations
2026-06-15 11:47:36 +02:00
adisposkofh 4474a24ee2 streamlined collapsing table presets sub-collapsibles when tablePresets is collapsed 2026-06-11 14:09:45 +02:00
adisposkofh f59e5a20ea formatting preset info/new preset overviews 2026-06-11 13:36:26 +02:00
adisposkofh c9fe633706 localized tabulator preset backend error messages 2026-06-11 13:21:56 +02:00
adisposkofh 3ced1966f4 minor fix 2026-06-11 12:53:34 +02:00
adisposkofh 538223752b hiding preset info/new preset form when table presets section is collapsed 2026-06-11 12:38:57 +02:00
adisposkofh c9011fd6ed minor naming change in table presets 2026-06-11 11:30:42 +02:00
adisposkofh f0f9becc1f fixed new table preset info string formatting 2026-06-11 11:29:29 +02:00
adisposkofh 34c210a2a7 fixed table preset info string formatting 2026-06-11 11:27:43 +02:00
adisposkofh 7abd35d11b added tabulator preset phrases 2026-06-11 11:20:34 +02:00
adisposkofh d2c97d0238 check to sync table preset with modified config 2026-06-10 14:43:20 +02:00
adisposkofh 1d0ca15bcb passing generalPresets prop from filter to table presets 2026-06-09 17:02:02 +02:00
adisposkofh 0bb81b23e5 implemented table presets functionality 2026-06-09 16:07:55 +02:00
adisposkofh b3ae1b74ab implemented basic tabulator table presets ui 2026-06-03 16:53:55 +02:00
adisposkofh bf4b8348d2 defined cis profile tabulator columns collapse order 2026-06-03 09:18:40 +02:00
ma0048 72692812ff lecture collision check bug fix 2026-06-01 15:08:29 +02:00
ma0048 80dabf5ce6 added join to hours for zeitsperren collision check 2026-06-01 14:28:27 +02:00
ma0048 e4a1264072 fixed zeitsperren collision check 2026-06-01 13:59:50 +02:00
ma0048 517f1a9d93 formatting 2026-06-01 13:39:59 +02:00
ma0048 e62848c773 added collision checks on creation 2026-06-01 11:18:53 +02:00
ma0068 22228478ad refactor addTaginTable and deleteTagInTable, add missing logic for automated tags in case of manual adding 2026-05-27 11:51:41 +02:00
ma0048 9ac9804563 implement first version of collision checks 2026-05-26 14:09:58 +02:00
Harald Bamberger ac6aa28680 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-05-26 11:01:39 +02:00
ma0068 f6f58642f5 update second occurence of id STORAGE_KEY 2026-05-26 10:57:26 +02:00
Harald Bamberger 57eec98604 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-05-26 09:38:06 +02:00
Harald Bamberger 1561aa55b7 correct model path 2026-05-26 09:37:49 +02:00
Harald Bamberger 35f4d23308 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-05-26 09:28:40 +02:00
Harald Bamberger bb366e4117 font color black on tag limette 2026-05-26 09:06:44 +02:00
ma0068 0ed56ca067 add config for userAutomatedTags 2026-05-22 14:04:32 +02:00
ma0048 24a0e74281 Fix: prevent duplicate entries 2026-05-21 12:27:55 +02:00
ma0068 b9c045382d add Hinweistext for Modal Hinweis Beratungsgespraech 2026-05-20 09:15:15 +02:00
Harald Bamberger c099eec7a7 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-05-19 17:29:52 +02:00
Harald Bamberger 0962e62e69 Merge branch 'feature-76202/HorizontalSplit_from_master' into studvw_2026_05_rc 2026-05-19 17:28:08 +02:00
Harald Bamberger dcd6cfd74b increase width of horizontal split 2026-05-19 17:26:46 +02:00
Harald Bamberger 5caab182b2 Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-05-19 17:12:37 +02:00
Harald Bamberger baaf941f25 Merge branch 'feature-75958/StudVW_DatenExport_wie_im_Fas' into studvw_2026_05_rc 2026-05-19 17:12:11 +02:00
Harald Bamberger 2e5e7afb4d slot end tag 2026-05-19 17:11:51 +02:00
Harald Bamberger 2c4626fd1a Merge branch 'studvw_2026_05_rc' into studvw_2026_05_rc_tags 2026-05-19 16:52:14 +02:00
Harald Bamberger 178638c006 Merge branch 'feature-75958/StudVW_DatenExport_wie_im_Fas' into studvw_2026_05_rc 2026-05-19 16:51:57 +02:00
Harald Bamberger 981c97173e add padding to export icon link 2026-05-19 16:51:24 +02:00
Harald Bamberger 49d5c46133 Merge branch 'feature-75959/StudVw_Automatische_Tags' into studvw_2026_05_rc_tags 2026-05-19 16:42:25 +02:00
Harald Bamberger 9fb00f6cbd remove orphaned end tag, add right padding 2026-05-19 16:40:18 +02:00
Harald Bamberger 7d3096c2e8 readd required assignments for tags removed during merge 2026-05-19 10:28:08 +02:00
Harald Bamberger ef2f9630a9 Merge branch 'feature-75959/StudVw_Automatische_Tags' into studvw_2026_05_rc_tags 2026-05-19 10:22:28 +02:00
Harald Bamberger 4d3c73c78f add join condition for notizzuordung via prestudent_id only 2026-05-19 10:21:56 +02:00
Harald Bamberger 1e226f4515 Merge branch 'master' into studvw_2026_05_rc_tags 2026-05-18 17:27:36 +02:00
Harald Bamberger ca8fe5bd19 Merge branch 'feature-75959/StudVw_Automatische_Tags' into studvw_2026_05_rc_tags 2026-05-18 17:27:06 +02:00
ma0068 e2497e1958 add Infomodal Beratungsgespraech in case of Abmeldung and configEntry 2026-05-18 17:25:48 +02:00
ma0068 d4e170037b add order Nachname, Vorname 2026-05-18 10:11:17 +02:00
ma0068 0326a01585 disable sendButton, show Spinner and prevent closeModal while sending Message 2026-05-15 14:14:22 +02:00
ma0068 7aba7aefb9 add order mitarbeiter_uid 2026-05-15 11:05:12 +02:00
ma0068 e5ae400686 Tab Abschlusspruefung: use searchPersons instead of Mitarbeiter and refactor Label for dropdown 2026-05-13 17:38:39 +02:00
chfhtw c468d350f3 outsource config to better read it and make reuse easier 2026-05-13 14:16:14 +02:00
ma0068 1b822fc8f8 reset config stv to readonly for automated tags 2026-05-11 15:15:06 +02:00
ma0068 368eded1fd remove frontend filtering list for studiensemester, update logs TagJob 2026-05-11 15:12:53 +02:00
ma0068 dbcacdddd6 add tagFilter for semester to students endpoint, add decoding jsonResult in Tags 2026-05-11 13:18:56 +02:00
Harald Bamberger 8b2ef4e832 Merge branch 'master' into feature-75959/StudVw_Automatische_Tags 2026-05-11 10:54:26 +02:00
ma0068 6fedb4b108 delete unused code 2026-05-11 10:07:28 +02:00
chfhtw a7cc07fe15 Add basic library and config for studvw 2026-05-11 09:31:08 +02:00
chfhtw e91f8e5ca4 Replace component and endpoint for Verband 2026-05-11 09:27:54 +02:00
ma0068 905c69c384 create log entries for Summary, Details and Errors 2026-05-11 09:20:59 +02:00
chfhtw c765c3c40a allow object as argument for drop directive to enable dynamic specification of allowed dragtypes 2026-05-11 09:20:42 +02:00
ma0068 6fa0a7c102 use injected studiensemester instead of api call for studiensemester 2026-05-08 11:53:47 +02:00
ma0068 7320dc448e correct bezeichnung interval.ende 2026-05-08 10:57:19 +02:00
ma0068 ede9323224 refactor manual triggering for double degree lib 2026-05-08 08:33:53 +02:00
ma0068 3dcf72d679 add semester filter for tags
- in detailheader: use currentSem for manual triggering and refactor formatter
- in list: preload list of ids with start and end for tabulator formatter to enable filtering
2026-05-07 17:36:34 +02:00
Harald Bamberger 8ce67a4726 Merge branch 'master' into studvw_2026_05_rc 2026-05-06 17:35:05 +02:00
Harald Bamberger bcfdf1e05c Merge branch 'feature-75838/UXImproveProjektarbeitSTVSprint247' into studvw_2026_05_rc 2026-05-06 17:33:33 +02:00
Harald Bamberger cb744799bd Merge branch 'feature-71776/StudVW_Abschlusspruefung_DropdownsPrueferAndMultiActionNewPruefung' into studvw_2026_05_rc 2026-05-06 17:27:26 +02:00
Harald Bamberger 90ebee25fe Merge branch 'feature-71775/StudVW_ChangeSem_Behaviour' into studvw_2026_05_rc 2026-05-06 16:28:44 +02:00
Harald Bamberger 3e8ed231a6 Merge branch 'feature-71392/StudVW_Einstiegssemester_bei_Interessenten_anzeigen' into studvw_2026_05_rc 2026-05-06 16:03:37 +02:00
Harald Bamberger 4c67b9d267 Merge branch 'feature-76202/HorizontalSplit_from_master' into studvw_2026_05_rc 2026-05-06 15:56:14 +02:00
Johann HoffmannandHarald Bamberger c16cf342cb horizontalsplit component analog to verticalsplit; also built it into Studentenverwaltung.js menu; added defaultRatio prop to both components which defaults to 50/50 seperation 2026-05-06 15:54:49 +02:00
Harald Bamberger d843f05922 Merge branch 'feature-76201/StudVWTabsBeibehalten' into studvw_2026_05_rc 2026-05-06 15:42:29 +02:00
Harald Bamberger 44e9b4dff1 Merge branch 'feature-76145/StudVW_Studienverlauf_in_AppMenu' into studvw_2026_05_rc 2026-05-06 15:41:41 +02:00
Harald Bamberger bda42ab347 Merge branch 'feature-75958/StudVW_DatenExport_wie_im_Fas' into studvw_2026_05_rc 2026-05-06 15:06:51 +02:00
Harald Bamberger b5b69878b8 Merge branch 'feature-75901/StudVW_AppMenue_neueVerlinkungen' into studvw_2026_05_rc 2026-05-06 14:40:17 +02:00
Harald Bamberger 6f17ddbbdf Merge branch 'feature-63428/Infomail_Foto' into studvw_2026_05_rc 2026-05-06 14:35:45 +02:00
ma0068 ef1347c7d5 - use function getAktOrNextSemester
- restructure single libs to isolate typeId of data
- refactor Job: use params, details output
- use functions insert, update, delete
- use timeperiode for getAllTags and checkIfExistingTag
- controller: rebuild function: change to POST
- updated insertVon Batchuser
2026-05-05 15:20:02 +02:00
ma0068 d1fa5f64c4 refactor TagJob, TagLib and single TagLibs for dynamic use of typeId, add temporary testfile application/libraries/tags/CoreFiftyFiveTagLib.php for testing person_id 2026-04-30 11:17:39 +02:00
ma0048 57597dac29 - added reservierungen
- added updatemails
- added reservierungssync
- updated status kurzbz
- reservierung renderer for tempus
2026-04-28 20:17:50 +02:00
ma0068 21eb95bb23 manually triggering of updateTag 2026-04-28 16:24:30 +02:00
ma0048 b57836c2af fixed bug 2026-04-28 14:17:23 +02:00
ma0048 e80ee03365 fixed bug 2026-04-28 14:13:22 +02:00
ma0068 e856c8ad6b change settings bezeichnung_mehrsprachig::varchar[] in TagController functions getTag and getTags 2026-04-27 10:01:54 +02:00
ma0068 2723d6a741 get Semester of Model instead of Using CONST, delete unused models 2026-04-24 14:07:14 +02:00
ma0068 e5e22931a9 add db queries for update system, update tags in config 2026-04-24 12:49:00 +02:00
ma0068 21ea277aaf use checks for param studiengang_kurzbz instead of deleting it 2026-04-24 09:20:37 +02:00
ma0068 2c0badf67c bugfix error undefined offset: deletion of unused variable studiengang_kz 2026-04-23 17:28:43 +02:00
ma0068 5e72161ab0 add variables from and to to show time of validity in backend
refactor function getZuordnungIds of all single tagLibs
add description line for editing/showing modal tag
2026-04-23 16:39:21 +02:00
ma0068 903f3b99b3 add Studienverlauf to AppMenue 2026-04-20 11:36:54 +02:00
ma0068 df9edc36e0 save temporary 2026-04-20 08:40:55 +02:00
ma0068 39f1716ae2 set all automatic tags to readonly, add icon lock to automatic tags 2026-04-17 10:47:45 +02:00
Harald Bamberger c7b25e6632 add name to TagComponent, combine action slot definition for tagcomponent with definition for filter active 2026-04-16 16:21:33 +02:00
Harald Bamberger 695f3455e6 add function generateCSSsIncludeIfExtensionCssExists and use to load additional tag.css from extensions if exists 2026-04-16 15:20:11 +02:00
ma0068 1339077b57 use single tagLibs for dynamisation
new tagLibs (doubleDegree, jgv, missingZgv, Outgoing, StudienbeitragErhoeht, Unterbrecher)
refactor tagJob rebuildAutomatedTags
2026-04-15 09:45:57 +02:00
Johann Hoffmann 3aebccbb9d track activeTab in StudVW Details.js and pass it to :default property of fhcTabs instances to attempt to set the last active tab to current, else use the old default tab of route.params.tab 2026-04-10 13:01:13 +02:00
ma0068 ee6f28c06d Refactor TagJob and TabLib: use dynamic approach with column taglib for creating Tags 2026-04-09 13:58:42 +02:00
Harald Bamberger fdb037da96 poc move logic for single tags to libs, and add lib loading path and name to extra column in tbl_notiztyp 2026-04-09 08:36:13 +02:00
ma0068 49cbbfc50c update user 2026-04-08 15:24:06 +02:00
ma0068 4f8e98f5d5 restyle button reloadTags 2026-04-08 15:11:58 +02:00
ma0048 7240b0c798 first version of history logic 2026-04-08 14:40:33 +02:00
ma0068 e9e614aa52 Add Functionality Frontend: triggering of reloading tags for prestudent from studentHeader
Refactoring: Recycling of tags instead of deleting it and creating new ones
2026-04-08 14:26:14 +02:00
ma0048 ab5294de2f stylingaenderungen
coursepicker umgebaut, keine backend suche mehr
hinzugefuegt:
- resizeHanlder funktion
- broadcastchannel postMessage "dropped"
- tbl_kalender_status column bezeichnung_mehrsprachig
- tbl_kalender_status column sort
2026-04-01 10:53:31 +02:00
ma0068 50af6694d0 show Tags in CoreHeader 2026-03-31 12:48:27 +02:00
ma0048 8dd42361a0 Merge branch 'master' into feature-68298/Tempus_Grundstruktur
# Conflicts:
#	public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js
#	system/dbupdate_3.4.php
2026-03-30 09:18:31 +02:00
ma0068 5dbddb4beb remove char 2026-03-27 09:46:48 +01:00
ma0068 b20613f5d7 Basic Structure Automatic Tagging
- new library libTag
- new Job TagJob
- new entries for automatic tags in config stv.php
- automatic tagging of wiederholer and prewiederholer
2026-03-27 09:40:14 +01:00
ma0048 229de14f9c tempus pre-alpha version - add missing file 2026-03-25 14:42:36 +01:00
ma0048 e990bb3d81 tempus pre-alpha version 2026-03-25 14:41:13 +01:00
Harald Bamberger 0621564be7 Merge branch 'master' into feature-71775/StudVW_ChangeSem_Behaviour 2026-03-19 15:57:13 +01:00
ma0068 f1714db09e add ExcelExport of FAS to StudentList, add slot additional to Filtercomponent 2026-03-19 15:00:51 +01:00
ma0068 70b025da30 add Link Reihungstestverwaltung to AppMenu 2026-03-17 14:59:05 +01:00
ma0068 87dd858358 add entry StudVw to navigation CI Menue 2026-03-17 14:58:39 +01:00
ma0068 51f3edcd72 delete not needed parameter orgform for html version lv planung 2026-03-17 12:57:55 +01:00
ma0068 e7f626bd72 add Lv-Planung to app menue 2026-03-17 12:49:40 +01:00
ma0068 17f94aabdf add loading skeletons for mitarbeiterHeader 2026-03-16 17:16:40 +01:00
ma0068 c49e32c4ac use skeletons for all data in studentHeader 2026-03-16 11:26:23 +01:00
ma0068 df124db84a use primeVue Skeleton while loading Data for Semester, Verband and Gruppe 2026-03-13 12:40:29 +01:00
ma0068 29a4b4aadc use permission PERM_LOGGED for header, add condition one empty space for showing verband 2026-03-13 09:11:00 +01:00
ma0068 2682ea75ab use only one endpoint for detailheader 2026-03-12 16:58:48 +01:00
ma0068 b3a63a60e9 update phrase noTextInSem 2026-03-12 16:02:44 +01:00
Harald Bamberger a54dfaf0c7 Merge branch 'master' into feature-71775/StudVW_ChangeSem_Behaviour 2026-03-12 15:20:53 +01:00
Harald Bamberger 595538d6bb Merge branch 'master' into feature-71775/StudVW_ChangeSem_Behaviour 2026-03-12 15:10:06 +01:00
Harald Bamberger a5329e5bba Merge branch 'master' into feature-71775/StudVW_ChangeSem_Behaviour 2026-03-12 15:03:56 +01:00
Harald Bamberger 37a79c4589 Merge branch 'master' into feature-71775/StudVW_ChangeSem_Behaviour 2026-03-12 15:03:28 +01:00
Harald Bamberger dd760f8210 finetune behavior 2026-03-12 11:10:13 +01:00
ma0068 dd87e893ba working version for relaod header and data without updateUrl 2026-03-11 17:13:59 +01:00
ma0068 127ce312ea reload Details and Detailheader without updateUrl 2026-03-10 08:28:11 +01:00
ma0068 2237e9f1b7 refactor detail Header, relaod array if semester changed, show no status if no status, phrase 2026-03-09 11:42:24 +01:00
ma0068 9b4fa132dc add status 2026-03-06 10:58:54 +01:00
Harald Bamberger daf332a102 add query_studiensemester_kurzbz to result of fetchStudents, fetchPrestudents and search 2026-03-06 10:39:37 +01:00
ma0048 7f91e20d03 lvverwaltung: vilesci lehrveranstaltung verwaltung verlinkt 2026-03-04 15:15:12 +01:00
ma0048 233a6e8b89 lvverwaltung:
- event hinzugefuegt damit tabs erweitert werden können
- berichte hinzugefuegt
2026-02-25 15:25:36 +01:00
ma0068 c127c0900e refactor dropdown for pruefer, add localStorage for formVariables, add multiactions for adding new finalexam 2026-02-25 14:28:41 +01:00
ma0068 fc01fa045e add and use variable semester_berechnet for using ausbildungssemester in status interessent 2026-02-23 13:44:33 +01:00
ma0048 bb23679683 auskommentierten code entfernt 2026-02-12 10:45:32 +01:00
ma0048 43a1d163a3 Merge branch 'master' into feature-68298/Tempus_Grundstruktur 2026-01-20 09:21:47 +01:00
ma0048 e26387a75a lektoren tausch auch bei verplanten lektoren hinzugefuegt 2026-01-19 15:08:59 +01:00
ma0048 ab63bf9d74 gruppen in baum anzeigen und drag and drop von gruppen 2026-01-12 09:27:27 +01:00
ma0048 60f128b314 tabs gleichgezogen 2025-12-09 13:00:40 +01:00
ma0048 cc0a89c924 lvverwaltung noten hinzugefuegt
noten highlight wenn keine note im zeugnis eingetragen ist
2025-12-04 14:18:13 +01:00
ma0048 8f974e8902 sql angepasst 2025-12-03 08:37:38 +01:00
ma0048 a91fe05395 funktionen umbenannt 2025-12-02 13:23:09 +01:00
ma0048 d9cdeb9773 scroll verhalten angepasst 2025-12-02 08:42:04 +01:00
ma0048 0de033e428 termine tab hinzugefuegt 2025-12-01 10:55:04 +01:00
ma0048 1ab9635039 disitnct lv id 2025-11-26 13:56:37 +01:00
ma0048 e7fdbe13d0 nullable felder speichern 2025-11-20 15:32:27 +01:00
chfhtw 00477528cc Bugfix: LVs without Stg should not throw an PHP error 2025-11-19 10:19:34 +01:00
chfhtw 4c6d645cc6 Studienverlauf verlinken im neuen FAS 2025-11-18 15:02:55 +01:00
Andreas Österreicher 93388ff06c Merge branch 'master' into feature-68298/Tempus_Grundstruktur 2025-11-12 13:55:44 +01:00
Andreas Österreicher 352fc53e74 Erster Prototyp für Tempus Neu DB und GUI 2025-10-20 11:01:50 +02:00
Harald Bamberger f57dc6785b Merge branch 'master' into feature-63428/Infomail_Foto 2025-09-30 13:47:04 +02:00
ma0068 cf59bcff12 add Functionality sendInfomail
- expand InputComponent for dynamic adding of actionButton to Form Upload Image
- add Phrases for Infomail
2025-08-19 09:16:26 +02:00
344 changed files with 37613 additions and 4223 deletions
+1
View File
@@ -1,5 +1,6 @@
documents/
vendor/
public/vendor
/nbproject/
.vscode
+22
View File
@@ -33,5 +33,27 @@ Events::on('loadRenderers', function ($renderers) {
);
});
//Tempus Renderers:
Events::on('loadTempusRenderers', function ($renderers) {
$fhc_core_renderers =& $renderers();
$fhc_core_renderers["reservierung"] = array(
'calendarEvent' => absoluteJsImportUrl('public/js/components/Tempus/Renderer/Reservierungen/calendarEvent.js'),
'modalTitle' => absoluteJsImportUrl('public/js/components/Tempus/Renderer/Reservierungen/modalTitle.js'),
'modalContent' => absoluteJsImportUrl('public/js/components/Tempus/Renderer/Reservierungen/modalContent.js'),
'calendarEventStyles' => APP_ROOT . 'public/css/Cis4/CoreCalendarEvents.css'
);
});
Events::on('loadTempusRenderers', function ($renderers) {
$fhc_core_renderers =& $renderers();
$fhc_core_renderers["lehreinheit"] = array(
'calendarEvent' => absoluteJsImportUrl('public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js'),
'modalTitle' => absoluteJsImportUrl('public/js/components/Tempus/Renderer/Lehreinheit/modalTitle.js'),
'modalContent' => absoluteJsImportUrl('public/js/components/Tempus/Renderer/Lehreinheit/modalContent.js'),
'calendarEventStyles' => APP_ROOT . 'public/css/Cis4/CoreCalendarEvents.css'
);
});
+12 -1
View File
@@ -8,4 +8,15 @@ $config['lvverwaltung_tags'] = [
];
*/
$config['lvverwaltung_tags'] = [];
$config['lvverwaltung_tags'] = [];
# Additional columns:
/*
$config["list_columns"] = [
'fieldname' => [
'js' => 'path/to/snippet.js', // tabulator config snippet (eg: return { name: 'Name', field: 'fieldname' }; )
// NOTE: 'default' & 'joins' like in stv.php config are currently not available here
]
];
*/
+8 -1
View File
@@ -170,6 +170,13 @@ $config['navigation_header'] = array(
'expand' => true,
'sort' => 51,
'requiredPermissions' => 'vertrag/mitarbeiter:r'
),
'studierendenverwaltung' => array(
'link' => site_url('studentenverwaltung'),
'description' => 'Studierendenverwaltung',
'expand' => true,
'sort' => 52,
'requiredPermissions' => ['admin:r', 'assistenz:r']
)
)
),
@@ -378,7 +385,7 @@ $config['navigation_menu']['apps'] = [
],
'lav' => [
'link' => site_url('lehre/lehrauftrag/Lehrauftrag/Dashboard'),
'description' => 'Lehraufträge',
'description' => 'Lehrauftragsverwaltung',
#'icon' => 'person-chalkboard',
'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r', 'lehre/lehrauftrag_erteilen:r')
]
+54 -37
View File
@@ -75,56 +75,73 @@ $route['Abgabetool/Student'] = 'Cis/Abgabetool/Student';
$route['Abgabetool/Student/(:any)'] = 'Cis/Abgabetool/Student/$1';
$route['Abgabetool/Deadlines'] = 'Cis/Abgabetool/Deadlines';
// Studierendenverwaltung App Routes
$route['studvw'] = 'studentenverwaltung/index';
$route['studvw/.*'] = 'studentenverwaltung/index';
// Old routes
$route['studentenverwaltung'] = 'redirect/301/studvw';
$route['studentenverwaltung/(:any)'] = 'redirect/301/studvw/stdsem/$1';
$route['studentenverwaltung/(:any)/(prestudent|student|person|search)/(:any)'] = 'redirect/301/studvw/stdsem/$1/$2/$3';
$route['studentenverwaltung/(:any)/prestudent/(:any)/tab/:any'] = 'redirect/301/studvw/stdsem/$1/prestudent/$2';
$route['studentenverwaltung/(:any)/search/(:any)/(:any)'] = 'redirect/301/studvw/stdsem/$1/search/$2/$3';
$route['studentenverwaltung/(:any)/(:any)'] = 'redirect/301/studvw/stdsem/$1/stg/$2';
// Studierendenverwaltung List Routes
$route['api/frontend/v1/stv/[sS]tudents/inout'] = 'api/frontend/v1/stv/Students/index';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/index';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/inout/1/incoming/1'] = 'api/frontend/v1/stv/students/getIncoming/$1';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/inout/1/outgoing/1'] = 'api/frontend/v1/stv/students/getOutgoing/$1';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/inout/1/shared_studies/1'] = 'api/frontend/v1/stv/students/getGemeinsamestudien/$1';
// (studiensemester_kurzbz)/inout[/(incoming|outgoing|gemeinsamestudien)]
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout'] = 'api/frontend/v1/stv/Students/index';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/incoming'] = 'api/frontend/v1/stv/Students/getIncoming/$1';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/outgoing'] = 'api/frontend/v1/stv/Students/getOutgoing/$1';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/gemeinsamestudien'] = 'api/frontend/v1/stv/Students/getGemeinsamestudien/$1';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1/stdsem/(:any)/:any/1/:any/1/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudents/$1/$2/$3';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1/stdsem/(:any)/:any/1/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudents/$1/$2/$3';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1/stdsem/(:any)/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudents/$1/$2/$3';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1/stdsem/(:any)'] = 'api/frontend/v1/stv/students/getPrestudents/$1/$2';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1'] = 'api/frontend/v1/stv/students/getPrestudents/$1';
// (studiengang_kz)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]]
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudents/$1';
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2';
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2/$3';
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2/$4';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1/stdsem/(:any)/:any/1/:any/1/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2/$3/$4';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1/stdsem/(:any)/:any/1/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2/$3/$4';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1/stdsem/(:any)/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2/$3/$4';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1/stdsem/(:any)'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2/$3';
$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2';
// (studiengang_kz)/(orgform)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]]
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2';
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3';
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3/$4';
$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3/$5';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)/verband/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2/$3/$4/$5';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)/verband/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2/$3/$4';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2/$3';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2';
// (studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe)
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/grp/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsSpezialgruppe/$1/$2/$3/$4';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)/verband/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3/$4/$5/$6';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)/verband/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3/$4/$5';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3/$4';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3';
// (studiensemester_kurzbz)/(studiengang_kz)[/(semester)[/(verband)[/(gruppe)]]]
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/(:any)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3/$4';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3/$4/$5';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudentsSpezialgruppe/$1/$2/$3/$4';
// (studiensemester_kurzbz)/(studiengang_kz)/(orgform)/(semester)/grp/(gruppe)
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/grp/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgformSpezialgruppe/$1/$2/$3/$4/$5';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgformSpezialgruppe/$1/$3/$2/$4/$5';
// (studiensemester_kurzbz)/(studiengang_kz)/(orgform)[/(semester)[/(verband)[/(gruppe)]]]
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4/$5';
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4/$5/$6';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/prestudent/(:any)'] = 'api/frontend/v1/stv/students/getPrestudent/$1/$2';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/student/(:any)'] = 'api/frontend/v1/stv/students/getStudent/$1/$2';
$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/person/(:any)'] = 'api/frontend/v1/stv/students/getPerson/$1/$2';
$route['api/frontend/v1/treemenudata/stv/.*'] = 'api/frontend/v1/stv/students/index';
// Lvverwaltung List Routes
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2';
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/semester/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/semester/(:any)/.*'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/orgform/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/orgform/(:any)/.*'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/emp/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByEmp/$1/$2';
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/emp/(:any)/stg/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByEmp/$1/$2/$3';
$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/emp/(:any)/stg/(:any)/.*'] = 'api/frontend/v1/Lehrveranstaltung/getByEmp/$1/$2/$3';
// // (studiensemester_kurzbz)/uid/(uid)
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/uid/(:any)'] = 'api/frontend/v1/stv/Students/getStudent/$1/$2';
// // (studiensemester_kurzbz)/prestudent/(prestudent_id)
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/prestudent/(:num)'] = 'api/frontend/v1/stv/Students/getPrestudent/$1/$2';
// // (studiensemester_kurzbz)/person/(person_id)
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/person/(:num)'] = 'api/frontend/v1/stv/Students/getPerson/$1/$2';
// load routes from extensions, also look for environment-specific configs
$subdirs = ['application/config/extensions', 'application/config/' . ENVIRONMENT . '/extensions'];
$route['api/frontend/v1/tempus/Tags/getTagsByCalendar/(:num)'] = 'api/frontend/v1/tempus/Tags/getTagsByCalendar/$1';
foreach($subdirs as $subdir)
{
if(is_dir($subdir))
@@ -197,3 +197,11 @@ $config['unterbrechung_enabled'] = true;
*/
$config['wiederholung_enabled'] = true;
/**
* Modal with Infotext of TLC
* if true, there will be shown an info modal in the studentsView after the first button ABMELDUNG
*
* @var boolean
*/
$config['showInfoModalAbmeldung'] = true;
+47 -8
View File
@@ -1,6 +1,27 @@
<?php
$config['number_displayed_past_studiensemester_default'] = 5;
# Additional columns:
/*
$config["list_columns"] = [
'fieldname' => [
'js' => 'path/to/snippet.js', // tabulator config snippet (eg: return { name: 'Name', field: 'fieldname' }; )
'default' => "SQL SELECT statement for value",
'joins' => [
// additional joins needed for the SELECT statement above
[
'tablename',
'join condition', // single fieldname for USING or full condition for ON
'LEFT|RIGHT', // optional - join type
'after_xxx|before_xxx|end' // optional - position in query
]
// ...
]
]
];
*/
$config['tabs'] =
[
'details' => [
@@ -60,7 +81,13 @@ $config['tabs'] =
],
'notes' => [
//if true, the count of Messages will be shown in the header of the Tab Messages
'showCountNotes' => true
'showCountNotes' => true,
//if true: section with following fields will be displayed: 'verfasser', 'bearbeiter', 'von', 'bis' and 'erledigt'
'showErweitert' => false,
//notizlayout: choose of "classicFas", "twoColumnsFormLeft", twoColumnsFormRight, popupModal"
'notizLayout' => 'popupModal'
],
'combinePeople' => [
//multitab should only be shown with this length of selection
@@ -133,13 +160,25 @@ $config['students_tab_order'] = [
$config['stv_prestudent_tags'] = [
'prioone' => ['readonly' => false],
'priotwo' => ['readonly' => true],
'priotwo' => ['readonly' => false],
'hinweis' => ['readonly' => false],
'hinweis_assistenz' => ['readonly' => true],
'hinweis_kf' => ['readonly' => true],
'hinweis_assistenz' => ['readonly' => false],
'hinweis_kf' => ['readonly' => false],
'hinweis_lehrende' => ['readonly' => false],
'hinweis_stg_kf' => ['readonly' => true],
'finished_stg' => ['readonly' => true],
'finished_kf' => ['readonly' => true],
'inwork_kf' => ['readonly' => true],
'hinweis_stg_kf' => ['readonly' => false],
'finished_stg' => ['readonly' => false],
'finished_kf' => ['readonly' => false],
'inwork_kf' => ['readonly' => false],
'dd_auto' => ['readonly' => true],
'wh_auto' => ['readonly' => true],
'prewh_auto' => ['readonly' => true],
'out_auto' => ['readonly' => true],
'zgv_auto' => ['readonly' => true],
'unterbrecher_auto' => ['readonly' => true],
'stbtr_erh_auto' => ['readonly' => true],
'jgv_auto' => ['readonly' => true],
'in_auto' => ['readonly' => true],
'preabbr_auto' => ['readonly' => true],
];
$config['userAutomatedTags'] = 'sftest';
+12
View File
@@ -0,0 +1,12 @@
<?php
$config['send_update_mails'] = false;
$config['calendar_start'] = 7;
$config['calendar_end'] = 23;
$config['tempus_tags'] = [
'prioone' => ['readonly' => false],
'priotwo' => ['readonly' => true],
'hinweis' => ['readonly' => false],
];
+34
View File
@@ -0,0 +1,34 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
$config['stv'] = [
"library" => "treemenu/StudVwLib",
"permissions" => ["admin:r", "assistenz:r"]
];
$config['lvv'] = [
"library" => "treemenu/LvVwLib",
"permissions" => ["admin:r", "assistenz:r"]
];
$config['tempus'] = [
"library" => "treemenu/TempusLib",
"permissions" => ["admin:r", "assistenz:r", "lehre/lvplan:r"]
];
@@ -0,0 +1,32 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
$config['root'] = [
'stg' => [
'semester' => [
'group',
'verband' => [
'group'
]
],
'orgform'
]
];
@@ -0,0 +1,32 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
$config['root'] = [
'stg' => [
'semester' => [
'group',
'verband' => [
'group'
]
],
'orgform'
]
];
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
$config['root'] = [
'stg' => [
'prestudent' => [
'stdsem' => [
'interessenten' => [
'bewerbungnichtabgeschickt',
'bewerbungabgeschickt',
'zgv',
'statusbestaetigt' => [
'statusbestaetigtrtnichtangemeldet',
'statusbestaetigtrtangemeldet'
],
'reihungstestnichtangemeldet',
'reihungstestangemeldet'
],
'bewerber' => [
'bewerberrtnichtangemeldet',
'bewerberrtangemeldet' => [
'bewerberrtangemeldetteilgenommen',
'bewerberrtangemeldetnichtteilgenommen'
]
],
'aufgenommen',
'warteliste',
'absage',
'incoming'
]
],
'semester' => [
'group',
'verband' => [
'group'
]
]
],
'inout' => [
'incoming',
'outgoing',
'shared_studies'
]
];
// copy stg tree into stg/orgforms
$config['root']['stg']['orgform'] = $config['root']['stg'];
+44
View File
@@ -0,0 +1,44 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller redirects urls to another location. This is mainly used
* with the $routes config
*/
class Redirect extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
/**
* Main function to handle all redirects.
*
* @param string $method - the redirect code (30x)
* @param array $params - the url to redirect to
*
* @return void
*/
public function _remap($method, $params)
{
redirect($params, 'location', $method);
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Tempus extends Auth_Controller
{
public function __construct()
{
$permissions = [];
$router = load_class('Router');
$permissions[$router->method] = ['admin:r', 'assistenz:r'];
parent::__construct($permissions);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
// Load Config
$this->load->config('calendar');
}
public function index()
{
$this->_loadView();
}
public function sync()
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$this->load->model('ressource/Kalenderstatus_model', 'KalenderStatusModel');
$this->OrganisationseinheitModel->addJoin('tbl_studiengang', 'oe_kurzbz', 'LEFT');
$this->OrganisationseinheitModel->addSelect('public.tbl_organisationseinheit.organisationseinheittyp_kurzbz,
public.tbl_organisationseinheit.bezeichnung,
public.tbl_studiengang.studiengang_kz,
public.tbl_organisationseinheit.oe_kurzbz,
tbl_studiengang.typ,
COALESCE(public.tbl_studiengang.bezeichnung, \'\') as stgbezeichnung');
$this->OrganisationseinheitModel->addOrder('tbl_organisationseinheit.aktiv', 'DESC');
$this->OrganisationseinheitModel->addOrder('tbl_organisationseinheit.organisationseinheittyp_kurzbz');
$organisationen = getData($this->OrganisationseinheitModel->loadWhere(array("tbl_organisationseinheit.aktiv" => true)));
$this->StudiensemesterModel->addOrder('start', 'DESC');
$studiensemestern = getData($this->StudiensemesterModel->load());
$this->_loadView(array('organisationen' => $organisationen, 'studiensemestern' => $studiensemestern));
}
private function _loadView($extraVariables = [])
{
$this->load->view('Tempus', [
'permissions' => [
'admin' => $this->permissionlib->isBerechtigt('admin'),
'stundenraster' => $this->permissionlib->isBerechtigt('basis/tempus_stundenraster'),
],
'variables' => array_merge([
'semester_aktuell' => $this->variablelib->getVar('semester_aktuell'),
'timezone' => $this->config->item('timezone')
], $extraVariables)
]);
}
}
@@ -20,8 +20,8 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about favorite verbände
* Listens to ajax post calls to change the favorite verbände data
* Provides data to the ajax get calls about favorite treemenu entries
* Listens to ajax post calls to change the favorite treemenu entries
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Favorites extends FHCAPI_Controller
@@ -29,7 +29,7 @@ class Favorites extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
'index' => self::PERM_LOGGED,
'get' => self::PERM_LOGGED,
'set' => self::PERM_LOGGED
]);
@@ -37,19 +37,19 @@ class Favorites extends FHCAPI_Controller
$this->load->model('system/Variable_model', 'VariableModel');
}
public function index()
public function get($app)
{
$result = $this->VariableModel->getVariables(getAuthUID(), ['stv_favorites']);
$result = $this->VariableModel->getVariables(getAuthUID(), [$app . '_favorites']);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
$this->terminateWithSuccess(null);
else
$this->terminateWithSuccess($data['stv_favorites'] ?? null);
$this->terminateWithSuccess($data[$app . '_favorites'] ?? null);
}
public function set()
public function set($app)
{
$this->load->library('form_validation');
@@ -60,7 +60,7 @@ class Favorites extends FHCAPI_Controller
$favorites = $this->input->post('favorites');
$result = $this->VariableModel->setVariable(getAuthUID(), 'stv_favorites', $favorites);
$result = $this->VariableModel->setVariable(getAuthUID(), $app . '_favorites', $favorites);
$this->getDataOrTerminateWithError($result);
@@ -56,7 +56,9 @@ class Lehrveranstaltung extends FHCAPI_Controller
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
$lehrveranstaltungen = $this->_ci->LehreinheitModel->getLvsByEmployee($mitarbeiter_uid, $studiensemester_kurzbz, $stg_kz);
$studiengang_kz = $this->getStudiengangKz($stg_kz);
$lehrveranstaltungen = $this->_ci->LehreinheitModel->getLvsByEmployee($mitarbeiter_uid, $studiensemester_kurzbz, $studiengang_kz);
$lehrveranstaltungen_data = $this->getDataOrTerminateWithError($lehrveranstaltungen);
$tree = [];
@@ -75,15 +77,17 @@ class Lehrveranstaltung extends FHCAPI_Controller
$this->terminateWithSuccess($tree);
}
public function getByStg($studiensemester_kurzbz = null, $studiengang_kz = null, $semester = null)
public function getByStg($studiensemester_kurzbz = null, $stg_kz = null, $semester = null)
{
$studiengang_kz = $this->getStudiengangKz($stg_kz);
if (is_null($studiengang_kz) || !preg_match("/^-?[1-9][0-9]*$/", (string)$studiengang_kz))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$verband = null;
if (!is_null($semester) && !is_numeric($semester))
{
$verband = $semester;
$verband = $this->getOrgformKurzbz($semester);
$semester = null;
}
@@ -260,18 +264,53 @@ class Lehrveranstaltung extends FHCAPI_Controller
}
}
protected function getStudiengangKz($studiengang_typ_kurzbz)
{
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$result = $this->StudiengangModel->loadWhere([
'LOWER(CONCAT(typ, kurzbz)) =' => strtolower($studiengang_typ_kurzbz)
]);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
return null;
return current($data)->studiengang_kz;
}
private function getStudiensemesterKurzbz($studiensemester_kurzbz = null)
{
if (!is_null($studiensemester_kurzbz))
{
$studiensemester_result = $this->_ci->StudiensemesterModel->load($studiensemester_kurzbz);
$studiensemester_result = $this->_ci->StudiensemesterModel->loadWhere([
'LOWER(studiensemester_kurzbz)' => strtolower($studiensemester_kurzbz)
]);
if (isError($studiensemester_result) || !hasData($studiensemester_result))
$this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
return getData($studiensemester_result)[0]->studiensemester_kurzbz;
}
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
}
protected function getOrgformKurzbz($orgform_kurzbz)
{
if ($orgform_kurzbz === null)
return null;
$this->load->model('codex/Orgform_model', 'OrgformModel');
$result = $this->OrgformModel->loadWhere([
'LOWER(orgform_kurzbz) =' => strtolower($orgform_kurzbz)
]);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
return $orgform_kurzbz;
return current($data)->orgform_kurzbz;
}
}
@@ -49,6 +49,8 @@ class LvPlan extends FHCAPI_Controller
'getLehrverband' => self::PERM_LOGGED,
'permissionOtherLvPlan' => self::PERM_LOGGED,
'compactibleEventTypes' => self::PERM_LOGGED,
'getLeEvents' => self::PERM_LOGGED,
'getLvEvents' => self::PERM_LOGGED,
]);
$this->load->library('LogLib');
@@ -60,7 +62,13 @@ class LvPlan extends FHCAPI_Controller
'dbExecuteUser' => 'RESTful API'
));
$this->load->library('form_validation');
$this->load->library('form_validation');
$this->load->library('PhrasesLib');
$this->loadPhrases(
array(
'ui'
)
);
}
//------------------------------------------------------------------------------------------------------------------
@@ -106,6 +114,7 @@ class LvPlan extends FHCAPI_Controller
// fetching lvplan events
$result = $this->stundenplanlib->getEventsUser($start_date, $end_date, $uid);
$lvplanEvents = $this->getDataOrTerminateWithError($result);
// fetching moodle events
@@ -196,6 +205,38 @@ class LvPlan extends FHCAPI_Controller
));
}
public function getLeEvents($le_id = null, $start_date = null, $end_date = null, $stundenplan = 'stundenplandev')
{
if (is_null($le_id) || is_null($start_date) || is_null($end_date))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
if ($stundenplan !== 'stundenplandev' && $stundenplan !== 'stundenplan')
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->library('StundenplanLib');
$result = $this->stundenplanlib->getEventsByLE($le_id, $start_date, $end_date, $stundenplan);
$lvplanEvents = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($lvplanEvents);
}
public function getLvEvents($lv_id = null, $start_date = null, $end_date = null, $stundenplan = 'stundenplandev')
{
if (is_null($lv_id) || is_null($start_date) || is_null($end_date))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
if ($stundenplan !== 'stundenplandev' && $stundenplan !== 'stundenplan')
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->library('StundenplanLib');
$result = $this->stundenplanlib->getEventsByLV($lv_id, $start_date, $end_date, $stundenplan);
$this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
//TODO: delete this function if we don't use the old calendar export endpoints anymore
public function studiensemesterDateInterval($date)
{
@@ -17,60 +17,61 @@
*/
if (!defined('BASEPATH'))
exit('No direct script access allowed');
exit('No direct script access allowed');
class OtherLvPlan extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'otherLvPlanViewData' => ['basis/other_lv_plan:r'],
]);
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'otherLvPlanViewData' => ['basis/other_lv_plan:r'],
]);
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->library('ProfilLib');
}
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* retrieves viewData for other lv plan view
* @access public
* @param $uid the userID for which the other lv plan is being viewed
*/
public function otherLvPlanViewData($uid)
{
$isMitarbeiterResult = $this->MitarbeiterModel->isMitarbeiter($uid);
$isMitarbeiter = getData($isMitarbeiterResult);
$isStudent = !$isMitarbeiter;
/**
* retrieves viewData for other lv plan view
* @access public
* @param $uid the userID for which the other lv plan is being viewed
*/
public function otherLvPlanViewData($uid)
{
$isMitarbeiterResult = $this->MitarbeiterModel->isMitarbeiter($uid);
$isMitarbeiter = getData($isMitarbeiterResult);
$isStudent = !$isMitarbeiter;
$this->BenutzerModel->addSelect(["foto", "vorname", "nachname"]);
$this->BenutzerModel->addJoin("tbl_person", "person_id");
$personResult = $this->BenutzerModel->load([$uid]);
$person = hasData($personResult) ? getData($personResult) : null;
$resProfileData = $this->profillib->getView($uid);
$profileData = hasData($resProfileData) ? getData($resProfileData) : null;
$viewData = [
"user_data" => [
"username" => $uid,
"is_student" => $isStudent,
"is_mitarbeiter" => $isMitarbeiter,
"foto" => $person[0]->foto,
"vorname" => $person[0]->vorname,
"nachname" => $person[0]->nachname,
],
];
$viewData = [
"user_data" => [
"username" => $uid,
"is_student" => $isStudent,
"is_mitarbeiter" => $isMitarbeiter,
"foto" => $profileData->data->foto,
"vorname" => $profileData->data->vorname,
"nachname" => $profileData->data->nachname,
"titel" => $profileData->data->titel,
"postnomen" => $profileData->data->postnomen,
],
];
$this->terminateWithSuccess($viewData);
}
$this->terminateWithSuccess($viewData);
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
// -----------------------------------------------------------------------------------------------------------------
// Private methods
}
@@ -31,7 +31,7 @@ class RendererLoader extends FHCAPI_Controller
parent::__construct([
'GetRenderers' => self::PERM_LOGGED,
'GetTempusRenderers' => self::PERM_LOGGED,
]);
$this->load->library('LogLib');
@@ -66,6 +66,26 @@ class RendererLoader extends FHCAPI_Controller
$this->terminateWithSuccess($renderer_paths);
}
public function GetTempusRenderers(){
$renderer_paths = [];
Events::trigger(
'loadRenderers',
function & () use (&$renderer_paths)
{
return $renderer_paths;
}
);
Events::trigger(
'loadTempusRenderers',
function & () use (&$renderer_paths)
{
return $renderer_paths;
}
);
$this->terminateWithSuccess($renderer_paths);
}
@@ -0,0 +1,162 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the PhrasesLib (back-end)
* Provides data to the ajax get calls about the Phrasen plugin
* This controller works with JSON calls on the HTTP GET and the output is always JSON
*/
class TabulatorPresets extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getTabulatorPresets' => self::PERM_LOGGED,
'createTabulatorPreset' => self::PERM_LOGGED,
'updateTabulatorPreset' => self::PERM_LOGGED,
'deleteTabulatorPreset' => self::PERM_LOGGED,
]);
$this->load->model('tabulator/Tabulator_preset_model', 'TabulatorPresetModel');
$this->loadPhrases([
'global',
'tabulator_presets'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getTabulatorPresets()
{
$tableName = $this->input->get("tableName");
if (!$tableName) {
$this->terminateWithError(error($this->p->t("tabulator_presets", "invalid_params_err_msg")));
}
$uid = getAuthUID();
$presets = $this->TabulatorPresetModel->getTabulatorPresetsByUserAndTable($uid, $tableName);
$presetsData = $this->getDataOrTerminateWithError($presets) ?? [];
$this->terminateWithSuccess($presetsData);
}
public function createTabulatorPreset()
{
$tableName = $this->input->post("tableName");
$presetName = $this->input->post("presetName");
$preset = $this->input->post("preset");
if (!$tableName || !$presetName || !$preset) {
$this->terminateWithError($this->p->t("tabulator_presets", "invalid_params_err_msg"), "general", 400);
}
$uid = getAuthUID();
$existingPresetsResult = $this->TabulatorPresetModel->getTabulatorPresetsByUserAndTable($uid, $tableName);
$existingPresets = $this->getDataOrTerminateWithError($existingPresetsResult) ?? [];
if (count($existingPresets) > 19) {
$this->terminateWithError($this->p->t("tabulator_presets", "max_presets_count_err_msg"), "general", 409);
}
$existingPresetNames = array_map(function($presetInfo) {
return $presetInfo->preset_name;
}, $existingPresets);
if (in_array($presetName, $existingPresetNames)) {
$this->terminateWithError($this->p->t("tabulator_presets", "preset_name_duplicate_err_msg"), "general", 409);
}
$presetCreationResult = $this->TabulatorPresetModel->createTabulatorPreset($uid, $tableName, $presetName, $preset);
if (isError($presetCreationResult)) {
$this->terminateWithError($presetCreationResult->retval);
}
$newPresetData = $this->TabulatorPresetModel->getTabulatorPreset($presetCreationResult->retval);
$newPresetArray = $this->getDataOrTerminateWithError($newPresetData) ?? [null];
$newPreset = $newPresetArray[0];
$this->terminateWithSuccess($newPreset);
}
public function updateTabulatorPreset()
{
$presetId = $this->input->post("presetId");
$preset = $this->input->post("preset");
if (!$presetId || !$preset) {
$this->terminateWithError($this->p->t("tabulator_presets", "invalid_params_err_msg"), "general", 400);
}
$existingPresetData = $this->TabulatorPresetModel->getTabulatorPreset($presetId);
$existingPresetArray = $this->getDataOrTerminateWithError($existingPresetData) ?? [null];
$existingPreset = $existingPresetArray[0];
if (!$existingPreset) {
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_found_err_msg"), "general", 404);
}
$uid = getAuthUID();
if ($existingPreset->benutzer_uid !== $uid) {
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_own_update_err_msg"), "general", 403);
}
$presetUpdateResult = $this->TabulatorPresetModel->updateTabulatorPreset($presetId, $preset);
if (isError($presetUpdateResult)) {
$this->terminateWithError($presetUpdateResult->retval);
}
$updatedPresetData = $this->TabulatorPresetModel->getTabulatorPreset($presetId);
$updatedPresetArray = $this->getDataOrTerminateWithError($updatedPresetData) ?? [null];
$updatedPreset = $updatedPresetArray[0];
$this->terminateWithSuccess($updatedPreset);
}
public function deleteTabulatorPreset()
{
$presetId = $this->input->post("presetId");
if (!$presetId) {
$this->terminateWithError($this->p->t("tabulator_presets", "invalid_params_err_msg"), "general", 400);
}
$presetData = $this->TabulatorPresetModel->getTabulatorPreset($presetId);
$presetArray = $this->getDataOrTerminateWithError($presetData) ?? [null];
$preset = $presetArray[0];
if (!$preset) {
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_found_err_msg"), "general", 404);
}
$uid = getAuthUID();
if ($preset->benutzer_uid !== $uid) {
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_own_delete_err_msg"), "general", 403);
}
$presetDeletionResult = $this->TabulatorPresetModel->deleteTabulatorPreset($presetId);
if (isError($presetDeletionResult)) {
$this->terminateWithError($presetDeletionResult->retval);
}
$this->terminateWithSuccess();
}
}
@@ -0,0 +1,148 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \ReflectionMethod as ReflectionMethod;
use \ReflectionFunction as ReflectionFunction;
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about menues
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Treemenu extends FHCAPI_Controller
{
public function __construct()
{
// Load Router
$router = load_class('Router');
// Load Config
$config = load_class('Config');
$config->load('treemenu');
// Get Treemenu name & config
$name = $router->method;
$conf = $config->item($name);
// Get Permissions from config
$permissions = $conf['permissions'] ?? self::PERM_ANONYMOUS;
// Call constructor
parent::__construct([
$name => $permissions
]);
// Load Library
$libraryName = $conf['library'] ?? null;
$this->load->library($libraryName, null, 'treemenulib');
}
/**
* @param string $method
* @param array $params (optional)
*
* @return void
*/
public function _remap($method, $params = [])
{
if (!$this->treemenulib)
show_404();
$this->addMeta('ci_method', $method);
$this->addMeta('ci_params', $params);
$params = $this->uri->uri_to_assoc(6); // 6 = start of $params
$config = $this->treemenulib->config;
foreach (array_keys($params) as $key) {
if (!isset($config[$key]) || !$config[$key])
show_404();
$config = $config[$key];
}
// Prepare aliases
$argumentaliases = [];
if (property_exists($this->treemenulib, 'path_to_argument'))
$argumentaliases = array_flip($this->treemenulib->path_to_argument);
$methodaliases = [];
if (property_exists($this->treemenulib, 'redirect_method'))
$methodaliases = $this->treemenulib->redirect_method;
$items = [];
foreach ($config as $uripart => $children) {
if (!is_array($children)) {
$uripart = $children;
$children = [];
}
$methodName = $uripart;
if (isset($methodaliases[$methodName])) {
$methodName = $methodaliases[$methodName];
} elseif (strpbrk($methodName, ' _-') !== false) {
$methodName = lcfirst(str_replace([' ', '_', '-'], '', ucwords($methodName, " \t\r\n\f\v_-")));
}
// Prepare arguments
if (is_callable($methodName, false, $name)) {
if (is_string($methodName) && is_callable([$this->treemenulib, $methodName]))
$callable = [$this->treemenulib, $methodName];
else
$callable = $methodName;
} else {
$callable = [$this->treemenulib, $methodName];
}
if (is_array($callable))
$reflection = new ReflectionMethod($callable[0], $callable[1]);
elseif (is_string($callable) && strstr($callable, '::'))
$reflection = new ReflectionMethod($callable);
elseif ($name != 'Closure::__invoke' && strstr($name, '::__invoke'))
$reflection = new ReflectionMethod($callable, '__invoke');
else
$reflection = new ReflectionFunction($callable);
$arguments = [];
foreach ($reflection->getParameters() as $arg) {
if ($arg->name == 'path_template') {
$path = $params;
$path[$uripart] = '%s';
$arguments[] = $this->uri->assoc_to_uri($path);
} elseif ($arg->name == 'has_children') {
$arguments[] = $children;
} elseif ($arg->name == 'original_method') {
$arguments[] = $uripart;
} elseif (isset($argumentaliases[$arg->name]) && isset($params[$argumentaliases[$arg->name]])) {
$arguments[] = $params[$argumentaliases[$arg->name]];
} elseif (isset($params[$arg->name])) {
$arguments[] = $params[$arg->name];
} else {
$arguments[] = null;
}
}
// Call function from lib
$items = array_merge($items, call_user_func_array($callable, $arguments));
}
$this->terminateWithSuccess($items);
}
}
@@ -9,9 +9,10 @@ class Detailheader extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
'getHeader' => ['vertrag/mitarbeiter:r', 'basis/mitarbeiter:r'],
'getPersonAbteilung' => ['vertrag/mitarbeiter:r', 'basis/mitarbeiter:r'],
'getLeitungOrg' => ['vertrag/mitarbeiter:r', 'basis/mitarbeiter:r'],
'getHeader' => ['vertrag/mitarbeiter:r', 'basis/mitarbeiter:r', 'admin:r', 'assistenz:r'],
'getPersonAbteilung' => ['vertrag/mitarbeiter:r', 'basis/mitarbeiter:r', 'admin:r', 'assistenz:r'],
'getLeitungOrg' => ['vertrag/mitarbeiter:r', 'basis/mitarbeiter:r', 'admin:r', 'assistenz:r'],
'getSemesterStati' => ['admin:r', 'assistenz:r'],
]);
}
@@ -48,6 +49,17 @@ class Detailheader extends FHCAPI_Controller
$this->terminateWithSuccess(current($data));
}
public function getSemesterStati($prestudent_id)
{
$this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
$result = $this->PrestudentstatusModel->getAllPrestudentstatiWithStudiensemester($prestudent_id);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
}
@@ -0,0 +1,86 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Config extends FHCAPI_Controller
{
private $_ci;
private $_uid;
public function __construct()
{
parent::__construct([
'get' => ['admin:r', 'assistenz:r'],
'set' => ['admin:r', 'assistenz:r'],
]);
$this->_ci = &get_instance();
$this->_setAuthUID();
$this->loadPhrases([
'lehre'
]);
$this->_ci->load->library('VariableLib', ['uid' => $this->_uid]);
$this->_ci->load->library('PermissionLib');
}
public function get()
{
if (!($this->permissionlib->isBerechtigt('basis/tempus')) && !($this->permissionlib->isBerechtigt('lv-plan')))
$this->terminateWithSuccess([]);
$ignore_kollision = $this->_ci->variablelib->getVar('ignore_kollision');
$ignore_zeitsperre = $this->_ci->variablelib->getVar('ignore_zeitsperre');
$ignore_reservierung = $this->_ci->variablelib->getVar('ignore_reservierung');
$config['ignore_kollision'] = [
"type" => "checkbox",
"label" => 'ignore_kollision',
"value" => $ignore_kollision,
];
$config['ignore_zeitsperre'] = [
"type" => "checkbox",
"label" => 'ignore_zeitsperre',
"value" => $ignore_zeitsperre,
];
$config['ignore_reservierung'] = [
"type" => "checkbox",
"label" => 'ignore_reservierung',
"value" => $ignore_reservierung,
];
$this->terminateWithSuccess($config);
}
public function set()
{
if (!($this->permissionlib->isBerechtigt('basis/tempus')) && !($this->permissionlib->isBerechtigt('lv-plan')))
$this->terminateWithSuccess([]);
$this->load->model('system/Variable_model', 'VariableModel');
foreach (['ignore_kollision','ignore_zeitsperre','ignore_reservierung'] as $variable)
{
if ($this->_ci->input->post($variable) !== null)
{
$this->VariableModel->update(array('uid' => $this->_uid, 'name' => $variable), array('wert' => $this->input->post($variable)));
}
}
$this->terminateWithSuccess();
}
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid)
show_error('User authentification failed');
}
}
@@ -15,6 +15,7 @@ class Gruppe extends FHCAPI_Controller
'getBenutzerSearch' => ['admin:r', 'assistenz:r'],
'getAllSearch' => ['admin:r', 'assistenz:r'],
'getByLehreinheit' => ['admin:r', 'assistenz:r'],
'getGruppe' => ['admin:r', 'assistenz:r'],
]);
$this->_ci = &get_instance();
@@ -67,7 +68,7 @@ class Gruppe extends FHCAPI_Controller
$this->checkPermission($lehreinheit_id);
$result = $this->_ci->LehreinheitgruppeModel->addGroup($lehreinheit_id, $gid, !($lehrverband === 'false'));
$result = $this->_ci->LehreinheitgruppeModel->addGroup($lehreinheit_id, $gid, $lehrverband === true || $lehrverband === 'true');
if (isError($result))
$this->terminateWithError(getError($result));
@@ -75,6 +76,71 @@ class Gruppe extends FHCAPI_Controller
$this->terminateWithSuccess($result);
}
public function getGruppe()
{
$lehrverband = $this->input->post('lehrverband');
$gruppen_result = array();
if ($lehrverband === false)
{
$gruppen_result = $this->_ci->GruppeModel->loadWhere(array(
'studiengang_kz' => $this->input->post('stg_kz'),
'gruppe_kurzbz' => $this->input->post('gruppe_kurzbz'),
'aktiv' => true
));
}
else if ($lehrverband === true)
{
if (!isEmptyString($this->input->post('verband')))
{
$this->LehrverbandModel->db->where('verband', $this->input->post('verband'));
}
else
{
$this->LehrverbandModel->db->group_start();
$this->LehrverbandModel->db->where("trim(verband) = ''");
$this->LehrverbandModel->db->or_where("verband IS NULL");
$this->LehrverbandModel->db->group_end();
}
if (!isEmptyString($this->input->post('gruppe')))
{
$this->LehrverbandModel->db->where('gruppe', $this->input->post('gruppe'));
}
else
{
$this->LehrverbandModel->db->group_start();
$this->LehrverbandModel->db->where("trim(gruppe) = ''");
$this->LehrverbandModel->db->or_where("gruppe IS NULL");
$this->LehrverbandModel->db->group_end();
}
if (!isEmptyString((string)$this->input->post('semester')))
{
$this->LehrverbandModel->db->where('semester', $this->input->post('semester'));
}
else
{
$this->LehrverbandModel->db->group_start();
$this->LehrverbandModel->db->where("semester = ''");
$this->LehrverbandModel->db->or_where("semester IS NULL");
$this->LehrverbandModel->db->group_end();
}
$gruppen_result = $this->LehrverbandModel->loadWhere(array('studiengang_kz' => $this->input->post('stg_kz'), 'aktiv' => true));
}
if (!hasData($gruppen_result))
return $this->terminateWithError('No group found');
$gruppen_array = getData($gruppen_result)[0];
$this->terminateWithSuccess($gruppen_array->gid);
}
public function getByLehreinheit($lehreinheit_id = null)
{
if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id))
@@ -118,54 +184,17 @@ class Gruppe extends FHCAPI_Controller
$query_words = explode(' ', $query);
$this->_ci->GruppeModel->addSelect('gruppe_kurzbz,
studiengang_kz,
semester,
bezeichnung,
gid,
\'false\' as lehrverband');
$this->_ci->GruppeModel->db->where(array('sichtbar' => true, 'aktiv' => true, 'lehre' => true, 'direktinskription' => false, 'semester IS NOT NULL' => null));
$this->_ci->GruppeModel->db->group_start();
foreach ($query_words as $word)
{
$this->_ci->GruppeModel->db->group_start();
$this->_ci->GruppeModel->db->where('gruppe_kurzbz ILIKE', "%" . $word . "%");
$this->_ci->GruppeModel->db->or_where('bezeichnung ILIKE', "%" . $word . "%");
$this->_ci->GruppeModel->db->group_end();
}
$this->_ci->GruppeModel->db->group_end();
$gruppen_result = $this->_ci->GruppeModel->load();
$gruppen_array = array();
$gruppen_result = $this->_ci->GruppeModel->search($query_words);
if (isError($gruppen_result))
$this->terminateWithError(getError($gruppen_result), self::ERROR_TYPE_GENERAL);
$gruppen_array = array();
if (hasData($gruppen_result))
$gruppen_array = getData($gruppen_result);
$this->_ci->LehrverbandModel->addSelect('CONCAT(UPPER(CONCAT(typ, kurzbz)), \'\', semester, verband, COALESCE(gruppe,\'\')) as gruppe_kurzbz,
studiengang_kz,
semester,
tbl_lehrverband.bezeichnung,
gid,
\'true\' as lehrverband');
$this->_ci->LehrverbandModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$this->_ci->LehrverbandModel->addOrder('verband');
$this->_ci->LehrverbandModel->addOrder('gruppe');
$this->_ci->LehrverbandModel->db->where(array('tbl_lehrverband.aktiv' => true));
$this->_ci->LehrverbandModel->db->group_start();
foreach ($query_words as $word)
{
$this->_ci->LehrverbandModel->db->group_start();
$this->_ci->LehrverbandModel->db->where('CONCAT(CONCAT(typ, kurzbz), \'\', semester, verband, COALESCE(gruppe,\'\')) ILIKE', "%" . $word . "%");
$this->_ci->LehrverbandModel->db->or_where('tbl_lehrverband.bezeichnung ILIKE', "%" . $word . "%");
$this->_ci->LehrverbandModel->db->group_end();
}
$this->_ci->LehrverbandModel->db->group_end();
$lehrverband_result = $this->_ci->LehrverbandModel->load();
$lehrverband_result = $this->_ci->LehrverbandModel->search($query_words);
$lehrverband_array = array();
@@ -134,9 +134,14 @@ class Lektor extends FHCAPI_Controller
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
if (isset($formData['semesterstunden']) && (!is_numeric($formData['semesterstunden']) || $formData['semesterstunden'] === ''))
$nullable_fields = array('semesterstunden', 'stundensatz', 'planstunden');
foreach ($nullable_fields as $nullable_field)
{
$formData['semesterstunden'] = null;
if (isset($formData[$nullable_field]) && (!is_numeric($formData[$nullable_field]) || $formData[$nullable_field] === ''))
{
$formData[$nullable_field] = null;
}
}
$lehreinheit_permission = $this->checkPermission($lehreinheit_id, array('admin', 'assistenz', 'lv-plan'));
@@ -144,6 +149,9 @@ class Lektor extends FHCAPI_Controller
if (!$lehreinheit_permission)
$this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess'));
if (!is_null($this->getLektorVertrag($lehreinheit_id, $mitarbeiter_uid)) && (array_key_exists('mitarbeiter_uid', $formData) && $mitarbeiter_uid !== $formData['mitarbeiter_uid']))
$this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess'));
$result = $this->_ci->lektorlib->updateLektorFromLehreinheit($lehreinheit_id, $mitarbeiter_uid, $formData);
if (isError($result)) $this->terminateWithError(getError($result));
@@ -154,7 +162,7 @@ class Lektor extends FHCAPI_Controller
{
$value = str_replace(',', '.', $value);
if (!is_numeric($value))
if (!is_numeric($value) && $value !== "")
{
$this->form_validation->set_message('_check_decimal', 'Das Feld {field} muss eine Zahl sein.');
return false;
@@ -0,0 +1,84 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Noten extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getCertificate' => 'student/noten:r',
'getTeacherProposal' => 'student/noten:r',
]);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
// Load Phrases
$this->loadPhrases([
'stv',
'person',
'lehre'
]);
}
public function getCertificate($lv_id, $studiensemester_kurzbz = null)
{
if (is_null($lv_id) || !ctype_digit((string)$lv_id))
$this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->model('education/lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->LehrveranstaltungModel->loadWhere([
'lehrveranstaltung_id' => $lv_id
]);
$lehrveranstaltung = $this->getDataOrTerminateWithError($result);
if (!$lehrveranstaltung)
$this->terminateWithSuccess([]);
if ($studiensemester_kurzbz !== null && !$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
{
$this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester'));
}
$result = $this->ZeugnisnoteModel->getZeugnisnoten(null, $studiensemester_kurzbz, $lehrveranstaltung[0]->lehrveranstaltung_id);
$grades = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($grades);
}
public function getTeacherProposal($lv_id, $studiensemester_kurzbz = null)
{
if (is_null($lv_id) || !ctype_digit((string)$lv_id))
$this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->model('education/lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->load->model('education/Lvgesamtnote_model', 'LvgesamtnoteModel');
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->LehrveranstaltungModel->loadWhere([
'lehrveranstaltung_id' => $lv_id
]);
$lehrveranstaltung = $this->getDataOrTerminateWithError($result);
if (!$lehrveranstaltung)
$this->terminateWithSuccess([]);
if ($studiensemester_kurzbz !== null && !$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
{
$this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester'));
}
$result = $this->LvgesamtnoteModel->getLvGesamtNoten($lv_id, null, $studiensemester_kurzbz);
$grades = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($grades);
}
}
@@ -19,6 +19,8 @@
if (!defined('BASEPATH'))
exit('No direct script access allowed');
use CI3_Events as Events;
class Setup extends FHCAPI_Controller
{
private $_ci;
@@ -27,7 +29,8 @@ class Setup extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
'getTabs' => ['admin:r', 'assistenz:r'],
'getLETabs' => ['admin:r', 'assistenz:r'],
'getLVTabs' => ['admin:r', 'assistenz:r'],
'getStudiensemester' => ['admin:r', 'assistenz:r'],
'getSprache' => ['admin:r', 'assistenz:r'],
'getRaumtyp' => ['admin:r', 'assistenz:r'],
@@ -41,9 +44,10 @@ class Setup extends FHCAPI_Controller
$this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->_ci->load->library('VariableLib', ['uid' => $this->_uid]);
$this->_ci->load->helper('hlp_document');
}
public function getTabs()
public function getLETabs()
{
$tabs['details'] = array (
'title' => 'Details',
@@ -60,11 +64,43 @@ class Setup extends FHCAPI_Controller
'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Lektor.js'),
'config' => []
);
$tabs['termine'] = array (
'title' => 'Termine',
'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Termine.js'),
'config' => []
);
$tabs['notiz'] = array (
'title' => 'Notizen',
'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Notiz.js'),
'config' => []
);
Events::trigger('lvv_conf_tabs', function & () use (&$tabs) {
return $tabs;
});
$this->terminateWithSuccess($tabs);
}
public function getLVTabs()
{
$tabs['termine'] = array (
'title' => 'Termine',
'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/LVTermine.js'),
'config' => []
);
$tabs['noten'] = array (
'title' => 'Noten',
'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Noten.js'),
'config' => [
'usePoints' => defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE,
'edit' => 'both', // Possible values: both|header|inline
'delete' => 'inline', // Possible values: both|header|inline
'documents' => 'inline', // Possible values: both|header|inline
'documentslist' => gradesDocumentsList(),
'semesterSelect' => false
]
);
$this->terminateWithSuccess($tabs);
}
@@ -1,117 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class StgTree extends FHCAPI_Controller
{
public function __construct()
{
$permissions = [];
$router = load_class('Router');
$permissions[$router->method] = ['admin:r', 'assistenz:r'];
parent::__construct($permissions);
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
}
public function _remap($method, $params = [])
{
if ($method == '' || $method == 'index')
return $this->getBase();
if (!$this->permissionlib->isBerechtigt('assistenz', 's', $method)
&& !$this->permissionlib->isBerechtigt('admin', 's', $method)
) {
return $this->_outputAuthError([$method => ['admin:r', 'assistenz:r']]);
}
return $this->getStudiengang($method);
show_404();
}
protected function getBase()
{
$this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->StudiengangModel->addDistinct();
$this->StudiengangModel->addSelect("v.studiengang_kz AS link");
$this->StudiengangModel->addSelect(
"CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name",
false
);
$this->StudiengangModel->addSelect('erhalter_kz');
$this->StudiengangModel->addSelect('typ');
$this->StudiengangModel->addSelect('kurzbz');
$this->StudiengangModel->addSelect('studiengang_kz');
$this->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
$this->StudiengangModel->addOrder('erhalter_kz');
$this->StudiengangModel->addOrder('typ');
$this->StudiengangModel->addOrder('kurzbz');
$stgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: [];
$stgs = array_merge($stgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
if (!$stgs)
$this->terminateWithSuccess([]);
$this->StudiengangModel->db->where_in('studiengang_kz', $stgs);
$result = $this->StudiengangModel->loadWhere(['v.aktiv' => true]);
$list = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($list);
}
protected function getStudiengang($studiengang_kz)
{
$link = $studiengang_kz . '/';
$this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->StudiengangModel->addDistinct();
$this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false);
$this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester ORDER BY verband, gruppe LIMIT 1)) AS name", false);
$this->StudiengangModel->addSelect("TRUE AS leaf", false);
$this->StudiengangModel->addSelect('semester');
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->StudiengangModel->addOrder('semester');
$result = $this->StudiengangModel->loadWhere([
'v.studiengang_kz' => $studiengang_kz,
'v.aktiv' => true
]);
$list = $this->getDataOrTerminateWithError($result);
$result = $this->StudiengangModel->load($studiengang_kz);
$result = $this->getDataOrTerminateWithError($result);
if ($result)
{
if (current($result)->mischform)
{
$this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
$this->StudienordnungModel->addDistinct();
$this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link");
$this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name");
$this->StudienordnungModel->addSelect("TRUE as leaf", false);
$this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id');
$result = $this->StudienordnungModel->loadWhere([
'aktiv' => true,
'studiengang_kz' => $studiengang_kz,
'p.orgform_kurzbz !=' => 'DDP'
]);
$result = $this->getDataOrTerminateWithError($result);
$list = array_merge($list, $result);
}
}
$this->terminateWithSuccess($list);
}
}
@@ -26,7 +26,9 @@ class Studiensemester extends FHCAPI_Controller
'getAll' => self::PERM_LOGGED,
'getAktNext' => self::PERM_LOGGED,
'getStudienjahrByStudiensemester' => self::PERM_LOGGED,
'getAllStudiensemesterAndAktOrNext' => self::PERM_LOGGED
'getAllStudiensemesterAndAktOrNext' => self::PERM_LOGGED,
'current' => self::PERM_LOGGED,
'set' => self::PERM_LOGGED
)
);
// Load model StudiensemesterModel
@@ -166,4 +168,39 @@ class Studiensemester extends FHCAPI_Controller
$this->terminateWithSuccess(array($studiensemester, $aktuell));
}
public function current()
{
$result = $this->StudiensemesterModel->getNearest();
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
$this->terminateWithError('Kein Studiensemester aktiv');
if (count($data) > 1)
$this->terminateWithError('Mehrere Studiensemester aktiv');
$this->terminateWithSuccess(current($data)->studiensemester_kurzbz);
}
public function set()
{
$this->load->library('AuthLib');
$this->load->library('form_validation');
$this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$stdsem = $this->input->post('studiensemester_kurzbz');
$this->load->model('system/Variable_model', 'VariableModel');
$result = $this->VariableModel->setVariable(getAuthUID(), 'semester_aktuell', $stdsem);
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(true);
}
}
@@ -246,12 +246,12 @@ class Abschlusspruefung extends FHCAPI_Controller
{
$searchString = $this->input->get('searchString') ?? '';
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('person/Person_model', 'PersonModel');
$result = $this->MitarbeiterModel->searchMitarbeiter($searchString, 'ohneMaUid');
$result = $this->PersonModel->searchPerson($searchString, 'mitMaUid');
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
@@ -301,6 +301,7 @@ class Config extends FHCAPI_Controller
public function student()
{
$this->load->helper('hlp_document');
$result = [];
$config = $this->config->item('tabs');
@@ -376,9 +377,9 @@ class Config extends FHCAPI_Controller
'config' => [
'usePoints' => defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE,
'edit' => 'both', // Possible values: both|header|inline
'delete' => 'both', // Possible values: both|header|inline
'documents' => 'both', // Possible values: both|header|inline
'documentslist' => $this->gradesDocumentsList()
'delete' => 'inline', // Possible values: both|header|inline
'documents' => 'inline', // Possible values: both|header|inline
'documentslist' => gradesDocumentsList()
]
];
@@ -622,188 +623,6 @@ class Config extends FHCAPI_Controller
] + $this->kontoColumns();
}
/**
* Helper function to generate the default documentslist config for the
* grades tab.
*
* The resulting array consists of elements which are associative arrays
* that can have the following entries:
* title (required) on the first level this can be HTML code.
* permissioncheck (optional) an URL to an FHCAPI endpoint which returns
* true or false.
* link (optional) an URL that will be called if "action" and
* "children" are not defined.
* action (optional) an associative array that describes an
* POST action that will be called if "children" is
* not defined.
* It can have the following entries:
* - url (required) an URL to an FHCAPI endpoint.
* - post (optional) an associative array with the POST data to
* be sent.
* - response (optional) a string that will be displayed on success.
* children (optional) an array of child elements
*
* All strings that start with { and end with } in the URLs and the
* actions post parameter will be replaced with the corresponding
* attribute of the current dataset (e.G: {uid} will be replaced with the
* uid of the current dataset)
*
* @return array
*/
protected function gradesDocumentsList()
{
$permissioncheck = site_url("api/frontend/v1/documents/permissionAlternativeFormat/{studiengang_kz}");
$title_ger = $this->p->t("global", "deutsch");
$title_eng = $this->p->t("global", "englisch");
$title_ff = $this->p->t("stv", "document_certificate");
$title_lv = $this->p->t("stv", "document_coursecertificate");
$link_ff = "documents/export/" .
"zertifikat.rdf.php/" .
"Zertifikat" .
"?stg_kz={studiengang_kz_lv}" .
"&uid={uid}" .
"&ss={studiensemester_kurzbz}" .
"&lvid={lehrveranstaltung_id}";
$link_lv_ger = "documents/export/" .
"lehrveranstaltungszeugnis.rdf.php/" .
"LVZeugnis" .
"?stg_kz={studiengang_kz}" .
"&uid={uid}" .
"&ss={studiensemester_kurzbz}" .
"&lvid={lehrveranstaltung_id}";
$link_lv_eng = "documents/export/" .
"lehrveranstaltungszeugnis.rdf.php/" .
"LVZeugnisEng" .
"?stg_kz={studiengang_kz}" .
"&uid={uid}" .
"&ss={studiensemester_kurzbz}" .
"&lvid={lehrveranstaltung_id}";
$archive_url = "api/frontend/v1/documents/archiveSigned";
$archive_response = $this->p->t("stv", "document_signed_and_archived");
$archive_post_ff = [
"xml" => "zertifikat.rdf.php",
"xsl" => "Zertifikat",
"stg_kz" => "{studiengang_kz_lv}",
"uid" => "{uid}",
"ss" => "{studiensemester_kurzbz}",
"lvid" => "{lehrveranstaltung_id}"
];
$archive_post_lv_ger = [
"xml" => "lehrveranstaltungszeugnis.rdf.php",
"xsl" => "LVZeugnis",
"stg_kz" => "{studiengang_kz}",
"uid" => "{uid}",
"ss" => "{studiensemester_kurzbz}",
"lvid" => "{lehrveranstaltung_id}"
];
$archive_post_lv_eng = [
"xml" => "lehrveranstaltungszeugnis.rdf.php",
"xsl" => "LVZeugnisEng",
"stg_kz" => "{studiengang_kz}",
"uid" => "{uid}",
"ss" => "{studiensemester_kurzbz}",
"lvid" => "{lehrveranstaltung_id}"
];
$list = [
[
'title' => '<i class="fa fa-download" title="' . $this->p->t("stv", "document_download") . '"></i>',
'children' => [
[
'title' => $title_ff,
'link' => site_url($link_ff)
],
[
'title' => $title_lv,
'children' => [
[
'title' => $title_ger,
'link' => site_url($link_lv_ger),
'children' => [
[
'title' => 'PDF',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_ger)
],
[
'title' => 'DOC',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_ger . "&output=doc")
],
[
'title' => 'ODT',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_ger . "&output=odt")
]
]
],
[
'title' => $title_eng,
'link' => site_url($link_lv_eng),
'children' => [
[
'title' => 'PDF',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_eng)
],
[
'title' => 'DOC',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_eng . "&output=doc")
],
[
'title' => 'ODT',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_eng . "&output=odt")
]
]
]
]
]
]
],
[
'title' => '<i class="fas fa-archive" title="' . $this->p->t("stv", "document_archive") . '"></i>',
'children' => [
[
'title' => $title_ff,
'action' => [
'url' => site_url($archive_url),
'post' => $archive_post_ff,
'response' => $archive_response
]
],
[
'title' => $title_lv,
'children' => [
[
'title' => $title_ger,
'action' => [
'url' => site_url($archive_url),
'post' => $archive_post_lv_ger,
'response' => $archive_response
]
],
[
'title' => $title_eng,
'action' => [
'url' => site_url($archive_url),
'post' => $archive_post_lv_eng,
'response' => $archive_response
]
]
]
]
]
]
];
return $list;
}
/**
* Sort tab list
*
@@ -34,7 +34,7 @@ class LvTermine extends FHCAPI_Controller
//TODO Build own lib or combine with Controller Stundenplan.php
//here use of logic of Stundenplan.php, extended with parameters uid, grouping, and used dbTable
public function getStundenplan($uid, $start_date = null, $end_date = null, $groupConsecutiveHours = false, $dbStundenplanTable = "stundenplan")
public function getStundenplan($uid, $start_date = null, $end_date = null, $dbStundenplanTable = "stundenplan", $groupConsecutiveHours = false)
{
$student_uid = $uid;
$semester_range = $this->studienSemesterErmitteln($start_date, $end_date);
@@ -80,13 +80,6 @@ class LvTermine extends FHCAPI_Controller
$stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? [];
$this->terminateWithSuccess($stundenplan_data);
$this->expand_object_information($stundenplan_data);
$this->returnObj['$stundenplan_query'] = $stundenplan_query;
$this->returnObj['$student_lehrverband'] = $student_lehrverband;
$this->returnObj['$benutzer_gruppen'] = $benutzer_gruppen;
$this->terminateWithSuccess($stundenplan_data);
}
public function getStudiensemester()
@@ -144,6 +144,7 @@ class Student extends FHCAPI_Controller
. $this->PrestudentModel->escape($studiensemester_kurzbz)
. ") AS statusofsemester"
);
$this->PrestudentModel->addSelect($this->PrestudentModel->escape($studiensemester_kurzbz) . ' as query_studiensemester_kurzbz');
$this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT');
$this->PrestudentModel->addJoin('public.tbl_benutzer b', 'student_uid = uid', 'LEFT');
@@ -138,7 +138,7 @@ class Students extends FHCAPI_Controller
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
@@ -190,14 +190,14 @@ class Students extends FHCAPI_Controller
) AS semester", false);
$this->studentlistlib->addSelect("COALESCE(v.verband::text, ''::text) AS verband");
$this->studentlistlib->addSelect("COALESCE(v.gruppe::text, ''::text) AS gruppe");
$this->addFilter($studiensemester_kurzbz);
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
@@ -235,59 +235,66 @@ class Students extends FHCAPI_Controller
) AS semester", false);
$this->studentlistlib->addSelect("COALESCE(v.verband::text, ''::text) AS verband");
$this->studentlistlib->addSelect("COALESCE(v.gruppe::text, ''::text) AS gruppe");
$this->addFilter($studiensemester_kurzbz);
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
public function getPrestudents(
$studiengang_kz,
$studiengang_typ_kurzbz,
$studiensemester_kurzbz = null,
$filter = null
) {
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiengang_kz' => $studiengang_kz,
'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'filter' => $filter
));
$this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter);
$this->fetchPrestudents($studiengang_typ_kurzbz, $studiensemester_kurzbz, $filter);
}
public function getPrestudentsOrgform(
$studiengang_kz,
$studiengang_typ_kurzbz,
$orgform_kurzbz,
$studiensemester_kurzbz = null,
$filter = null
) {
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiengang_kz' => $studiengang_kz,
'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'filter' => $filter,
'orgform_kurzbz' => $orgform_kurzbz
));
$this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter, $orgform_kurzbz);
$this->fetchPrestudents($studiengang_typ_kurzbz, $studiensemester_kurzbz, $filter, $orgform_kurzbz);
}
/**
* @param integer $studiengang_kz
* @param string $studiengang_typ_kurzbz
* @param string $studiensemester_kurzbz (optional)
* @param string $filter (optional)
* @param string $orgform_kurzbz (optional)
*
* @return void
*/
protected function fetchPrestudents($studiengang_kz, $studiensemester_kurzbz = null, $filter = null, $orgform_kurzbz = null)
protected function fetchPrestudents($studiengang_typ_kurzbz, $studiensemester_kurzbz = null, $filter = null, $orgform_kurzbz = null)
{
$studiengang_kz = $this->getStudiengangKz($studiengang_typ_kurzbz);
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
$orgform_kurzbz = $this->getOrgformKurzbz($orgform_kurzbz);
if ($studiengang_kz === null)
show_404();
$stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
$selectRT = "
@@ -439,19 +446,21 @@ class Students extends FHCAPI_Controller
$this->studentlistlib->addSelect("'' AS verband");
$this->studentlistlib->addSelect("'' AS gruppe");
$query_studiensemester_kurzbz = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : '\'NULL\'';
$this->studentlistlib->addSelect($query_studiensemester_kurzbz . ' as query_studiensemester_kurzbz');
$this->addFilter($studiensemester_kurzbz);
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
public function getStudents(
$studiensemester_kurzbz,
$studiengang_kz,
$studiengang_typ_kurzbz,
$semester = null,
$verband = null,
$gruppe = null
@@ -459,18 +468,18 @@ class Students extends FHCAPI_Controller
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'studiengang_kz' => $studiengang_kz,
'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'semester' => $semester,
'verband' => $verband,
'gruppe' => $gruppe
));
$this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, null);
$this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, $verband, $gruppe, null, null);
}
public function getStudentsOrgform(
$studiensemester_kurzbz,
$studiengang_kz,
$studiengang_typ_kurzbz,
$orgform_kurzbz,
$semester = null,
$verband = null,
@@ -479,37 +488,37 @@ class Students extends FHCAPI_Controller
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'studiengang_kz' => $studiengang_kz,
'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'orgform_kurzbz' => $orgform_kurzbz,
'semester' => $semester,
'verband' => $verband,
'gruppe' => $gruppe
));
$this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, $orgform_kurzbz);
$this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, $verband, $gruppe, null, $orgform_kurzbz);
}
public function getStudentsSpezialgruppe(
$studiensemester_kurzbz,
$studiengang_kz,
$studiengang_typ_kurzbz,
$semester,
$gruppe_kurzbz
) {
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'studiengang_kz' => $studiengang_kz,
'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'semester' => $semester,
'gruppe_kurzbz' => $gruppe_kurzbz
));
$this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, null);
$this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, null, null, $gruppe_kurzbz, null);
}
public function getStudentsOrgformSpezialgruppe(
$studiensemester_kurzbz,
$orgform_kurzbz,
$studiengang_kz,
$studiengang_typ_kurzbz,
$semester,
$gruppe_kurzbz
) {
@@ -517,17 +526,17 @@ class Students extends FHCAPI_Controller
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'orgform_kurzbz' => $orgform_kurzbz,
'studiengang_kz' => $studiengang_kz,
'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'semester' => $semester,
'gruppe_kurzbz' => $gruppe_kurzbz
));
$this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, $orgform_kurzbz);
$this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, null, null, $gruppe_kurzbz, $orgform_kurzbz);
}
/**
* @param integer $studiengang_kz
* @param string $studiensemester_kurzbz
* @param string $studiengang_typ_kurzbz
* @param integer $semester (optional)
* @param string $verband (optional)
* @param integer $gruppe (optional)
@@ -538,13 +547,20 @@ class Students extends FHCAPI_Controller
*/
protected function fetchStudents(
$studiensemester_kurzbz,
$studiengang_kz,
$studiengang_typ_kurzbz,
$semester = null,
$verband = null,
$gruppe = null,
$gruppe_kurzbz = null,
$orgform_kurzbz = null
) {
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
$studiengang_kz = $this->getStudiengangKz($studiengang_typ_kurzbz);
$orgform_kurzbz = $this->getOrgformKurzbz($orgform_kurzbz);
if ($studiengang_kz === null)
show_404();
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -556,6 +572,7 @@ class Students extends FHCAPI_Controller
$this->studentlistlib->addJoin("public.tbl_student s", "prestudent_id");
$this->studentlistlib->addSelect("'' AS priorisierung_relativ");
$this->studentlistlib->addSelect($this->PrestudentModel->escape($studiensemester_kurzbz) . ' as query_studiensemester_kurzbz');
if ($gruppe_kurzbz !== null) {
$this->studentlistlib->addJoin('public.tbl_benutzergruppe g', 'uid', '', 'after_b');
@@ -594,10 +611,22 @@ class Students extends FHCAPI_Controller
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
protected function decodeTagsJsonInResult(&$data)
{
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED) {
array_walk($data, function($item, $key) {
if(isset($item->tags))
{
$item->tags = json_decode($item->tags);
}
});
}
}
/**
* @param string $prestudent_id
*
@@ -611,6 +640,8 @@ class Students extends FHCAPI_Controller
'prestudent_id' => $prestudent_id,
));
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -618,7 +649,7 @@ class Students extends FHCAPI_Controller
$this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester'));
}
$this->studentlistlib->addSelect("COALESCE(
v.semester::text,
CASE
@@ -638,7 +669,7 @@ class Students extends FHCAPI_Controller
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
@@ -655,6 +686,8 @@ class Students extends FHCAPI_Controller
'student_uid' => $student_uid,
));
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -664,14 +697,14 @@ class Students extends FHCAPI_Controller
$this->studentlistlib->addWhere('s.student_uid', $student_uid);
$this->addFilter($studiensemester_kurzbz);
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
@@ -689,6 +722,8 @@ class Students extends FHCAPI_Controller
'person_id' => $person_id,
));
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -699,13 +734,13 @@ class Students extends FHCAPI_Controller
$this->studentlistlib->addWhere('p.person_id', $person_id);
$this->addFilter($studiensemester_kurzbz);
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
@@ -721,6 +756,8 @@ class Students extends FHCAPI_Controller
'studiensemester_kurzbz' => $studiensemester_kurzbz
));
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
$this->load->library('SearchLib', [ 'config' => 'searchstv' ]);
$this->load->library('form_validation');
@@ -755,6 +792,7 @@ class Students extends FHCAPI_Controller
END
) AS semester", false);
$this->studentlistlib->addSelect($this->PrestudentModel->escape($studiensemester_kurzbz) . ' as query_studiensemester_kurzbz');
if ($prestudent_ids && $student_uids) {
$this->studentlistlib->addWhere('tbl_prestudent.prestudent_id', $prestudent_ids);
@@ -773,7 +811,7 @@ class Students extends FHCAPI_Controller
$result = $this->studentlistlib->execute($studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->decodeTagsJsonInResult($data);
$this->terminateWithSuccess($data);
}
@@ -802,4 +840,55 @@ class Students extends FHCAPI_Controller
}
}
}
protected function getStudiengangKz($studiengang_typ_kurzbz)
{
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$result = $this->StudiengangModel->loadWhere([
'LOWER(CONCAT(typ, kurzbz)) =' => strtolower($studiengang_typ_kurzbz)
]);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
return null;
return current($data)->studiengang_kz;
}
protected function getStudiensemesterKurzbz($studiensemester_kurzbz)
{
if ($studiensemester_kurzbz === null)
return null;
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->StudiensemesterModel->loadWhere([
'LOWER(studiensemester_kurzbz) =' => strtolower($studiensemester_kurzbz)
]);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
return $studiensemester_kurzbz;
return current($data)->studiensemester_kurzbz;
}
protected function getOrgformKurzbz($orgform_kurzbz)
{
if ($orgform_kurzbz === null)
return null;
$this->load->model('codex/Orgform_model', 'OrgformModel');
$result = $this->OrgformModel->loadWhere([
'LOWER(orgform_kurzbz) =' => strtolower($orgform_kurzbz)
]);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
return $orgform_kurzbz;
return current($data)->orgform_kurzbz;
}
}
@@ -15,7 +15,9 @@ class Tags extends Tag_Controller
'addTag' => self::BERECHTIGUNG_KURZBZ,
'updateTag' => self::BERECHTIGUNG_KURZBZ,
'doneTag' => self::BERECHTIGUNG_KURZBZ,
'deleteTag' => self::BERECHTIGUNG_KURZBZ
'deleteTag' => self::BERECHTIGUNG_KURZBZ,
'getAllTags' => self::BERECHTIGUNG_KURZBZ,
'rebuildTagsForTypeId' => self::BERECHTIGUNG_KURZBZ,
]);
$this->config->load('stv');
@@ -45,4 +47,5 @@ class Tags extends Tag_Controller
{
parent::doneTag($this->config->item('stv_prestudent_tags'));
}
}
@@ -1,513 +0,0 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about verbände
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Verband extends FHCAPI_Controller
{
public function __construct()
{
$permissions = [];
$router = load_class('Router');
$permissions[$router->method] = ['admin:r', 'assistenz:r'];
parent::__construct($permissions);
// Load Models
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
}
/**
* Remap calls:
* /
* /(studiengang_kz) => getStudiengang
* /(studiengang_kz)/(semester) => getSemester
* /(studiengang_kz)/(semester)/(verband) => getVerband
* /(studiengang_kz)/(org_form) => getStudiengang
* /(studiengang_kz)/(org_form)/(semester) => getSemester
* /(studiengang_kz)/(org_form)/(semester)/(verband) => getVerband
*
* @param string $method
* @param array $params (optional)
*
* @return void
*/
public function _remap($method, $params = [])
{
if ($method == '' || $method == 'index')
return $this->getBase();
// NOTE(chris): Test if access is allowed ($method is the Studiengang)
if (!$this->permissionlib->isBerechtigt('assistenz', 's', $method)
&& !$this->permissionlib->isBerechtigt('admin', 's', $method)
) {
return $this->_outputAuthError([$method => ['admin:r', 'assistenz:r']]);
}
$count = count($params);
if (!$count)
return $this->getStudiengang($method);
if ($count == 1) {
if (is_numeric($params[0]))
return $this->getSemester($method, $params[0]);
elseif ($params[0] == 'prestudent')
return $this->terminateWithSuccess($this->getStdSem($method . '/prestudent/', $method));
else
return $this->getStudiengang($method, $params[0]);
}
if ($count == 2) {
if (is_numeric($params[0]))
return $this->getVerband($method, $params[0], $params[1]);
elseif ($params[1] == 'prestudent')
return $this->terminateWithSuccess($this->getStdSem($method . '/' . $params[0] . '/prestudent/', $method));
else
return $this->getSemester($method, $params[1], $params[0]);
}
if ($count == 3 && !is_numeric($params[0]) && is_numeric($params[1]) && !is_numeric($params[2]))
return $this->getVerband($method, $params[1], $params[2], $params[0]);
show_404();
}
/**
* @return void
*/
protected function getBase()
{
$this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->StudiengangModel->addDistinct();
$this->StudiengangModel->addSelect("v.studiengang_kz AS link");
$this->StudiengangModel->addSelect(
"CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name",
false
);
$this->StudiengangModel->addSelect('erhalter_kz');
$this->StudiengangModel->addSelect('typ');
$this->StudiengangModel->addSelect('kurzbz');
$this->StudiengangModel->addSelect('studiengang_kz');
$this->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
$this->StudiengangModel->addOrder('erhalter_kz');
$this->StudiengangModel->addOrder('typ');
$this->StudiengangModel->addOrder('kurzbz');
$stgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: [];
$stgs = array_merge($stgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
if (!$stgs)
$this->terminateWithSuccess([]);
$this->StudiengangModel->db->where_in('studiengang_kz', $stgs);
$result = $this->StudiengangModel->loadWhere(['v.aktiv' => true]);
$list = $this->getDataOrTerminateWithError($result);
if ($this->permissionlib->isBerechtigt('inout/uebersicht'))
$list[] = [
'name' => 'International',
'link' => 'inout',
'children' => [
[
'name' => 'Incoming',
'link' => 'inout/incoming',
'leaf' => true
],
[
'name' => 'Outgoing',
'link' => 'inout/outgoing',
'leaf' => true
],
[
'name' => 'Gemeinsame Studien',
'link' => 'inout/gemeinsamestudien',
'leaf' => true
]
]
];
$this->terminateWithSuccess($list);
}
/**
* @param integer $studiengang_kz
* @param string $orgform (optional)
*
* @return void
*/
protected function getStudiengang($studiengang_kz, $org_form = null)
{
$link = $studiengang_kz . '/';
if ($org_form !== null)
$link .= $org_form . '/';
$this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->StudiengangModel->addDistinct();
$this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false);
$this->StudiengangModel->addSelect("CONCAT(
UPPER(CONCAT(typ, kurzbz)),
'-',
semester,
(
SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END
FROM public.tbl_lehrverband
WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester
ORDER BY verband, gruppe LIMIT 1
)
) AS name", false);
$this->StudiengangModel->addSelect('semester');
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->StudiengangModel->addOrder('semester');
if ($org_form !== null) {
$this->StudiengangModel->addSelect("v.orgform_kurzbz");
$this->StudiengangModel->db->group_start();
$this->StudiengangModel->db->where('v.semester', 0);
$this->StudiengangModel->db->or_where('v.orgform_kurzbz', $org_form);
$this->StudiengangModel->db->group_end();
}
$result = $this->StudiengangModel->loadWhere([
'v.studiengang_kz' => $studiengang_kz,
'v.aktiv' => true
]);
$list = $this->getDataOrTerminateWithError($result);
array_unshift($list, [
'name' => 'PreStudent',
'link' => $link . 'prestudent',
'no_sem_reload' => true,
'stg_kz' => (int)$studiengang_kz,
'children' => $this->getStdSem($link . 'prestudent/', $studiengang_kz)
]);
if ($org_form === null) {
// NOTE(chris): if mischform show orgforms
$result = $this->StudiengangModel->load($studiengang_kz);
$result = $this->getDataOrTerminateWithError($result);
if ($result) {
if (current($result)->mischform) {
$this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
$this->StudienordnungModel->addDistinct();
$this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link");
$this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name");
$this->StudienordnungModel->addSelect("studiengang_kz AS stg_kz");
$this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id');
$result = $this->StudienordnungModel->loadWhere([
'aktiv' => true,
'studiengang_kz' => $studiengang_kz,
'p.orgform_kurzbz !=' => 'DDP'
]);
$result = $this->getDataOrTerminateWithError($result);
$list = array_merge($list, $result);
}
}
}
$this->terminateWithSuccess($list);
}
/**
* @param integer $studiengang_kz
* @param integer $semester
* @param string $orgform
*
* @return void
*/
protected function getSemester($studiengang_kz, $semester, $org_form = null)
{
$link = $studiengang_kz . '/';
if ($org_form !== null)
$link .= $org_form . '/';
$link .= $semester . '/';
$this->load->model('organisation/Gruppe_model', 'GruppeModel');
$this->GruppeModel->addDistinct();
$this->GruppeModel->addSelect("CONCAT(" . $this->GruppeModel->escape($link . 'grp/') . ", gruppe_kurzbz) AS link", false);
$this->GruppeModel->addSelect("CONCAT(gruppe_kurzbz, ' (', bezeichnung, ')') AS name", false);
$this->GruppeModel->addSelect("TRUE AS leaf", false);
$this->GruppeModel->addSelect('sort');
$this->GruppeModel->addSelect('gruppe_kurzbz');
$this->GruppeModel->addSelect($this->GruppeModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->GruppeModel->addOrder('sort');
$this->GruppeModel->addOrder('gruppe_kurzbz');
$where = [
'studiengang_kz' => $studiengang_kz,
'semester' => $semester,
'lehre' => true,
'sichtbar' => true,
'aktiv' => true,
'direktinskription' => false
];
if ($org_form !== null)
$where['orgform_kurzbz'] = $org_form;
$result = $this->GruppeModel->loadWhere($where);
$list = $this->getDataOrTerminateWithError($result);
$this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", verband) AS link", false);
$this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband ORDER BY gruppe LIMIT 1)) AS name", false);
$this->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($semester) . ' AS semester');
$this->StudiengangModel->addSelect('verband');
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->StudiengangModel->addOrder('verband');
$this->StudiengangModel->addGroupBy('link, name, verband');
$where = [
'v.studiengang_kz' => $studiengang_kz,
'v.semester' => $semester,
'v.verband !=' => '',
'v.aktiv' => true
];
if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all?
$where['v.orgform_kurzbz'] = $org_form;
$result = $this->StudiengangModel->loadWhere($where);
$result = $this->getDataOrTerminateWithError($result);
$list = array_merge($list, $result);
$this->terminateWithSuccess($list);
}
/**
* @param integer $studiengang_kz
* @param integer $semester
* @param integer $verband
* @param string $orgform
*
* @return void
*/
protected function getVerband($studiengang_kz, $semester, $verband, $org_form = null)
{
$link = $studiengang_kz . '/';
if ($org_form !== null)
$link .= $org_form . '/';
$link .= $semester . '/'. $verband . '/';
$this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->StudiengangModel->addDistinct();
$this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", gruppe) AS link", false);
$this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, gruppe, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband AND gruppe=v.gruppe ORDER BY gruppe LIMIT 1)) AS name", false);
$this->StudiengangModel->addSelect("TRUE AS leaf", false);
$this->StudiengangModel->addSelect('v.semester');
$this->StudiengangModel->addSelect('v.verband');
$this->StudiengangModel->addSelect('gruppe');
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->StudiengangModel->addOrder('gruppe');
$where = [
'v.studiengang_kz' => $studiengang_kz,
'v.semester' => $semester,
'v.verband' => $verband,
'v.gruppe !=' => '',
'v.aktiv' => true
];
if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all?
$where['v.orgform_kurzbz'] = $org_form;
$result = $this->StudiengangModel->loadWhere($where);
$list = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($list);
}
/**
* @param string $link
* @param integer $studiengang_kz
*
* @return array
*/
protected function getStdSem($link, $studiengang_kz)
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->load->model('system/Variable_model', 'VariableModel');
$result = $this->VariableModel->getVariables(getAuthUID(), ['number_displayed_past_studiensemester']);
$data = $this->getDataOrTerminateWithError($result);
$this->load->config('stv');
$number_displayed_past_studiensemester_default = $this->config->item('number_displayed_past_studiensemester_default');
$number_displayed_past_studiensemester = $data['number_displayed_past_studiensemester'] ?? $number_displayed_past_studiensemester_default;
$this->StudiensemesterModel->addPlusMinus(null, $number_displayed_past_studiensemester);
$this->StudiensemesterModel->addOrder('ende');
$result = $this->StudiensemesterModel->load();
$studiensemester = $this->getDataOrTerminateWithError($result);
$result = [];
$studiengang_kz = (int)$studiengang_kz;
foreach ($studiensemester as $sem) {
$semlink = $link . $sem->studiensemester_kurzbz;
$intlink = $semlink . '/interessenten';
$result[] = [
'name' => $sem->studiensemester_kurzbz,
'link' => $semlink,
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Interessenten',
'link' => $intlink,
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Bewerbung nicht abgeschickt',
'link' => $intlink . '/bewerbungnichtabgeschickt',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Bewerbung abgeschickt, Status unbestätigt',
'link' => $intlink . '/bewerbungabgeschickt',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'ZGV erfüllt',
'link' => $intlink . '/zgv',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Status bestätigt',
'link' => $intlink . '/statusbestaetigt',
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Nicht zum Reihungstest angemeldet',
'link' => $intlink . '/statusbestaetigtrtnichtangemeldet',
'leaf' => true
],
[
'name' => 'Reihungstest angemeldet',
'link' => $intlink . '/statusbestaetigtrtangemeldet',
'leaf' => true
]
]
],
[
'name' => 'Nicht zum Reihungstest angemeldet',
'link' => $intlink . '/reihungstestnichtangemeldet',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Reihungstest angemeldet',
'link' => $intlink . '/reihungstestangemeldet',
'stg_kz' => $studiengang_kz,
'leaf' => true
]
]
],
[
'name' => 'Bewerber',
'link' => $semlink . '/bewerber',
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Nicht zum Reihungstest angemeldet',
'link' => $intlink . '/bewerberrtnichtangemeldet',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Reihungstest angemeldet',
'link' => $intlink . '/bewerberrtangemeldet',
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Teilgenommen',
'link' => $intlink . '/bewerberrtangemeldetteilgenommen',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Nicht teilgenommen',
'link' => $intlink . '/bewerberrtangemeldetnichtteilgenommen',
'stg_kz' => $studiengang_kz,
'leaf' => true
]
]
]
]
],
[
'name' => 'Aufgenommen',
'link' => $semlink . '/aufgenommen',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Warteliste',
'link' => $semlink . '/warteliste',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Absage',
'link' => $semlink . '/absage',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Incoming',
'link' => $semlink . '/incoming',
'stg_kz' => $studiengang_kz,
'leaf' => true
]
]
];
}
return $result;
}
}
@@ -0,0 +1,157 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Config extends FHCAPI_Controller
{
private $_ci;
public function __construct()
{
parent::__construct([
'get' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
'getHeader' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
'set' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
'updateCollision' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
]);
// Load Phrases
$this->loadPhrases([
'ui',
]);
$this->_ci = &get_instance();
$this->_ci->load->model('ressource/Kalenderstatus_model', 'KalenderStatusModel');
$this->_ci->load->model('system/Variable_model', 'VariableModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
}
public function get()
{
$config = [];
$var_array = array(
'ignore_kollision',
'kollision_student',
'ignore_reservierung',
'ignore_zeitsperre',
'ignore_resources_collisions',
'roomless_planning',
'priority_room_planning',
'dialog_room_planning'
);
$result = $this->_ci->VariableModel->getVariables(getAuthUID(), $var_array);
$data = $this->getDataOrTerminateWithError($result);
$config['ignore_kollision'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'ignore_kollision'),
"value" => ($data['ignore_kollision'] ?? 'false') === 'true'
];
$config['kollision_student'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'kollision_student'),
"value" => ($data['kollision_student'] ?? 'false') === 'true'
];
$config['ignore_reservierung'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'ignore_reservierung'),
"value" => ($data['ignore_reservierung'] ?? 'false') === 'true'
];
$config['ignore_zeitsperre'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'ignore_zeitsperre'),
"value" => ($data['ignore_zeitsperre'] ?? 'false') === 'true'
];
$config['ignore_resources_collisions'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'ignore_resources_collisions'),
"value" => ($data['ignore_resources_collisions'] ?? 'false') === 'true'
];
$config['roomless_planning'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'roomless_planning'),
"value" => ($data['roomless_planning'] ?? 'false') === 'true'
];
$config['priority_room_planning'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'priority_room_planning'),
"value" => ($data['priority_room_planning'] ?? 'false') === 'true'
];
$config['dialog_room_planning'] = [
"type" => "checkbox",
"label" => $this->p->t('ui', 'dialog_room_planning'),
"value" => ($data['dialog_room_planning'] ?? 'false') === 'true'
];
$this->terminateWithSuccess($config);
}
public function getHeader()
{
$language = getUserLanguage() == 'German' ? 0 : 1;
$this->_ci->KalenderStatusModel->addSelect('*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS status');
$this->_ci->KalenderStatusModel->addOrder('sort');
$this->_ci->KalenderStatusModel->db->where_not_in('status_kurzbz', array('archived', 'deleted'));
$visible_status = $this->_ci->KalenderStatusModel->load();
$visible_status = getData($visible_status);
$config['visible_status']['all'] = 'Alle';
foreach ($visible_status as $status)
{
$config['visible_status'][$status->status_kurzbz] = $status->status;
}
$this->terminateWithSuccess($config);
}
public function set()
{
$configs = array(
'ignore_kollision',
'kollision_student',
'ignore_reservierung',
'ignore_zeitsperre',
'ignore_resources_collisions',
'roomless_planning',
'priority_room_planning',
'dialog_room_planning'
);
foreach ($configs as $config)
{
$this->_ci->VariableModel->setVariable(
getAuthUID(),
$config,
$this->input->post($config) === true ? 'true' : 'false'
);
}
$this->terminateWithSuccess();
}
public function updateCollision()
{
$original_ignore = $this->_ci->variablelib->getVar('ignore_kollision');
$this->_ci->VariableModel->setVariable(
getAuthUID(),
'ignore_kollision',
$original_ignore === 'true' ? 'false' : 'true'
);
}
}
@@ -0,0 +1,276 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Coursepicker extends FHCAPI_Controller
{
private $_ci;
const ALLOWED_COURSE_FILTER = ['uid', 'stg'];
public function __construct()
{
parent::__construct([
'getCourses' => 'lehre/lvplan:rw',
]);
$this->_ci = &get_instance();
$this->load->library('form_validation');
$this->_ci->load->model('education/lehreinheit_model', 'LehreinheitModel');
$this->_ci->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel');
$this->loadPhrases(['ui']);
}
public function getCourses()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$studiensemester_kurzbz = $this->_ci->input->post('studiensemester_kurzbz', TRUE);
$filter = $this->_checkFilter(self::ALLOWED_COURSE_FILTER);
$this->_getBasePlan($studiensemester_kurzbz);
$this->_ci->LehreinheitModel->db->group_start();
if (isset($filter->stg))
$this->_addStgWhere($filter->stg);
if (isset($filter->uid))
{
$uid_array = (array) $filter->uid;
$this->_ci->LehreinheitModel->db->or_where_in('tbl_benutzer.uid', $uid_array);
}
$this->_ci->LehreinheitModel->db->group_end();
$this->_ci->LehreinheitModel->addOrder('lehreinheit_id');
$result = $this->_ci->LehreinheitModel->load();
$result = hasData($result) ? getData($result) : array();
$this->terminateWithSuccess($this->_mapEvents($result));
}
private function _getBasePlan($studiensemester_kurzbz)
{
$this->_ci->LehreinheitModel->addSelect('
tbl_lehreinheit.lehreinheit_id,
tbl_lehreinheit.lvnr,
tbl_lehreinheit.lehrfach_id,
lehrfach.kurzbz AS lehrfach,
lehrfach.bezeichnung AS lehrfach_bez,
lehrfach.farbe AS lehrfach_farbe,
tbl_lehreinheit.lehrform_kurzbz AS lehrform,
lema.mitarbeiter_uid AS lektor_uid,
ma.kurzbz AS lektor,
tbl_person.vorname,
tbl_person.nachname,
tbl_studiengang.studiengang_kz,
upper(tbl_studiengang.typ::character varying::text || tbl_studiengang.kurzbz::text) AS studiengang,
lvb.semester,
lvb.verband,
lvb.gruppe,
lvb.gruppe_kurzbz,
tbl_lehreinheit.raumtyp,
tbl_lehreinheit.raumtypalternativ,
tbl_lehreinheit.stundenblockung,
tbl_lehreinheit.wochenrythmus,
lema.semesterstunden,
lema.planstunden,
tbl_lehreinheit.start_kw,
tbl_lehreinheit.anmerkung,
tbl_lehreinheit.studiensemester_kurzbz
');
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_lehreinheit.lehreinheit_id = lema.lehreinheit_id');
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitgruppe lvb', 'tbl_lehreinheit.lehreinheit_id = lvb.lehreinheit_id');
$this->_ci->LehreinheitModel->addJoin('public.tbl_studiengang', 'lvb.studiengang_kz = tbl_studiengang.studiengang_kz');
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id');
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung lehrfach', 'tbl_lehreinheit.lehrfach_id = lehrfach.lehrveranstaltung_id');
$this->_ci->LehreinheitModel->addJoin('public.tbl_mitarbeiter ma', 'lema.mitarbeiter_uid = ma.mitarbeiter_uid');
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrform', 'tbl_lehrform.lehrform_kurzbz = tbl_lehreinheit.lehrform_kurzbz');
$this->_ci->LehreinheitModel->addJoin('public.tbl_benutzer', 'ma.mitarbeiter_uid = tbl_benutzer.uid');
$this->_ci->LehreinheitModel->addJoin('public.tbl_person', 'tbl_benutzer.person_id = tbl_person.person_id');
$this->_ci->LehreinheitModel->db->group_start();
$this->_ci->LehreinheitModel->db->where('tbl_lehrform.verplanen', true);
$this->_ci->LehreinheitModel->db->where('tbl_lehreinheit.studiensemester_kurzbz', $studiensemester_kurzbz);
$this->_ci->LehreinheitModel->db->group_end();
}
private function _addStgWhere($studiengaenge)
{
$this->_ci->LehreinheitModel->db->group_start();
$first = true;
foreach ($studiengaenge as $studiengang)
{
if ($first)
$this->_ci->LehreinheitModel->db->group_start();
else
{
$this->_ci->LehreinheitModel->db->or_group_start();
}
$first = false;
$this->_ci->LehreinheitModel->db->where('tbl_lehrveranstaltung.studiengang_kz', $studiengang['stg_kz']);
if (isset($studiengang['semester']))
$this->_ci->LehreinheitModel->db->where('tbl_lehrveranstaltung.semester', $studiengang['semester']);
if (isset($studiengang['orgform_kurzbz']))
$this->_ci->LehreinheitModel->db->where('tbl_lehrveranstaltung.orgform_kurzbz', $studiengang['orgform_kurzbz']);
$this->_ci->LehreinheitModel->db->group_end();
}
$this->_ci->LehreinheitModel->db->group_end();
}
private function _mapEvents($result)
{
$lehreinheit_ids = array_values(array_unique(array_column($result, 'lehreinheit_id')));
$offen_map = array();
if (!empty($lehreinheit_ids))
{
$offen_result = $this->_ci->LehreinheitModel->getOffeneStunden($lehreinheit_ids);
if (hasData($offen_result))
{
foreach (getData($offen_result) as $row)
{
$offen_map[$row->lehreinheit_id . '_' . $row->mitarbeiter_uid] = $row;
}
}
}
$grouped = array();
foreach ($result as $row)
{
$lehreinheit_id = $row->lehreinheit_id;
if (!isset($grouped[$lehreinheit_id]))
{
$grouped[$lehreinheit_id] = (object)array(
'lehrfach_id' => $row->lehrfach_id,
'lehrfach_bez' => $row->lehrfach_bez,
'lehrfach_farbe' => $row->lehrfach_farbe,
'studiengang_kz' => $row->studiengang_kz,
'studiengang' => $row->studiengang,
'semester' => $row->semester,
'verband' => $row->verband,
'gruppe' => $row->gruppe,
'gruppe_kurzbz' => $row->gruppe_kurzbz,
'raumtyp' => $row->raumtyp,
'raumtypalternativ' => $row->raumtypalternativ,
'anmerkung' => $row->anmerkung,
'studiensemester_kurzbz' => $row->studiensemester_kurzbz,
'fachbereich_kurzbz' => isset($row->fachbereich_kurzbz) ? $row->fachbereich_kurzbz : null,
'lektoren' => array(),
'lehreinheit_id' => $lehreinheit_id,
'lvnr' => array(),
'lehrfach' => array(),
'lehrform' => array(),
'stundenblockung' => array(),
'wochenrythmus' => array(),
'planstunden' => array(),
'start_kw' => array(),
'verplant' => array(),
'offenestunden' => array(),
'lehrverband' => array(),
'lem' => array(),
'verplant_gesamt' => 0,
);
}
$group = $grouped[$lehreinheit_id];
$group->lektoren[$row->lektor_uid] = (object)array(
'uid' => $row->lektor_uid,
'kurzbz' => trim($row->lektor),
'name' => $row->vorname . ' ' . $row->nachname,
);
$group->lvnr[] = $row->lvnr;
$group->lehrfach[] = $row->lehrfach;
$group->lehrform[] = $row->lehrform;
$group->stundenblockung[] = $row->stundenblockung;
$group->wochenrythmus[] = $row->wochenrythmus;
$group->planstunden[] = $row->planstunden;
$group->start_kw[] = $row->start_kw;
$offen_key = $lehreinheit_id . '_' . $row->lektor_uid;
$offen = isset($offen_map[$offen_key]) ? $offen_map[$offen_key] : null;
$verplant_wert = $offen ? $offen->verplant : 0;
$offenestunden_wert = $offen ? $offen->offenestunden : 0;
$group->verplant[] = $verplant_wert;
$group->offenestunden[] = $offenestunden_wert;
$group->verplant_gesamt += $verplant_wert;
$lvb = $row->studiengang . '-' . $row->semester;
if ($row->verband != '' && $row->verband != ' ' && $row->verband != '0' && $row->verband != null)
$lvb .= $row->verband;
if ($row->gruppe != '' && $row->gruppe != ' ' && $row->gruppe != '0' && $row->gruppe != null)
$lvb .= $row->gruppe;
$group->lehrverband[] = ($row->gruppe_kurzbz != '' && $row->gruppe_kurzbz != null) ? $row->gruppe_kurzbz : $lvb;
$group->lem[] = array(
'lehreinheit_id' => $row->lehreinheit_id,
'mitarbeiter_uid' => $row->lektor_uid,
);
}
foreach ($grouped as $group)
{
$group->lektoren = array_values($group->lektoren);
$group->lehrverband = array_values(array_unique($group->lehrverband));
$group->lehrfach = $this->_formatArr($group->lehrfach);
$group->lehrform = $this->_formatArr($group->lehrform);
$group->stundenblockung = $this->_formatArr($group->stundenblockung);
$group->wochenrythmus = $this->_formatArr($group->wochenrythmus);
$group->planstunden = $this->_formatArr($group->planstunden);
$group->start_kw = $this->_formatArr($group->start_kw);
$group->verplant = $this->_formatArr($group->verplant);
$group->offenestunden = $this->_formatArr($group->offenestunden);
}
return array_values($grouped);
}
private function _formatArr($arr)
{
$values = array_values(array_unique($arr));
$formatted = implode(' ', $values);
if (count($values) > 1)
$formatted .= ' ?';
return $formatted;
}
private function _checkFilter($filters)
{
$filter_valid = false;
$filter_object = new stdClass();
foreach ($filters as $filter)
{
if ($this->_ci->input->post($filter))
{
$filter_valid = true;
$filter_object->$filter = $this->_ci->input->post($filter);
}
}
if (!$filter_valid)
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
return $filter_object;
}
}
@@ -7,8 +7,8 @@ class Favorites extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
'index' => self::PERM_LOGGED,
'set' => self::PERM_LOGGED
'index' => 'lehre/lvplan:rw',
'set' => 'lehre/lvplan:rw'
]);
// Load models
@@ -17,14 +17,14 @@ class Favorites extends FHCAPI_Controller
public function index()
{
$result = $this->VariableModel->getVariables(getAuthUID(), ['lv_favorites']);
$result = $this->VariableModel->getVariables(getAuthUID(), ['tempus_favorites']);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
$this->terminateWithSuccess(null);
else
$this->terminateWithSuccess(isset($data['lv_favorites']) ? $data['lv_favorites'] : null);
$this->terminateWithSuccess(isset($data['tempus_favorites']) ? $data['tempus_favorites'] : null);
}
public function set()
@@ -38,7 +38,7 @@ class Favorites extends FHCAPI_Controller
$favorites = $this->input->post('favorites');
$result = $this->VariableModel->setVariable(getAuthUID(), 'lv_favorites', $favorites);
$result = $this->VariableModel->setVariable(getAuthUID(), 'tempus_favorites', $favorites);
$this->getDataOrTerminateWithError($result);
@@ -0,0 +1,37 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Info extends FHCAPI_Controller
{
private $_ci;
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getStudiengaenge' => 'lehre/lvplan:rw',
]);
$this->_ci =& get_instance();
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->loadPhrases([
'ui'
]);
}
public function getStudiengaenge()
{
$this->_ci->StudiengangModel->addDistinct();
$this->_ci->StudiengangModel->addSelect('studiengang_kz');
$this->_ci->StudiengangModel->addSelect("CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name");
$result = $this->getDataOrTerminateWithError($this->_ci->StudiengangModel->load());
$this->terminateWithSuccess($result);
}
}
@@ -0,0 +1,514 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Kalender extends FHCAPI_Controller
{
private $_ci;
const ALLOWED_PLAN_FILTER = ['ort', 'uid', 'stg'];
const ALLOWED_ROOM_FILTER = ['lehreinheit_id', 'kalender_id'];
const ALLOWED_TO_UPDATE = ['start_time', 'end_time', 'orte'];
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getStunden' => 'lehre/lvplan:rw',
'getCalendarHours' => 'lehre/lvplan:rw',
'getPlan' => 'lehre/lvplan:rw',
'getPlanByOrt' => 'lehre/lvplan:rw',
'getRaumvorschlag' => 'lehre/lvplan:rw',
'getRaumvorschlagSlots' => 'lehre/lvplan:rw',
'getLehreinheiten' => 'lehre/lvplan:rw',
'getHistory' => 'lehre/lvplan:rw',
'deleteEntry' => 'lehre/lvplan:rw',
'syncToLecturer' => 'lehre/lvplan:rw',
'syncToStudent' => 'lehre/lvplan:rw',
'getPlanLecturer' =>'lehre/lvplan:rw',
'getPlanStudent' => 'lehre/lvplan:rw',
'getZeitwuensche' => 'lehre/lvplan:rw',
'getZeitsperren' => 'lehre/lvplan:rw',
'updateKalenderEvent' => 'lehre/lvplan:rw',
'deleteOrtEntry' => 'lehre/lvplan:rw',
'deleteFromKalenderEvent' => 'lehre/lvplan:rw',
'addKalenderEvent' => 'lehre/lvplan:rw',
'calculateMultiWeekPlan' => 'lehre/lvplan:rw',
'confirmMultiWeekPlan' => 'lehre/lvplan:rw',
'addToKalenderEvent' => 'lehre/lvplan:rw',
'sync' => 'lehre/lvplan:rw',
]);
$this->_ci =& get_instance();
$this->_ci->load->library('LogLib');
$this->_ci->load->library('form_validation');
$this->_ci->load->library('KalenderLib');
$this->_ci->load->library('KalenderSyncLib');
$this->_ci->load->library('RaumvorschlagLib');
$this->loadPhrases([
'ui'
]);
$this->_ci->load->config('tempus');
$this->_ci->loglib->setConfigs(array(
'classIndex' => 5,
'functionIndex' => 5,
'lineIndex' => 4,
'dbLogType' => 'API', // required
'dbExecuteUser' => 'RESTful API'
));
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* fetches Stunden layout from database
* @access public
*
*/
public function getStunden()
{
$this->load->model('ressource/Stunde_model', 'StundeModel');
$this->_ci->StundeModel->addOrder('stunde', 'ASC');
$stunden = $this->_ci->StundeModel->load();
$stunden = $this->getDataOrTerminateWithError($stunden);
$this->terminateWithSuccess($stunden);
}
public function getCalendarHours()
{
$calender_start = $this->_ci->config->item('calendar_start') ?? 7;
$calender_end = $this->_ci->config->item('calendar_end') ?? 23;
$this->terminateWithSuccess(array(
'start' => $calender_start,
'end' => $calender_end
));
}
public function getPlan()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$start_date = $this->_ci->input->post('start_date', TRUE);
$end_date = $this->_ci->input->post('end_date', TRUE);
$isCollisionCheckEnabled = $this->_ci->input->post('collisionCheck', TRUE) ?? false;
$maxDailyEventLimit = $this->_ci->input->post('maxDailyEventLimit', TRUE) ?? false;
$filter = $this->_checkFilter(self::ALLOWED_PLAN_FILTER);
$stundenplan_data = $this->_ci->kalenderlib->getPlanForPlanner(
$start_date,
$end_date,
isset($filter->ort) ? $filter->ort : null,
isset($filter->uid) ? $filter->uid : null,
isset($filter->stg) ? $filter->stg : null,
$isCollisionCheckEnabled,
$maxDailyEventLimit
);
$this->terminateWithSuccess($stundenplan_data);
}
public function getPlanStudent()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$start_date = $this->_ci->input->get('start_date', TRUE);
$end_date = $this->_ci->input->get('end_date', TRUE);
$stundenplan_data = $this->_ci->kalenderlib->getPlanForStudent(
$start_date,
$end_date
);
$this->terminateWithSuccess($stundenplan_data);
}
public function getPlanLecturer()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$start_date = $this->_ci->input->get('start_date', TRUE);
$end_date = $this->_ci->input->get('end_date', TRUE);
$stundenplan_data = $this->_ci->kalenderlib->getPlanForLecturer(
$start_date,
$end_date
);
$this->terminateWithSuccess($stundenplan_data);
}
public function getPlanByOrt($start_date = null, $end_date = null, $ort = null)
{
if (!isset($start_date) || !isset($end_date) || !isset($ort))
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
$this->_ci->form_validation->set_rules('ort',"ort","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$start_date = $this->_ci->input->get('start_date', TRUE);
$end_date = $this->_ci->input->get('end_date', TRUE);
$ort = $this->_ci->input->get('ort', TRUE);
}
$this->terminateWithSuccess($this->_ci->kalenderlib->getPlanByOrt($start_date, $end_date, $ort));
}
public function getZeitsperren()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
$this->_ci->form_validation->set_rules('emp',"emp","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$start_date = $this->_ci->input->get('start_date', TRUE);
$end_date = $this->_ci->input->get('end_date', TRUE);
$emp = $this->_ci->input->get('emp', TRUE);
$stundenplan_data = $this->_ci->kalenderlib->getZeitsperren($start_date, $end_date, $emp);
$this->terminateWithSuccess($stundenplan_data);
}
public function getZeitwuensche()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
$this->_ci->form_validation->set_rules('emp',"emp","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$start_date = $this->_ci->input->get('start_date', TRUE);
$end_date = $this->_ci->input->get('end_date', TRUE);
$emp = $this->_ci->input->get('emp', TRUE);
$stundenplan_data = $this->_ci->kalenderlib->getZeitwuensche($start_date, $end_date, $emp);
$this->terminateWithSuccess($stundenplan_data);
}
public function updateKalenderEvent()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('kalender_id',"kalender_id","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$updateFields = $this->_checkUpdate($this->_ci->input->post('updatedInfos', TRUE));
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
$result = $this->_ci->kalenderlib->updateKalenderEvent($kalender_id, $updateFields->orte ?? null, $updateFields->start_time ?? null, $updateFields->end_time ?? null, $updateFields->location ?? null);
if (isError($result))
$this->terminateWithError(getError($result), $result->code);
$this->terminateWithSuccess(getData($result));
}
public function deleteOrtEntry()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('kalender_id',"kalender_id","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
$result = $this->_ci->kalenderlib->updateOrt($kalender_id, []);
if (isError($result))
$this->terminateWithError(getError($result), $result->code);
$this->terminateWithSuccess(getData($result));
}
public function getRaumvorschlag()
{
$this->_ci->form_validation->set_data($_POST);
$filter = $this->_checkFilter(self::ALLOWED_ROOM_FILTER);
$this->terminateWithSuccess($this->_ci->raumvorschlaglib->getVorschlaege($filter->kalender_id));
}
public function getRaumvorschlagSlots()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('lehreinheit_id',"lehreinheit_id","required");
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$lehreinheit_id = $this->_ci->input->get('lehreinheit_id', TRUE);
$start_date = $this->_ci->input->get('start_date', TRUE);
$end_date = $this->_ci->input->get('end_date', TRUE);
$this->terminateWithSuccess(getData($this->_ci->raumvorschlaglib->getVorschlaegeSlots($lehreinheit_id, $start_date, $end_date)));
}
public function getLehreinheiten()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('kalender_id', "kalender_id", "required");
$kalender_id = $this->_ci->input->get('kalender_id', TRUE);
$result = $this->_ci->kalenderlib->getLehreinheiten($kalender_id);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function getHistory()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('kalender_id',"kalender_id","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$kalender_id = $this->_ci->input->get('kalender_id', TRUE);
$result = $this->_ci->kalenderlib->getHistory($kalender_id);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function deleteEntry()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('kalender_id', "kalender_id", "required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
$result = $this->_ci->kalenderlib->deleteEntry($kalender_id);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function sync()
{
$result = $this->_ci->kalendersynclib->sync();
$this->terminateWithSuccess(getData($result));
}
public function syncToLecturer()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('kalender_id', "kalender_id", "required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
$result = $this->_ci->kalenderlib->updateStatus($kalender_id, 'sync_preview');
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function syncToStudent()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('kalender_id', "kalender_id", "required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
$result = $this->_ci->kalenderlib->updateStatus($kalender_id, 'sync_live');
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function addKalenderEvent()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('lehreinheit_id',"lehreinheit_id","required");
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$lehreinheit_id = $this->_ci->input->post('lehreinheit_id', TRUE);
$ort_kurzbz = $this->_ci->input->post('ort_kurzbz', TRUE);
$start_date = $this->_ci->input->post('start_date', TRUE);
$end_date = $this->_ci->input->post('end_date', TRUE);
$result = $this->_ci->kalenderlib->addKalenderEvent($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function calculateMultiWeekPlan()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('lehreinheit_id',"lehreinheit_id","required");
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$lehreinheit_id = $this->_ci->input->post('lehreinheit_id', TRUE);
$ort_kurzbz = $this->_ci->input->post('ort_kurzbz', TRUE);
$start_date = $this->_ci->input->post('start_date', TRUE);
$end_date = $this->_ci->input->post('end_date', TRUE);
$result = $this->_ci->kalenderlib->calculateMultiWeekPlan($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function confirmMultiWeekPlan()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('plan[]',"plan","required");
$this->_ci->form_validation->set_rules('lehreinheit_id',"lehreinheit_id","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$plan = $this->_ci->input->post('plan', TRUE);
$lehreinheit_id = $this->_ci->input->post('lehreinheit_id', TRUE);
$result = $this->_ci->kalenderlib->confirmMultiWeekPlan($plan, $lehreinheit_id);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function addToKalenderEvent()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('target_kalender_id',"target_kalender_id","required");
$this->_ci->form_validation->set_rules('lehreinheit_id',"lehreinheit_id","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$target_kalender_id = $this->_ci->input->post('target_kalender_id', TRUE);
$lehreinheit_id = $this->_ci->input->post('lehreinheit_id', TRUE);
$result = $this->_ci->kalenderlib->addToKalenderEvent($target_kalender_id, $lehreinheit_id);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
public function deleteFromKalenderEvent()
{
$this->_ci->form_validation->set_data($_POST);
$this->_ci->form_validation->set_rules('kalender_id',"kalender_id","required");
$this->_ci->form_validation->set_rules('lehreinheit_ids[]',"lehreinheit_ids","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
$lehreinheit_ids = $this->_ci->input->post('lehreinheit_ids', TRUE);
$result = $this->_ci->kalenderlib->deleteFromKalenderEvent($kalender_id, $lehreinheit_ids);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(getData($result));
}
private function _checkFilter($filters)
{
$filter_valid = true;
$filter_object = new stdClass();
foreach ($filters as $filter)
{
if ($this->_ci->input->post($filter))
{
$filter_valid = true;
$filter_object->$filter = $this->_ci->input->post($filter);
}
}
if (!$filter_valid)
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
return $filter_object;
}
private function _checkUpdate($updateInfos)
{
$update_valid = false;
$update_object = new stdClass();
foreach (self::ALLOWED_TO_UPDATE as $filter)
{
if (isset($updateInfos[$filter]))
{
$update_valid = true;
$update_object->$filter = $updateInfos[$filter];
}
}
if (!$update_valid)
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
return $update_object;
}
}
@@ -0,0 +1,304 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class KalenderSync extends FHCAPI_Controller
{
private $_ci;
const ALLOWED_STATUS = ['preview', 'live'];
public function __construct()
{
parent::__construct([
'getSyncs' => ['admin:r', 'assistenz:r'],
'loadSync' => ['admin:r', 'assistenz:r'],
'add' => ['admin:r', 'assistenz:r'],
'start' => ['admin:r', 'assistenz:r'],
'delete' => ['admin:r', 'assistenz:r'],
'updateSync' => ['admin:r', 'assistenz:r'],
'getStudienplan' => ['admin:r', 'assistenz:r'],
'getSyncStatus' => ['admin:r', 'assistenz:r'],
]);
$this->loadPhrases([
'lehre',
]);
$this->_ci = &get_instance();
$this->_ci->load->library('form_validation');
$this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel');
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->load->model('ressource/Kalendersyncstatus_model', 'KalendersyncstatusModel');
$this->_ci->load->model('ressource/Kalenderstatus_model', 'KalenderStatusModel');
$this->_ci->load->library('KalenderSyncLib');
}
public function getSyncs()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$studiensemester_kurzbz = $this->_ci->input->get('studiensemester_kurzbz', TRUE);
$language = getUserLanguage() == 'German' ? 0 : 1;
$this->_ci->KalenderStatusModel->addSelect('tbl_kalender_syncstatus.*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS sync_status, tbl_organisationseinheit.bezeichnung as oebezeichnung, tbl_studienplan.bezeichnung as studienplanbezeichnung');
$this->_ci->KalenderStatusModel->addJoin('lehre.tbl_kalender_status', 'tbl_kalender_syncstatus.sync_status_kurzbz = tbl_kalender_status.status_kurzbz');
$this->_ci->KalenderStatusModel->addJoin('public.tbl_organisationseinheit', 'tbl_kalender_syncstatus.oe_kurzbz = tbl_organisationseinheit.oe_kurzbz');
$this->_ci->KalenderStatusModel->addJoin('lehre.tbl_studienplan', 'tbl_kalender_syncstatus.studienplan_id = tbl_studienplan.studienplan_id', 'LEFT');
$this->_ci->KalenderStatusModel->addJoin('public.tbl_studiensemester', 'tbl_kalender_syncstatus.studiensemester_kurzbz = tbl_studiensemester.studiensemester_kurzbz');
$this->_ci->KalenderStatusModel->addOrder('public.tbl_studiensemester.start', 'DESC');
if ($studiensemester_kurzbz === 'all')
$data = $this->_ci->KalendersyncstatusModel->load();
else
$data = $this->_ci->KalendersyncstatusModel->loadWhere(array('tbl_kalender_syncstatus.studiensemester_kurzbz' => $studiensemester_kurzbz));
if (isError($data))
$this->terminateWithError(getError($data));
$this->terminateWithSuccess(getData($data));
}
public function delete()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('kalender_syncstatus_id', 'kalender_syncstatus_id', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$kalender_syncstatus_id = $this->input->post('kalender_syncstatus_id');
$result = $this->_ci->KalendersyncstatusModel->load($kalender_syncstatus_id);
if (isError($result))
$this->terminateWithError(getError($result));
if (!hasData($result))
$this->terminateWithError($this->p->t('lehre', 'errorDeleting'));
$del_result = $this->_ci->KalendersyncstatusModel->delete(getData($result)[0]->kalender_syncstatus_id);
if (isError($del_result))
$this->terminateWithError(getError($del_result));
$this->terminateWithSuccess($del_result);
}
public function loadSync()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('kalender_syncstatus_id',"kalender_syncstatus_id","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$kalender_syncstatus_id = $this->_ci->input->get('kalender_syncstatus_id', TRUE);
$data = $this->_ci->KalendersyncstatusModel->loadWhere(array('kalender_syncstatus_id' => $kalender_syncstatus_id));
if (isError($data))
$this->terminateWithError(getError($data));
$this->terminateWithSuccess(getData($data)[0]);
}
public function getSyncStatus()
{
$language = getUserLanguage() == 'German' ? 0 : 1;
$this->_ci->KalenderStatusModel->addSelect('*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS bezeichnung, status_kurzbz');
$this->_ci->KalenderStatusModel->db->where_in('status_kurzbz', self::ALLOWED_STATUS);
$data = $this->_ci->KalenderStatusModel->load();
if (isError($data))
$this->terminateWithError(getError($data));
$this->terminateWithSuccess(getData($data));
}
public function add()
{
$formData = $this->input->post('formData');
$this->_ci->form_validation->set_data($formData);
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
$this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$ausbildungssemester = isEmptyString($formData['ausbildungssemester']) ? null : $formData['ausbildungssemester'];
$studienplan_id = isEmptyString($formData['studienplan_id']) ? null : $formData['studienplan_id'];
$existing = $this->_checkIfExist(
$formData['oe_kurzbz'],
$formData['studiensemester_kurzbz'],
$ausbildungssemester,
$studienplan_id
);
if (isError($existing))
$this->terminateWithError(getError($existing));
if (hasData($existing))
{
$this->terminateWithError('Es existiert bereits ein Eintrag.');
}
$result = $this->_ci->KalendersyncstatusModel->insert(
array(
'oe_kurzbz' => $formData['oe_kurzbz'],
'studiensemester_kurzbz' => $formData['studiensemester_kurzbz'],
'datum_bis' => $formData['datum_bis'],
'studienplan_id' => $studienplan_id,
'ausbildungssemester' => $ausbildungssemester,
'sync_status_kurzbz' => $formData['sync_status_kurzbz'],
'mail' => $formData['mail'],
'insertvon' => getAuthUID()
)
);
$this->terminateWithSuccess($result);
}
public function start()
{
$formData = $this->input->post('formData');
$this->_ci->form_validation->set_data($formData);
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
$this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$result = $this->_ci->kalendersynclib->runManual($formData['oe_kurzbz'], $formData['studiensemester_kurzbz'], $formData['ausbildungssemester'], $formData['studienplan_id'], $formData['mail'], $formData['datum_bis'], $formData['sync_status_kurzbz']);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess($result);
}
public function updateSync()
{
$formData = $this->input->post('formData');
$this->_ci->form_validation->set_data($formData);
$this->_ci->form_validation->set_rules('kalender_syncstatus_id',"kalender_syncstatus_id","required");
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
$this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$ausbildungssemester = isEmptyString($formData['ausbildungssemester']) ? null : $formData['ausbildungssemester'];
$studienplan_id = isEmptyString($formData['studienplan_id']) ? null : $formData['studienplan_id'];
$existing = $this->_checkIfExist(
$formData['oe_kurzbz'],
$formData['studiensemester_kurzbz'],
$ausbildungssemester,
$studienplan_id,
$formData['kalender_syncstatus_id']
);
if (isError($existing))
$this->terminateWithError(getError($existing));
if (hasData($existing))
{
$this->terminateWithError('Es existiert bereits ein Eintrag.');
}
$this->_ci->KalendersyncstatusModel->update(
array('kalender_syncstatus_id' => $formData['kalender_syncstatus_id']),
array(
'oe_kurzbz' => $formData['oe_kurzbz'],
'studiensemester_kurzbz' => $formData['studiensemester_kurzbz'],
'datum_bis' => $formData['datum_bis'],
'studienplan_id' => $studienplan_id,
'ausbildungssemester' => $ausbildungssemester,
'sync_status_kurzbz' => $formData['sync_status_kurzbz'],
'mail' => $formData['mail'],
'updatevon' => getAuthUID(),
'updateamum' => date('c'),
)
);
}
public function getStudienplan()
{
$this->_ci->form_validation->set_data($_GET);
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$oe_kurzbz = $this->_ci->input->get('oe_kurzbz', TRUE);
$studiensemester_kurzbz = $this->_ci->input->get('studiensemester_kurzbz', TRUE);
$ausbildungssemester = $this->_ci->input->get('ausbildungssemester', TRUE);
$this->_ci->StudiengangModel->addJoin('tbl_organisationseinheit', 'oe_kurzbz');
$is_studiengang = $this->_ci->StudiengangModel->loadWhere(array('oe_kurzbz' => $oe_kurzbz));
if (hasData($is_studiengang) && !isEmptyString($studiensemester_kurzbz))
{
$studiengang = getData($is_studiengang)[0];
$studienplaene = $this->_ci->StudienplanModel->getStudienplaeneBySemester(
$studiengang->studiengang_kz,
$studiensemester_kurzbz,
isEmptyString($ausbildungssemester) ? null : $ausbildungssemester
);
$data = $this->getDataOrTerminateWithError($studienplaene);
$unique = array();
foreach ($data as $row)
{
$unique[$row->studienplan_id] = (object) array(
'studienplan_id' => $row->studienplan_id,
'studienordnung_id' => $row->studienordnung_id,
'bezeichnung' => $row->bezeichnung,
'orgform_kurzbz' => $row->orgform_kurzbz
);
}
$this->terminateWithSuccess(array_values($unique));
}
$this->terminateWithSuccess();
}
private function _checkIfExist($oe_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $studienplan_id, $kalender_syncstatus_id = null)
{
$this->_ci->KalendersyncstatusModel->db->where('oe_kurzbz', $oe_kurzbz);
$this->_ci->KalendersyncstatusModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
if (is_null($ausbildungssemester))
$this->_ci->KalendersyncstatusModel->db->where('ausbildungssemester IS NULL', null, false);
else
$this->_ci->KalendersyncstatusModel->db->where('ausbildungssemester', $ausbildungssemester);
if (is_null($studienplan_id))
$this->_ci->KalendersyncstatusModel->db->where('studienplan_id IS NULL', null, false);
else
$this->_ci->KalendersyncstatusModel->db->where('studienplan_id', $studienplan_id);
if (!is_null($kalender_syncstatus_id))
$this->_ci->KalendersyncstatusModel->db->where('kalender_syncstatus_id !=', $kalender_syncstatus_id);
return $this->_ci->KalendersyncstatusModel->load();
}
}
@@ -0,0 +1,84 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class OperationalResourceToCalenderAPI extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getAssignedResourcesByCalender' => ['admin:r', 'assistenz:r', 'lehre/lvplan:rw'],
'storeResourcesToCalendarRelationship' => ['admin:w', 'assistenz:w', 'lehre/lvplan:rw'],
'getSchedulableResourcesByCalendar' => ['admin:r', 'assistenz:r', 'lehre/lvplan:rw'],
]);
$this->load->model('ressource/BetriebsmittelKalender_model', 'BetriebsmittelKalenderModel');
$this->load->model('ressource/Betriebsmittel_model', 'BetriebsmittelModel');
$this->load->model('ressource/Kalender_model', 'KalenderModel');
$this->load->library('CollisionChecker');
$this->load->library('KalenderLib');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getSchedulableResourcesByCalendar($calenderID)
{
if (!isset($calenderID)) $this->terminateWithError("Missing required parameter 'kalender_id'");
$result = $this->KalenderModel->loadWhere(['kalender_id' => $calenderID]);
if (isError($result)) $this->terminateWithError("Calendar with id '$calenderID' does not have a valid group id");
$calender = $this->getDataOrTerminateWithError($result)[0];
if (!isset($calender)) $this->terminateWithError("Calendar with id '$calenderID' not found");
$result = $this->BetriebsmittelModel->getSchedulableEntriesByDatetimeInterval($calender->von, $calender->bis);
$this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
}
public function getAssignedResourcesByCalender($calenderID)
{
if (!isset($calenderID)) $this->terminateWithError("Missing required parameter 'kalender_id'");
$result = $this->KalenderModel->loadWhere(['kalender_id' => $calenderID]);
if (empty($result)) $this->terminateWithError("Calendar with id '$calenderID' not found");
$calenderGroupID = $this->getDataOrTerminateWithError($result)[0]->eindeutige_kalender_gruppen_id;
if (!isset($calenderGroupID)) $this->terminateWithError("Calendar with id '$calenderID' does not have a valid group id");
$this->BetriebsmittelKalenderModel->addSelect(['tbl_betriebsmittel_kalender.*', 'tbl_betriebsmittel.beschreibung', 'tbl_betriebsmittel.verplanen']);
$this->BetriebsmittelKalenderModel->addJoin('wawi.tbl_betriebsmittel', 'betriebsmittel_id');
$result = $this->BetriebsmittelKalenderModel->loadWhere([
'eindeutige_kalender_gruppen_id' => $calenderGroupID,
'tbl_betriebsmittel.verplanen' => true,
]);
$this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
}
public function storeResourcesToCalendarRelationship()
{
$calenderID = $this->input->post('kalender_id');
$assignedResources = $this->input->post('assignedResources');
if (!isset($calenderID)) $this->terminateWithError("Missing required parameter 'kalender_id'", 'general');
if (!isset($assignedResources)) $this->terminateWithError("Missing required parameter 'assignedResources'", 'general');
$result = $this->KalenderModel->loadWhere(['kalender_id' => $calenderID]);
if (empty($result)) $this->terminateWithError("Calendar with id '$calenderID' not found");
$calendar = $this->getDataOrTerminateWithError($result)[0];
$calenderGroupID = $calendar->eindeutige_kalender_gruppen_id;
if (!isset($calenderGroupID)) $this->terminateWithError("Calendar with id '$calenderID' does not have a valid group id");
$result = $this->kalenderlib->addOperationalResourcesToKalenderEvent($calendar, $assignedResources);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess(['message' => 'Resources assigned successfully']);
}
}
@@ -0,0 +1,233 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Reservierung extends FHCAPI_Controller
{
private $_ci;
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'addReservierung' => 'lehre/lvplan:rw',
'getRollen' => 'lehre/lvplan:rw',
'getInformation' => 'lehre/lvplan:rw',
'getLektor' => 'lehre/lvplan:rw',
'searchGroup' => 'lehre/lvplan:rw',
]);
$this->_ci =& get_instance();
$this->_ci->load->library('LogLib');
$this->_ci->load->library('form_validation');
$this->_ci->load->library('KalenderLib');
$this->_ci->load->model('ressource/Ort_model', 'OrtModel');
$this->_ci->load->model('ressource/Kalender_Event_Rolle_model', 'KalenderEventRolleModel');
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->_ci->load->model('organisation/gruppe_model', 'GruppeModel');
$this->loadPhrases([
'ui'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getInformation()
{
$return_array = array('berechtigt' => false, 'studiengaenge' => []);
$this->_ci->OrtModel->db->join("
(select ort,standort_id,strasse, plz
FROM public.tbl_standort
LEFT JOIN public.tbl_adresse USING(adresse_id)
) standort", "standort_id", "LEFT", false);
$raeume = $this->_ci->OrtModel->loadWhere(array('aktiv' => true, 'reservieren' => true));
$return_array['raeume'] = hasData($raeume) ? getData($raeume) : [];
if (!$this->_ci->permissionlib->isBerechtigt('lehre/reservierung'))
$this->terminateWithSuccess($return_array);
$stg_berechtigungen = $this->_ci->permissionlib->getSTG_isEntitledFor('lehre/reservierung');
if (isEmptyArray($stg_berechtigungen))
$this->terminateWithSuccess($return_array);
$this->_ci->StudiengangModel->addSelect('studiengang_kz, UPPER(CONCAT(typ, kurzbz)) as kuerzel, kurzbzlang');
$this->_ci->StudiengangModel->addOrder('typ, kurzbz');
$this->_ci->StudiengangModel->db->where_in('studiengang_kz', $stg_berechtigungen);
$studiengaenge = $this->_ci->StudiengangModel->loadWhere(array('aktiv' => true));
if (isError($studiengaenge))
$this->terminateWithError(getError($studiengaenge));
$language = getUserLanguage() == 'German' ? 0 : 1;
$this->_ci->KalenderEventRolleModel->addOrder('sort');
$this->_ci->KalenderEventRolleModel->addSelect('rolle_kurzbz, array_to_json(bezeichnung_mehrsprachig::varchar[])->>'. $language. ' as bezeichnung');
$rollen = $this->_ci->KalenderEventRolleModel->load();
$this->_ci->StudiensemesterModel->addOrder('start', 'DESC');
$studiensemester = $this->_ci->StudiensemesterModel->load();
$return_array['studiengaenge'] = hasData($studiengaenge) ? getData($studiengaenge) : [];
$return_array['berechtigt'] = true;
$return_array['rollen'] = hasData($rollen) ? getData($rollen) : [];
$return_array['studiensemester'] = hasData($studiensemester) ? getData($studiensemester) : [];
$this->terminateWithSuccess($return_array);
}
public function getRaeume()
{
$this->_ci->OrtModel->db->join("
(select ort,standort_id,strasse, plz
FROM public.tbl_standort
LEFT JOIN public.tbl_adresse USING(adresse_id)
) standort", "standort_id", "LEFT", false);
$result = $this->_ci->OrtModel->loadWhere(array('aktiv' => true, 'reservieren' => true));
$this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function searchGroup()
{
$query = $this->input->get('query');
if (is_null($query))
$this->terminateWithError($this->_ci->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$stg_berechtigungen = $this->_ci->permissionlib->getSTG_isEntitledFor('lehre/reservierung');
if (isEmptyArray($stg_berechtigungen))
$this->terminateWithSuccess([]);
$query_words = explode(' ', urldecode($query));
$gruppen_result = $this->_ci->GruppeModel->search($query_words);
if (isError($gruppen_result))
$this->terminateWithError(getError($gruppen_result), self::ERROR_TYPE_GENERAL);
$gruppen_array = array();
if (hasData($gruppen_result))
$gruppen_array = getData($gruppen_result);
$lehrverband_result = $this->_ci->LehrverbandModel->search($query_words);
$lehrverband_array = array();
if (isError($lehrverband_result))
$this->terminateWithError(getError($lehrverband_result), self::ERROR_TYPE_GENERAL);
if (hasData($lehrverband_result))
$lehrverband_array = getData($lehrverband_result);
$all_gruppen = array_merge($gruppen_array, $lehrverband_array);
$gefilterte_gruppen = array_filter($all_gruppen, function($gruppe) use ($stg_berechtigungen)
{
return in_array($gruppe->studiengang_kz, $stg_berechtigungen);
});
$this->terminateWithSuccess($gefilterte_gruppen);
}
public function getRollen()
{
$language = getUserLanguage() == 'German' ? 0 : 1;
$this->_ci->KalenderEventRolleModel->addOrder('sort');
$this->_ci->KalenderEventRolleModel->addSelect('rolle_kurzbz, array_to_json(bezeichnung_mehrsprachig::varchar[])->>'. $language. ' as bezeichnung');
$result = $this->_ci->KalenderEventRolleModel->load();
$this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function addReservierung()
{
$this->_ci->form_validation->set_rules('titel', "titel", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
$this->_ci->form_validation->set_rules('beschreibung', "beschreibung", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
$this->_ci->form_validation->set_rules('start_date', "start_date", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
$this->_ci->form_validation->set_rules('end_date', "end_date", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
if ($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
$orte = $this->_ci->input->post('orte', TRUE);
if (empty($orte) || (empty($orte['ort_kurzbz']) && empty($orte['location'])))
{
$this->terminateWithValidationErrors(['ort_kurzbz' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Raum'])]);
}
$titel = $this->_ci->input->post('titel', TRUE);
$beschreibung = $this->_ci->input->post('beschreibung', TRUE);
$start_date = $this->_ci->input->post('start_date', TRUE);
$end_date = $this->_ci->input->post('end_date', TRUE);
$teilnehmer = $this->_ci->input->post('teilnehmer', TRUE);
$specialGroups = $this->_ci->input->post('specialGroups', TRUE);
$specialFinalGroups = $this->_ci->input->post('specialFinalGroups', TRUE);
$groups = $this->_ci->input->post('groups', TRUE);
if ($this->_ci->permissionlib->isBerechtigt('lehre/reservierung'))
{
if (empty($teilnehmer) || !is_array($teilnehmer))
{
$teilnehmer[] = array('uid' => getAuthUID(), 'rolle' => 'organisator');
}
}
else
$teilnehmer[] = array('uid' => getAuthUID(), 'rolle' => 'organisator');
$result = $this->_ci->kalenderlib->addReservierung($titel, $beschreibung, $orte, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups);
if (isError($result))
$this->terminateWithError(getError($result));
$this->terminateWithSuccess($result);
}
public function getLektor()
{
$query = $this->input->get('query');
if (is_null($query))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$query_words = explode(' ', $query);
$this->_ci->MitarbeiterModel->addSelect('uid, person_id, vorname, nachname');
$this->_ci->MitarbeiterModel->addJoin('public.tbl_benutzer', 'uid = mitarbeiter_uid');
$this->_ci->MitarbeiterModel->addJoin('public.tbl_person', 'person_id');
$this->_ci->MitarbeiterModel->db->where('public.tbl_benutzer.aktiv', true);
$this->_ci->MitarbeiterModel->db->group_start();
foreach ($query_words as $word)
{
$this->_ci->MitarbeiterModel->db->group_start();
$this->_ci->MitarbeiterModel->db->where('tbl_person.vorname ILIKE', "%" . $word . "%");
$this->_ci->MitarbeiterModel->db->or_where('tbl_person.nachname ILIKE', "%" . $word . "%");
$this->_ci->MitarbeiterModel->db->or_where('uid ILIKE', "%" . $word . "%");
$this->_ci->MitarbeiterModel->db->group_end();
}
$this->_ci->MitarbeiterModel->db->group_end();
$this->_ci->MitarbeiterModel->addOrder('nachname');
$this->_ci->MitarbeiterModel->addOrder('vorname');
$result = $this->_ci->MitarbeiterModel->load();
$this->terminateWithSuccess(hasData($result) ? getData($result) : array());
}
}
@@ -0,0 +1,53 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Tags extends Tag_Controller
{
const BERECHTIGUNG_KURZBZ = ['admin:rw', 'assistenz:rw'];
public function __construct()
{
parent::__construct([
'getTag' => self::BERECHTIGUNG_KURZBZ,
'getTags' => self::BERECHTIGUNG_KURZBZ,
'getTagsByCalendar' => self::BERECHTIGUNG_KURZBZ,
'addTag' => self::BERECHTIGUNG_KURZBZ,
'updateTag' => self::BERECHTIGUNG_KURZBZ,
'doneTag' => self::BERECHTIGUNG_KURZBZ,
'deleteTag' => self::BERECHTIGUNG_KURZBZ
]);
$this->config->load('tempus');
}
public function getTag($readonly_tags = null)
{
parent::getTag($this->config->item('tempus_tags'));
}
public function getTags($tags = null)
{
parent::getTags($this->config->item('tempus_tags'));
}
public function getTagsByCalendar($eindeutige_kalender_gruppen_id = null)
{
parent::getTagsByAssignmentTypeValue('eindeutige_kalender_gruppen_id', $eindeutige_kalender_gruppen_id, $this->config->item('tempus_tags'));
}
public function addTag($withZuordnung = true, $updatable_tags = null)
{
parent::addTag(true, $this->config->item('tempus_tags'));
}
public function updateTag($updatable_tags = null)
{
parent::updateTag($this->config->item('tempus_tags'));
}
public function deleteTag($withZuordnung = true, $updatable_tags = null)
{
parent::deleteTag(true, $this->config->item('tempus_tags'));
}
public function doneTag($updatable_tags = null)
{
parent::doneTag($this->config->item('tempus_tags'));
}
}
@@ -37,6 +37,7 @@ class Tag extends API_Controller
if (isset($tag))
{
$this->TagModel->addJoin('public.tbl_notiz_typ', 'typ_kurzbz', 'typ_kurzbz');
$result = $this->TagModel->load($tag);
$this->response($result, REST_Controller::HTTP_OK);
@@ -14,11 +14,11 @@ class Mylv extends Auth_Controller
public function __construct()
{
parent::__construct([
'Student' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
'Studiensemester' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
'Lvs' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
'Info' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
'Pruefungen' => ['student/anrechnung_beantragen:r','user:r'] // TODO(chris): permissions?
'Student' => self::PERM_LOGGED,
'Studiensemester' => self::PERM_LOGGED,
'Lvs' => self::PERM_LOGGED,
'Info' => self::PERM_LOGGED,
'Pruefungen' => self::PERM_LOGGED
]);
}
@@ -1,78 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Studiensemester extends Auth_Controller
{
public function __construct()
{
// TODO(chris): access!
parent::__construct([
'index' => self::PERM_LOGGED,
'now' => self::PERM_LOGGED,
'set' => self::PERM_LOGGED
]);
}
public function index()
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->StudiensemesterModel->addOrder('start');
$result = $this->StudiensemesterModel->load();
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
}
$this->outputJson($result);
}
public function now()
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->StudiensemesterModel->getNearest();
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
$this->outputJson(getError($result));
}
$result = getData($result) ?: [];
if (count($result) != 1) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
$this->outputJsonError(count($result) ? 'Mehrere Studiensemester aktiv' : 'Kein Studiensemester aktiv');
} else {
$this->outputJsonSuccess(current($result)->studiensemester_kurzbz);
}
}
public function set()
{
$this->load->library('AuthLib');
$this->load->library('form_validation');
$_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
$this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
if ($this->form_validation->run() == false) {
$this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
return $this->outputJsonError($this->form_validation->error_array());
}
$stdsem = $this->input->post('studiensemester');
$this->load->model('system/Variable_model', 'VariableModel');
$result = $this->VariableModel->setVariable(getAuthUID(), 'semester_aktuell', $stdsem);
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
return $this->outputJson($result);
}
$this->outputJsonSuccess(true);
}
}
+1 -1
View File
@@ -125,7 +125,7 @@ class AntragJob extends JOB_Controller
$stgLeitungen[$leitung->uid]['stgs'][] = $antrag->studiengang_kz;
}
$result = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
$result = $this->StudierendenantragModel->getStgAndDetails($antrag->studierendenantrag_id);
if (isError($result))
{
$this->logError(getError($result));
+110
View File
@@ -0,0 +1,110 @@
<?php
if (!defined("BASEPATH")) exit("No direct script access allowed");
use \DateTime as DateTime;
class TagJob extends JOB_Controller
{
/**
* API constructor
*/
public function __construct()
{
parent::__construct();
// Configs
$this->load->config('stv');
// Library
$this->load->library('TagLib');
// Load Models
$this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->load->model('system/Notiztyp_model', 'NotiztypModel');
$this->loadPhrases([
'lehre'
]);
}
public function rebuildAutomatedTags()
{
$automatedTagsRes = $this->NotiztypModel->loadWhere(array('automatisiert' => true, 'taglib IS NOT NULL' => null));
$automatedTags = hasData($automatedTagsRes) ? getData($automatedTagsRes) : [];
$result = $this->StudiensemesterModel->getAktOrNextSemester();
if (isError($result))
{
$this->logInfo('Start Job rebuild Automated Tags');
$this->logError('Error occurred during retrieving studiensemester');
return $this->logInfo('End Job rebuild Automated Tags');
}
if (empty($result->retval) || !isset($result->retval[0])) {
$this->logInfo('Start Job rebuild Automated Tags');
$this->logError('No Studiensemester found');
return $this->logInfo('End Job rebuild Automated Tags');
}
$studiensemester_kurzbz = $result->retval[0]->studiensemester_kurzbz ?? null;
$params = array(
'studiensemester_kurzbz' => $studiensemester_kurzbz
);
$this->logInfo('Start Job rebuild Automated Tags ' . $studiensemester_kurzbz);
foreach($automatedTags as $autoTag)
{
// getPath: must not be lost
$filePath = APPPATH . 'libraries/' . $autoTag->taglib . '.php'; // APPPATH = application/
if(file_exists($filePath)) {
require_once($filePath);
} else {
$this->logInfo("File not found: " . $filePath);
continue;
}
$kurz_bz = $autoTag->typ_kurzbz;
// className without PATH (basename)
$className = basename($autoTag->taglib);
$obj = new $className();
$outputArray = $obj->getZuordnungIds($params);
$typeId = $outputArray->typeId;
$paramsTag = array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'kurzbz' => $kurz_bz,
'data' => $outputArray->data,
'typeId' => $typeId
);
$result = $this->taglib->updateAutomatedTags($paramsTag);
if (isError($result)) {
$this->logError('Error occurred during updateAutomatedTags ' . $kurz_bz);
continue;
}
$data = is_array($result) ? $result['retval'] : $result->retval;
//SUMMARY
$this->logInfo("Tag " . $result->retval['input']['tag'] . " | type_id " . $typeId . " --"
. " Count Recycled: " . $result->retval['summary']['recycled']
. " Count Added: ". $result->retval['summary']['added']
. " Count Deleted: ". $result->retval['summary']['deleted']);
//DETAILS
if($result->retval['results']['newTags'])
$this->logInfo("Tag " . $result->retval['input']['tag'] . "New tag(s): " . implode(', ', $result->retval['results']['newTags']));
if($result->retval['results']['deletedTagsIds'])
$this->logInfo("Tag " . $result->retval['input']['tag'] . "Deleted tags(s: " . implode(', ', $result->retval['results']['deletedTagsIds']));
if ($result->retval['results']['retaggedIds'])
$this->logInfo("Tag " . $result->retval['input']['tag'] . "Recycled tag(s): " . implode(', ', $result->retval['results']['retaggedIds']));
}
$this->logInfo( "End Job rebuild Automated Tags");
}
}
@@ -0,0 +1,27 @@
<?php
if (!defined("BASEPATH")) exit("No direct script access allowed");
class TempusJob extends JOB_Controller
{
private $_ci;
public function __construct()
{
parent::__construct();
$this->_ci =& get_instance();
$this->_ci->load->helper('hlp_sancho_helper');
$this->_ci->load->library('KalenderLib');
}
public function sync()
{
$this->_ci->logInfo('Start job FHC-Core->Tempus->sync');
$this->_ci->kalenderlib->sync();
$this->_ci->logInfo('End job FHC-Core->Tempus->sync');
}
}
@@ -0,0 +1,60 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller generates javascript from snippets for tabulator columns
*/
class Tabulatorcolumns extends Auth_Controller
{
public function __construct()
{
parent::__construct([
'stv' => ['admin:r', 'assistenz:r'],
'lvverwaltung' => ['admin:r', 'assistenz:r']
]);
}
/**
* Render tabulator columns for config
*
* @param string $config
*
* @return void
*/
public function _remap($config)
{
$this->load->config($config);
$list_columns = $this->config->item('list_columns') ?: [];
$snippets = [
'jssnippets/tabulatorcolumns/' . $config . '.js'
];
foreach ($list_columns as $col) {
$snippets[] = $col['js'];
}
$this->output->set_content_type('application/javascript');
$this->load->view('jssnippets/tabulatorcolumns.js', [
'snippets' => $snippets
]);
}
}
@@ -25,7 +25,8 @@ class Studierendenantrag extends FHC_Controller
// Load language phrases
$this->loadPhrases([
'studierendenantrag'
'studierendenantrag',
'ui'
]);
$this->load->config('studierendenantrag');
+15 -3
View File
@@ -198,7 +198,19 @@ class Gradelist extends Auth_Controller
if (!isset($row_noten->found))
{
$result_lv = $this->LehrveranstaltungModel->load($row_noten->lehrveranstaltung_id);
$result_stg = $this->StudiengangModel->load($result_lv->retval[0]->studiengang_kz);
$studiengang_kz = null;
if (!empty($result_lv->retval) && isset($result_lv->retval[0]) && isset($result_lv->retval[0]->studiengang_kz))
{
$result_stg = $this->StudiengangModel->load($result_lv->retval[0]->studiengang_kz);
if (!empty($result_stg->retval) && isset($result_stg->retval[0]) && is_object($result_stg->retval[0]) && isset($result_stg->retval[0]->kurzbzlang))
{
$studiengang_kz = $result_stg->retval[0]->kurzbzlang;
}
}
$courses['semester'][$row_noten->studiensemester_kurzbz]['lvs_nonstpl'][] = array(
'lehrveranstaltung_id' => $row_noten->lehrveranstaltung_id,
'lehrtyp_kurzbz' => $result_lv->retval[0]->lehrtyp_kurzbz,
@@ -212,8 +224,8 @@ class Gradelist extends Auth_Controller
'semester' => $result_lv->retval[0]->semester,
'note' => $row_noten->note,
'datum' => $row_noten->benotungsdatum,
'zugeordnet' => true,
'studiengang_kurzbz' => $result_stg->retval[0]->kurzbzlang
'studiengang_kurzbz' => $studiengang_kz,
'zugeordnet' => true
);
if(!isset($courses['semester'][$row_noten->studiensemester_kurzbz]['data']['ectssumme_nonstpl']))
$courses['semester'][$row_noten->studiensemester_kurzbz]['data']['ectssumme_nonstpl'] = 0;
@@ -0,0 +1,610 @@
<?php
/*
* Job zur einmaligen Migration des Stundenplans
*
* Aufruf
* php index.ci.php system/MigrateKalender
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class MigrateKalender extends CLI_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->load->model('ressource/Kalender_model', 'KalenderModel');
$this->load->model('ressource/Kalender_Lehreinheit_model', 'KalenderLehreinheitModel');
$this->load->model('ressource/Kalender_Ort_model', 'KalenderOrtModel');
$this->load->model('ressource/Stundenplandev_Kalender_model', 'SyncModel');
$this->load->model('ressource/Reservierung_Kalender_model', 'SyncReservierungModel');
$this->load->model('ressource/Kalender_Event_Teilnehmer_model', 'KalenderEventTeilnehmerModel');
$this->load->model('ressource/Kalender_Event_model', 'KalenderEventModel');
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
}
/**
* Everything has a beginning
*/
public function migrateStundenplan($von, $bis = null, $studiengang_kz = null)
{
if (is_null($von))
return error('Parameter "von" ist erforderlich');
if (is_null($bis))
$bis = '2100-12-31';
$db = new DB_Model();
$stpldevsql = '
WITH eindeutige_stunden AS (
SELECT DISTINCT unr, datum, stunde
FROM lehre.tbl_stundenplandev
WHERE datum >= ? AND datum <= ?';
$params = [$von, $bis];
if (!is_null($studiengang_kz))
{
$stpldevsql .= ' AND studiengang_kz = ?';
$params[] = $studiengang_kz;
}
$stpldevsql .= '),
block_keys AS (
SELECT
unr,
datum,
stunde,
stunde - ROW_NUMBER() OVER (PARTITION BY unr, datum ORDER BY stunde) AS block_nr
FROM eindeutige_stunden
),
blocks AS (
SELECT
bk.unr,
bk.datum,
bk.block_nr,
MIN(bk.stunde) AS stunde_von,
MAX(bk.stunde) AS stunde_bis,
array_agg(DISTINCT sp.lehreinheit_id) AS lehreinheit_id,
array_agg(DISTINCT sp.ort_kurzbz) AS ort_kurzbz,
array_agg(sp.stundenplandev_id ORDER BY bk.stunde) AS stundenplandev_ids,
MIN(sp.insertamum) AS insertamum,
(array_agg(sp.insertvon ORDER BY sp.insertamum ASC))[1] AS insertvon,
MAX(sp.updateamum) AS updateamum,
(array_agg(sp.updatevon ORDER BY sp.updateamum DESC))[1] AS updatevon
FROM block_keys bk JOIN lehre.tbl_stundenplandev sp ON sp.unr = bk.unr AND sp.datum = bk.datum AND sp.stunde = bk.stunde
WHERE sp.datum >= ? AND sp.datum <= ?
GROUP BY bk.unr, bk.datum, bk.block_nr
)
SELECT
b.stundenplandev_ids,
b.unr,
b.datum,
b.block_nr,
b.lehreinheit_id,
b.ort_kurzbz,
b.datum + stundevon.beginn AS von,
b.datum + stundebis.ende AS bis,
b.insertamum,
b.insertvon,
b.updateamum,
b.updatevon
FROM blocks b
JOIN lehre.tbl_stunde stundevon ON stundevon.stunde = b.stunde_von
JOIN lehre.tbl_stunde stundebis ON stundebis.stunde = b.stunde_bis
ORDER BY b.datum, b.unr, b.block_nr;';
array_push($params, $von, $bis);
$stpldev = $db->execReadOnlyQuery($stpldevsql, $params);
if (hasData($stpldev))
{
// Pruefen ob der Eintrag schon in Sync Tabelle vorhanden ist
// Wenn neuere Änderungen vorhanden dann Update
// Wenn keine Änderungen seit leztem Sync dann Ueberspringen
// Wenn noch nicht vorhanden neu anlegen
// Danach ggf pruefen welceh Eintraege in der zwischenzeit geloescht wurden und
// in der neuen Tabelle auch archivieren oder loeschen
$data = getData($stpldev);
foreach($data as $block)
{
$ids = is_array($block->stundenplandev_ids) ? $block->stundenplandev_ids : explode(',', $block->stundenplandev_ids);
/*$ids = array_map('intval', $ids);*/
$this->SyncModel->db->group_start();
$where_ids_chunks = array_chunk($ids,25);
foreach($where_ids_chunks as $where_ids)
{
$this->SyncModel->db->or_where_in('stundenplandev_id', $where_ids);
}
$this->SyncModel->db->group_end();
$sync_result = $this->SyncModel->load();
if (!hasData($sync_result))
{
$kalender_id = $this->_insertKalender($block, 'lehreinheit');
if ($kalender_id)
{
$this->_insertSync($block->stundenplandev_ids, $kalender_id);
}
}
else
{
$syncData = getData($sync_result);
$kalender_id = $syncData[0]->kalender_id;
$last_sync = $syncData[0]->lastupdate;
$synced_ids = array_column($syncData, 'stundenplandev_id');
if ($block->updateamum > $last_sync)
{
$this->_updateKalender($kalender_id, $block);
$this->_updateSync($synced_ids, $kalender_id);
}
$fehlende = array_diff($block->stundenplandev_ids, $synced_ids);
if (!empty($fehlende))
{
$this->_insertSync($fehlende, $kalender_id);
}
}
}
}
}
public function migrateReservierung($von, $bis = null, $ort_kurzbz = null)
{
if (is_null($von))
return error('Parameter "von" ist erforderlich');
if (is_null($bis))
$bis = '2100-12-31';
$db = new DB_Model();
$qry = "WITH eindeutige_stunden AS (
SELECT DISTINCT titel, beschreibung, datum, stunde
FROM campus.tbl_reservierung
WHERE datum >= ? AND datum <= ?";
$params = array($von, $bis);
if (!is_null($ort_kurzbz))
{
$qry .= " AND ort_kurzbz = ?";
$params[] = $ort_kurzbz;
}
$qry .= "),
block_keys AS (
SELECT
titel, beschreibung, datum, stunde,
stunde - ROW_NUMBER() OVER (PARTITION BY titel, beschreibung, datum ORDER BY stunde) AS block_nr
FROM eindeutige_stunden
),
blocks AS (
SELECT
bk.titel,
bk.beschreibung,
bk.datum,
bk.block_nr,
MIN(bk.stunde) AS stunde_von,
MAX(bk.stunde) AS stunde_bis,
array_agg(DISTINCT r.reservierung_id::text) AS reservierung_ids,
array_agg(DISTINCT r.uid) AS uids,
array_agg(DISTINCT r.gruppe_kurzbz) AS gruppen_kurzbz,
array_agg(DISTINCT ROW(r.semester, r.verband, r.gruppe, r.studiengang_kz)::text) AS svg_kombis,
array_agg(DISTINCT r.ort_kurzbz) AS ort_kurzbz,
MIN(r.studiengang_kz) AS studiengang_kz,
MIN(r.reservierung_id) AS reservierung_id,
MAX(r.insertamum) AS insertamum,
(array_agg(r.insertvon ORDER BY r.insertamum ASC))[1] AS insertvon
FROM block_keys bk
JOIN campus.tbl_reservierung r
ON r.titel = bk.titel AND r.beschreibung = bk.beschreibung AND r.datum = bk.datum AND r.stunde = bk.stunde
WHERE r.datum >= ? AND r.datum <= ?
GROUP BY bk.titel, bk.beschreibung, bk.datum, bk.block_nr
)
SELECT
b.*,
(b.datum + s_von.beginn) AS von,
(b.datum + s_bis.ende) AS bis
FROM blocks b
JOIN lehre.tbl_stunde s_von ON s_von.stunde = b.stunde_von
JOIN lehre.tbl_stunde s_bis ON s_bis.stunde = b.stunde_bis
ORDER BY b.reservierung_id DESC;";
array_push($params, $von, $bis);
$reservierung_data = $db->execReadOnlyQuery($qry, $params);
if (hasData($reservierung_data))
{
$data = getData($reservierung_data);
foreach($data as $block)
{
$ids = is_array($block->reservierung_ids) ? $block->reservierung_ids : explode(',', $block->reservierung_ids);
$this->SyncReservierungModel->db->group_start();
$where_ids_chunks = array_chunk($ids,25);
foreach($where_ids_chunks as $where_ids)
{
$this->SyncReservierungModel->db->or_where_in('reservierung_id', $where_ids);
}
$this->SyncReservierungModel->db->group_end();
$sync_result = $this->SyncReservierungModel->load();
if (!hasData($sync_result))
{
$kalender_id = $this->_insertKalender($block, 'reservierung');
if ($kalender_id)
{
$this->_insertReservierungSync($block->reservierung_ids, $kalender_id);
}
}
else
{
$syncData = getData($sync_result);
$kalender_id = $syncData[0]->kalender_id;
$last_sync = $syncData[0]->lastupdate;
$synced_ids = array_column($syncData, 'reservierung_id');
if ($block->insertamum > $last_sync)
{
$this->_updateKalender($kalender_id, $block);
$this->_updateReservierungSync($synced_ids, $kalender_id);
}
$fehlende = array_diff($block->reservierung_ids, $synced_ids);
if (!empty($fehlende))
{
$this->_insertReservierungSync($fehlende, $kalender_id);
}
}
}
}
}
public function migrateStundenplanBetriebsmittelEntries() {
$this->setKalendarEntriesGroupIDs();
$this->setKalendarEntriesGroupIDsForChildren();
$dbModel = new DB_Model();
$deleteOldImportedTempusEntriesQuery = "DELETE from lehre.tbl_betriebsmittel_kalender WHERE quelle != 'tempus_neu' OR quelle IS NULL;";
$createHelperTypeQuery = "DO $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM pg_type
WHERE typname = 'betriebsmittel_info'
) THEN
CREATE TYPE betriebsmittel_info AS (
betriebsmittel_id bigint,
insertamum timestamp,
insertvon text
);
END IF;
END $$;";
$query = $deleteOldImportedTempusEntriesQuery .
$createHelperTypeQuery .
"WITH test AS (
SELECT
tk.eindeutige_kalender_gruppen_id AS eindeutige_kalender_gruppen_id,
array_agg(tk.kalender_id),
array_agg(
ROW(tsb.betriebsmittel_id, tsb.insertamum, tsb.insertvon)::betriebsmittel_info
) AS betriebsmittel_data
FROM sync.tbl_stundenplandev_kalender AS sk
JOIN lehre.tbl_kalender tk ON tk.kalender_id = sk.kalender_id
JOIN lehre.tbl_stundenplan_betriebsmittel tsb ON tsb.stundenplandev_id = sk.stundenplandev_id
GROUP BY tk.eindeutige_kalender_gruppen_id
)
INSERT INTO lehre.tbl_betriebsmittel_kalender (
eindeutige_kalender_gruppen_id,
betriebsmittel_id,
insertamum,
insertvon
)
SELECT
t.eindeutige_kalender_gruppen_id,
bm.betriebsmittel_id,
bm.insertamum,
bm.insertvon
FROM test t
CROSS JOIN LATERAL unnest(t.betriebsmittel_data) AS bm
ON CONFLICT (eindeutige_kalender_gruppen_id, betriebsmittel_id) DO NOTHING;
;";
$dbModel->db->query($query);
}
private function setKalendarEntriesGroupIDs() {
$dbModel = new DB_Model();
$query = "UPDATE lehre.tbl_kalender
SET eindeutige_kalender_gruppen_id = gen_random_uuid()
WHERE vorgaenger_kalender_id IS NULL
AND eindeutige_kalender_gruppen_id IS NULL;";
$dbModel->db->query($query);
}
private function setKalendarEntriesGroupIDsForChildren() {
$dbModel = new DB_Model();
$query = "WITH RECURSIVE tree AS
(
SELECT
kalender_id,
vorgaenger_kalender_id,
kalender_id AS root_id,
eindeutige_kalender_gruppen_id as root_eindeutige_kalender_gruppen_id
FROM lehre.tbl_kalender
WHERE vorgaenger_kalender_id IS NULL
UNION ALL
SELECT
i.kalender_id,
i.vorgaenger_kalender_id,
t.root_id,
t.root_eindeutige_kalender_gruppen_id
FROM lehre.tbl_kalender i
JOIN tree t
ON i.vorgaenger_kalender_id = t.kalender_id
where i.eindeutige_kalender_gruppen_id is NULL
)
UPDATE lehre.tbl_kalender k
SET eindeutige_kalender_gruppen_id = t.root_eindeutige_kalender_gruppen_id
FROM tree t
WHERE k.kalender_id = t.kalender_id
AND k.eindeutige_kalender_gruppen_id IS NULL;";
$dbModel->db->query($query);
}
private function _insertKalender($block, $typ)
{
$result = $this->KalenderModel->insert(
array (
'von' => $block->von,
'bis' => $block->bis,
'typ' => $typ,
'status_kurzbz'=> 'live',
'insertamum' => $block->insertamum,
'insertvon' => $block->insertvon,
'updateamum' => $block->updateamum ?? null,
'updatevon' => $block->updatevon ?? null
)
);
if(!isSuccess($result))
return null;
$kalender_id = getData($result);
if ($typ === 'lehreinheit')
{
$lehreinheit_ids = is_array($block->lehreinheit_id) ? $block->lehreinheit_id : explode(',', $block->lehreinheit_id);
foreach ($lehreinheit_ids as $lehreinheit_id)
{
$leResult = $this->KalenderLehreinheitModel->insert(
array (
'kalender_id' => $kalender_id,
'lehreinheit_id'=> $lehreinheit_id
)
);
if (!isSuccess($leResult))
return null;
}
}
else if ($typ === 'reservierung')
{
$eventResult = $this->KalenderEventModel->insert(array(
'kalender_id' => $kalender_id,
'titel' => $block->titel,
'beschreibung' => $block->beschreibung
));
if (!isSuccess($eventResult))
return null;
if ($block->insertvon)
{
$user = $this->BenutzerModel->load(array('uid' => $block->insertvon));
if (hasData($user))
{
$this->KalenderEventTeilnehmerModel->insert(array(
'kalender_id' => $kalender_id,
'uid' => getData($user)[0]->uid,
'rolle_kurzbz' => 'organisator'
));
}
}
$uids = is_array($block->uids) ? $block->uids : explode(',', $block->uids);
foreach ($uids as $uid)
{
$this->KalenderEventTeilnehmerModel->insert(array(
'kalender_id' => $kalender_id,
'uid' => $uid,
'rolle_kurzbz' => 'teilnehmer'
));
}
$semester_range = $this->StudiensemesterModel->getByDateRange($block->von, $block->bis);
if (isError($semester_range))
return null;
$studiensemester_kurzbz = getData($semester_range)[0]->studiensemester_kurzbz ?? null;
$gruppen = is_array($block->gruppen_kurzbz) ? $block->gruppen_kurzbz : explode(',', $block->gruppen_kurzbz ?? '');
foreach ($gruppen as $gruppe_kurzbz)
{
$gruppe_kurzbz = trim($gruppe_kurzbz);
if (!empty($gruppe_kurzbz))
{
$this->KalenderEventTeilnehmerModel->insert(array(
'kalender_id' => $kalender_id,
'gruppe_kurzbz' => $gruppe_kurzbz,
'studiengang_kz' => $block->studiengang_kz,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'rolle_kurzbz' => 'teilnehmer'
));
}
}
foreach ($block->svg_kombis as $kombi_str)
{
$kombi_str = trim($kombi_str, '()');
list($sem, $verb, $grp, $stg_kz) = explode(',', $kombi_str);
$sem = trim($sem) === '' ? null : trim($sem);
$verb = trim($verb) === '' ? null : trim($verb);
$grp = trim($grp) === '' ? null : trim($grp);
$stg_kz = trim($stg_kz) === '' ? null : trim($stg_kz);
if (is_null($sem) && is_null($verb) && is_null($grp) && is_null($stg_kz))
continue;
$this->KalenderEventTeilnehmerModel->insert(array(
'kalender_id' => $kalender_id,
'studiengang_kz' => $stg_kz,
'semester' => $sem,
'verband' => $verb,
'gruppe' => $grp,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'rolle_kurzbz' => 'teilnehmer'
));
}
}
$orte = is_array($block->ort_kurzbz) ? $block->ort_kurzbz : explode(',', $block->ort_kurzbz ?? '');
foreach ($orte as $ort)
{
$ort = trim($ort);
if (!empty($ort))
{
$this->KalenderOrtModel->insert(
array (
'kalender_id' => $kalender_id,
'ort_kurzbz' => $ort
)
);
}
}
return $kalender_id;
}
private function _insertSync($ids, $kalender_id)
{
foreach($ids as $id)
{
$this->SyncModel->insert(
array (
'stundenplandev_id' => $id,
'kalender_id' => $kalender_id,
'lastupdate' => date('Y-m-d H:i:s')
)
);
}
}
private function _insertReservierungSync($ids, $kalender_id)
{
foreach($ids as $id)
{
$this->SyncReservierungModel->insert(
array (
'reservierung_id' => $id,
'kalender_id' => $kalender_id,
'lastupdate' => date('Y-m-d H:i:s')
)
);
}
}
private function _updateKalender($kalender_id, $block)
{
$this->KalenderModel->update(
array (
'kalender_id' => $kalender_id
),
array (
'von' => $block->von,
'bis' => $block->bis,
'updateamum'=> $block->updateamum,
'updatevon' => $block->updatevon
)
);
$orte = is_array($block->ort_kurzbz) ? $block->ort_kurzbz : explode(',', $block->ort_kurzbz ?? '');
$orte = array_filter(array_map('trim', $orte));
$this->KalenderOrtModel->delete(array('kalender_id' => $kalender_id));
foreach ($orte as $ort)
{
$this->KalenderOrtModel->insert(
array (
'kalender_id' => $kalender_id,
'ort_kurzbz' => $ort
)
);
}
}
private function _updateSync($ids, $kalender_id)
{
foreach($ids as $id)
{
$this->SyncModel->update(
array (
'stundenplandev_id' => $id,
'kalender_id' => $kalender_id
),
array (
'lastupdate' => date('Y-m-d H:i:s')
)
);
}
}
private function _updateReservierungSync($ids, $kalender_id)
{
foreach($ids as $id)
{
$this->SyncReservierungModel->update(
array (
'reservierung_id' => $id,
'kalender_id' => $kalender_id
),
array (
'lastupdate' => date('Y-m-d H:i:s')
)
);
}
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
interface ICollisionCheck
{
public function getName();
public function check($data);
public function checkAll($kalender_ids);
}
+140 -11
View File
@@ -7,7 +7,7 @@ class Tag_Controller extends FHCAPI_Controller
{
private $_uid;
const BERECHTIGUNG_KURZBZ = 'admin:rw';
const BERECHTIGUNG_KURZBZ = ['admin:rw'];
public function __construct($permissions)
{
@@ -15,10 +15,11 @@ class Tag_Controller extends FHCAPI_Controller
'getTag' => self::BERECHTIGUNG_KURZBZ,
'getTags' => self::BERECHTIGUNG_KURZBZ,
'addTag' => self::BERECHTIGUNG_KURZBZ,
'updateTag' => self::BERECHTIGUNG_KURZBZ,
'doneTag' => self::BERECHTIGUNG_KURZBZ,
'deleteTag' => self::BERECHTIGUNG_KURZBZ,
'getAllTags' => self::BERECHTIGUNG_KURZBZ,
'rebuildTagsForTypeId' => self::BERECHTIGUNG_KURZBZ,
];
$merged_permissions = array_merge($default_permissions, $permissions);
@@ -26,6 +27,10 @@ class Tag_Controller extends FHCAPI_Controller
parent::__construct($merged_permissions);
$this->_setAuthUID();
// Library
$this->load->library('TagLib');
$this->load->model('person/Notiz_model', 'NotizModel');
$this->load->model('system/Notiztyp_model', 'NotiztypModel');
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
@@ -38,6 +43,7 @@ class Tag_Controller extends FHCAPI_Controller
public function getTag($readonly_tags = null)
{
$language = $this->_getLanguageIndex();
$index_bezeichnung_mehrsprachig = $language - 1;
$id = $this->input->get('id');
if (is_array($readonly_tags) && !isEmptyArray($readonly_tags))
@@ -62,14 +68,18 @@ class Tag_Controller extends FHCAPI_Controller
$this->NotizModel->addSelect(
"tbl_notiz.titel,
tbl_notiz.text,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $language. " as bezeichnung,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $index_bezeichnung_mehrsprachig . " as bezeichnung,
tbl_notiz.notiz_id,
tbl_notiz_typ.style,
tbl_notiz_typ.automatisiert,
tbl_notiz_typ.prioritaet,
tbl_notiz.erledigt as done,
tbl_notiz.insertamum,
tbl_notiz.updateamum,
(verfasserperson.vorname || ' ' || verfasserperson.nachname || ' ' || '(' || verfasserbenutzer.uid || ')') as verfasser,
(bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter
(bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter,
tbl_notiz.start,
tbl_notiz.ende
"
);
$this->NotizModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz');
@@ -82,18 +92,24 @@ class Tag_Controller extends FHCAPI_Controller
$notiz = $this->NotizModel->loadWhere(array('notiz_id' => $id));
$this->terminateWithSuccess(hasData($notiz) ? getData($notiz)[0] : array());
}
public function getTags($tags = null)
{
$language = $this->_getLanguageIndex();
$index_bezeichnung_mehrsprachig = $language - 1;
$this->NotiztypModel->addSelect(
'typ_kurzbz as tag_typ_kurzbz,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung,
"typ_kurzbz as tag_typ_kurzbz,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $index_bezeichnung_mehrsprachig . " as bezeichnung,
style,
beschreibung,
tag
'
tag,
automatisiert,
prioritaet
"
);
$this->NotiztypModel->addOrder('prioritaet');
@@ -106,7 +122,36 @@ class Tag_Controller extends FHCAPI_Controller
$notiztypen = $this->NotiztypModel->loadWhere(array('aktiv' => true));
$this->terminateWithSuccess(hasData($notiztypen) ? getData($notiztypen) : array());
}
public function getTagsByAssignmentTypeValue($zuordnung_typ, $zuordnung_id, $tags = null)
{
$language = $this->_getLanguageIndex();
$index_bezeichnung_mehrsprachig = $language - 1;
$this->NotizzuordnungModel->addSelect(
'tbl_notizzuordnung.notiz_id as notiz_id,
typ_kurzbz as tag_typ_kurzbz,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>'. $index_bezeichnung_mehrsprachig. ' as bezeichnung,
style,
beschreibung,
tag,
tbl_notiz.erledigt as done
'
);
if (is_array($tags) && !isEmptyArray($tags))
{
$tags = $this->_filterTag($tags, false);
$this->NotizzuordnungModel->db->where_in('tbl_notiz_typ.typ_kurzbz', $tags);
}
$this->NotizzuordnungModel->addJoin('public.tbl_notiz', 'public.tbl_notizzuordnung.notiz_id = public.tbl_notiz.notiz_id');
$this->NotizzuordnungModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz');
$this->NotizzuordnungModel->addOrder('prioritaet');
$notiztypen = $this->NotizzuordnungModel->loadWhere(array('aktiv' => true, $zuordnung_typ => $zuordnung_id));
$this->terminateWithSuccess(hasData($notiztypen) ? getData($notiztypen) : array());
}
public function addTag($withZuordnung = true, $updatable_tags = null)
{
$postData = $this->getPostJson();
@@ -126,7 +171,7 @@ class Tag_Controller extends FHCAPI_Controller
if (!in_array($postData->tag_typ_kurzbz, $tags))
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
}
if ($withZuordnung)
{
$return = array();
@@ -135,7 +180,7 @@ class Tag_Controller extends FHCAPI_Controller
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$values = array_unique($postData->values);
foreach ($values as $value)
{
$insertResult = $this->addNotiz($postData);
@@ -271,6 +316,90 @@ class Tag_Controller extends FHCAPI_Controller
$this->terminateWithSuccess($deleteNotiz);
}
public function getAllTags($readonly_tags = false)
{
$language = $this->_getLanguageIndex();
$index_bezeichnung_mehrsprachig = $language - 1;
$prestudent_id = $this->input->get('prestudent_id');
if (is_array($readonly_tags) && !isEmptyArray($readonly_tags))
{
$readonly_tags = $this->_filterTag($readonly_tags, true);
foreach ($readonly_tags as $key => $tag)
{
$readonly_tags[$key] = $this->NotizModel->db->escape($tag);
}
$tags = '(' . implode(',', $readonly_tags) . ')';
$this->NotizModel->addSelect("
CASE
WHEN tbl_notiz_typ.typ_kurzbz IN $tags
THEN TRUE
ELSE FALSE
END as readonly
");
}
$this->NotizModel->addSelect(
"tbl_notiz.titel,
tbl_notiz.text,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $index_bezeichnung_mehrsprachig . " as bezeichnung,
tbl_notiz.notiz_id,
tbl_notiz_typ.style,
tbl_notiz_typ.automatisiert,
tbl_notiz_typ.prioritaet,
tbl_notiz.erledigt as done,
tbl_notiz.insertamum,
tbl_notiz.updateamum,
(verfasserperson.vorname || ' ' || verfasserperson.nachname || ' ' || '(' || verfasserbenutzer.uid || ')') as verfasser,
(bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter,
tbl_notiz.start,
tbl_notiz.ende
"
);
$this->NotizModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz');
$this->NotizModel->addJoin('public.tbl_benutzer verfasserbenutzer', 'tbl_notiz.verfasser_uid = verfasserbenutzer.uid', 'LEFT');
$this->NotizModel->addJoin('public.tbl_person verfasserperson', 'verfasserbenutzer.person_id = verfasserperson.person_id', 'LEFT');
$this->NotizModel->addJoin('public.tbl_benutzer bearbeiterbenutzer', 'tbl_notiz.bearbeiter_uid = bearbeiterbenutzer.uid', 'LEFT');
$this->NotizModel->addJoin('public.tbl_person bearbeiterperson', 'bearbeiterbenutzer.person_id = bearbeiterperson.person_id', 'LEFT');
$this->NotizModel->addJoin('public.tbl_notizzuordnung notizzuordnung', 'tbl_notiz.notiz_id = notizzuordnung.notiz_id');
$this->NotizModel->addOrder('done');
$this->NotizModel->addOrder('tbl_notiz_typ.prioritaet');
$notiz = $this->NotizModel->loadWhere(array('prestudent_id' => $prestudent_id));
$this->terminateWithSuccess(hasData($notiz) ? getData($notiz) : array());
}
public function rebuildTagsForTypeId()
{
$ids = $this->input->post('ids');
$typeId = $this->input->post('typeId');
$semester = $this->input->post('sem');
$idsSuccess = [];
$idsError = [];
$outputResult = [];
foreach ($ids as $id)
{
$result = $this->taglib->rebuildTagsForTypeId($typeId, $id, $semester);
if (isError($result))
$idsError[] = $id;
else
$idsSuccess[] = $id;
$outputResult[] = $result;
}
$this->terminateWithSuccess([$outputResult, $idsSuccess, $idsError]);
}
private function _setAuthUID()
{
$this->_uid = getAuthUID();
@@ -311,4 +440,4 @@ class Tag_Controller extends FHCAPI_Controller
));
}
}
}
+10
View File
@@ -570,3 +570,13 @@ function buildDropdownEntryPrintArray($id, $name, $parameterurl, $uid=null, $ord
];
}
function generateUUID()
{
$data = openssl_random_pseudo_bytes(16);
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
+188
View File
@@ -0,0 +1,188 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Helper function to generate the default documentslist config for the
* grades tab.
*
* The resulting array consists of elements which are associative arrays
* that can have the following entries:
* title (required) on the first level this can be HTML code.
* permissioncheck (optional) an URL to an FHCAPI endpoint which returns
* true or false.
* link (optional) an URL that will be called if "action" and
* "children" are not defined.
* action (optional) an associative array that describes an
* POST action that will be called if "children" is
* not defined.
* It can have the following entries:
* - url (required) an URL to an FHCAPI endpoint.
* - post (optional) an associative array with the POST data to
* be sent.
* - response (optional) a string that will be displayed on success.
* children (optional) an array of child elements
*
* All strings that start with { and end with } in the URLs and the
* actions post parameter will be replaced with the corresponding
* attribute of the current dataset (e.G: {uid} will be replaced with the
* uid of the current dataset)
*
* @return array
*/
function gradesDocumentsList()
{
$ci =& get_instance();
$ci->load->library('PhrasesLib', array('stv'), 'p');
$permissioncheck = site_url("api/frontend/v1/documents/permissionAlternativeFormat/{studiengang_kz}");
$title_ger = $ci->p->t("global", "deutsch");
$title_eng = $ci->p->t("global", "englisch");
$title_ff = $ci->p->t("stv", "document_certificate");
$title_lv = $ci->p->t("stv", "document_coursecertificate");
$link_ff = "documents/export/" .
"zertifikat.rdf.php/" .
"Zertifikat" .
"?stg_kz={studiengang_kz_lv}" .
"&uid={uid}" .
"&ss={studiensemester_kurzbz}" .
"&lvid={lehrveranstaltung_id}";
$link_lv_ger = "documents/export/" .
"lehrveranstaltungszeugnis.rdf.php/" .
"LVZeugnis" .
"?stg_kz={studiengang_kz}" .
"&uid={uid}" .
"&ss={studiensemester_kurzbz}" .
"&lvid={lehrveranstaltung_id}";
$link_lv_eng = "documents/export/" .
"lehrveranstaltungszeugnis.rdf.php/" .
"LVZeugnisEng" .
"?stg_kz={studiengang_kz}" .
"&uid={uid}" .
"&ss={studiensemester_kurzbz}" .
"&lvid={lehrveranstaltung_id}";
$archive_url = "api/frontend/v1/documents/archiveSigned";
$archive_response = $ci->p->t("stv", "document_signed_and_archived");
$archive_post_ff = [
"xml" => "zertifikat.rdf.php",
"xsl" => "Zertifikat",
"stg_kz" => "{studiengang_kz_lv}",
"uid" => "{uid}",
"ss" => "{studiensemester_kurzbz}",
"lvid" => "{lehrveranstaltung_id}"
];
$archive_post_lv_ger = [
"xml" => "lehrveranstaltungszeugnis.rdf.php",
"xsl" => "LVZeugnis",
"stg_kz" => "{studiengang_kz}",
"uid" => "{uid}",
"ss" => "{studiensemester_kurzbz}",
"lvid" => "{lehrveranstaltung_id}"
];
$archive_post_lv_eng = [
"xml" => "lehrveranstaltungszeugnis.rdf.php",
"xsl" => "LVZeugnisEng",
"stg_kz" => "{studiengang_kz}",
"uid" => "{uid}",
"ss" => "{studiensemester_kurzbz}",
"lvid" => "{lehrveranstaltung_id}"
];
$list = [
[
'title' => '<i class="fa fa-download" title="' . $ci->p->t("stv", "document_download") . '"></i>',
'children' => [
[
'title' => $title_ff,
'link' => site_url($link_ff)
],
[
'title' => $title_lv,
'children' => [
[
'title' => $title_ger,
'link' => site_url($link_lv_ger),
'children' => [
[
'title' => 'PDF',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_ger)
],
[
'title' => 'DOC',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_ger . "&output=doc")
],
[
'title' => 'ODT',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_ger . "&output=odt")
]
]
],
[
'title' => $title_eng,
'link' => site_url($link_lv_eng),
'children' => [
[
'title' => 'PDF',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_eng)
],
[
'title' => 'DOC',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_eng . "&output=doc")
],
[
'title' => 'ODT',
'permissioncheck' => $permissioncheck,
'link' => site_url($link_lv_eng . "&output=odt")
]
]
]
]
]
]
],
[
'title' => '<i class="fas fa-archive" title="' . $ci->p->t("stv", "document_archive") . '"></i>',
'children' => [
[
'title' => $title_ff,
'action' => [
'url' => site_url($archive_url),
'post' => $archive_post_ff,
'response' => $archive_response
]
],
[
'title' => $title_lv,
'children' => [
[
'title' => $title_ger,
'action' => [
'url' => site_url($archive_url),
'post' => $archive_post_lv_ger,
'response' => $archive_response
]
],
[
'title' => $title_eng,
'action' => [
'url' => site_url($archive_url),
'post' => $archive_post_lv_eng,
'response' => $archive_response
]
]
]
]
]
]
];
return $list;
}
+24 -1
View File
@@ -111,7 +111,8 @@ function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod)
'theme' => [
'name'=>$ci->config->item('theme_name'),
'modes'=>$ci->config->item('theme_modes'),
]
],
'domain' => DOMAIN
);
$toPrint = "\n";
@@ -270,6 +271,28 @@ function absoluteJsImportUrl($relurl)
return $url;
}
/*
* Generate Css File Include if Extension contains file
*
* @param $relativeFilePath path relative to Extension public/css dir
*/
function generateCSSsIncludeIfExtensionCssExists($relativeFilePath)
{
$fsiterator = new FilesystemIterator(FHCPATH . 'application/extensions');
foreach ($fsiterator as $fsitem)
{
if(preg_match('/^FHC-Core-/', $fsitem->getBasename()))
{
$extensionfile = 'public/extensions/' . $fsitem->getBasename()
. '/css/' . $relativeFilePath;
if(is_readable(FHCPATH . $extensionfile))
{
generateCSSsInclude($extensionfile);
}
}
}
}
/*
* Manipulate CI views includes Array to load
* - public/js/FhcApps.js via customJSs and
@@ -0,0 +1,67 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
use CI3_Events as Events;
class CollisionChecker
{
private $_checks = [];
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->library('collision/checks/RoomCollisionCheck');
$this->_ci->load->library('collision/checks/LectureCollisionCheck');
$this->_ci->load->library('collision/checks/VerbandCollisionCheck');
$this->_ci->load->library('collision/checks/StudentCollisionCheck');
$this->_ci->load->library('collision/checks/ResourcesCollisionCheck');
$this->register($this->_ci->roomcollisioncheck);
$this->register($this->_ci->lecturecollisioncheck);
$this->register($this->_ci->verbandcollisioncheck);
$this->register($this->_ci->studentcollisioncheck);
$this->register($this->_ci->resourcescollisioncheck);
Events::trigger('collision_register', $this);
}
public function register(ICollisionCheck $check)
{
$this->_checks[$check->getName()] = $check;
}
public function run($data)
{
$errors = [];
foreach ($this->_checks as $check)
{
$result = $check->check($data);
if (!empty($result))
{
$errors = array_merge($errors, $result);
}
}
return $errors;
}
public function runAll($kalender_ids)
{
$results = array_fill_keys($kalender_ids, []);
foreach ($this->_checks as $check)
{
$batchResult = $check->checkAll($kalender_ids);
foreach ($batchResult as $kalender_id => $errors)
{
$results[$kalender_id] = array_merge($results[$kalender_id], $errors);
}
}
return $results;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,171 @@
<?php
if (! defined("BASEPATH")) exit("No direct script access allowed");
class KalenderNotificationLib
{
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->library('MailLib');
$this->_ci->load->config('tempus');
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
}
public function sendMails($mail_infos)
{
if (!$this->_ci->config->item('send_update_mails'))
return true;
$lektor_added = array();
$lektor_changed = array();
$lektor_deleted = array();
$student_added = array();
$student_changed = array();
$student_deleted = array();
foreach ($mail_infos as $info)
{
$entry = $info['entry'];
$new_status = $info['new_status'];
$notify = $info['notify'];
$old_entry = null;
if ($entry->vorgaenger_kalender_id)
{
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id', 'LEFT');
$vorgaenger = $this->_ci->KalenderModel->load(array('tbl_kalender.kalender_id' => $entry->vorgaenger_kalender_id));
if (hasData($vorgaenger))
$old_entry = getData($vorgaenger)[0];
}
if ($new_status === 'deleted')
$row = $this->_buildMailDeleted($entry);
else if ($old_entry)
$row = $this->_buildMailChanged($old_entry, $entry);
else
$row = $this->_buildMailNew($entry);
if (in_array('lektor', $notify))
{
if ($new_status === 'deleted')
$lektor_deleted[] = $row;
else if ($old_entry)
$lektor_changed[] = $row;
else
$lektor_added[] = $row;
}
if (in_array('student', $notify))
{
if ($new_status === 'deleted')
$student_deleted[] = $row;
else if ($old_entry)
$student_changed[] = $row;
else
$student_added[] = $row;
}
}
$lektor_entries = '';
$student_entries = '';
if (!empty($lektor_added))
$lektor_entries .= $this->_addToList($lektor_added, 'hinzugefügt') . '<hr/>';
if (!empty($lektor_changed))
$lektor_entries .= $this->_addToList($lektor_changed, 'geändert') . '<hr/>';
if (!empty($lektor_deleted))
$lektor_entries .= $this->_addToList($lektor_deleted, 'gelöscht') . '<hr/>';
if (!empty($student_added))
$student_entries .= $this->_addToList($student_added, 'hinzugefügt') . '<hr/>';
if (!empty($student_changed))
$student_entries .= $this->_addToList($student_changed, 'geändert') . '<hr/>';
if (!empty($student_deleted))
$student_entries .= $this->_addToList($student_deleted, 'gelöscht') . '<hr/>';
//TODO (david) richtigen Empfänger
if (!empty($lektor_entries))
$this->_ci->maillib->send('', '[email protected]', 'Lektor Tempus Update', $lektor_entries);
if (!empty($student_entries))
$this->_ci->maillib->send('', '[email protected]', 'Student Tempus Update', $student_entries);
}
private function _addToList($entries, $status)
{
return 'Folgende Einträge wurden <b>'. $status .'</b>: <ul>' . implode('', $entries) . '</ul>';
}
private function _buildMailNew($entry)
{
$von = date('d.m.Y H:i', strtotime($entry->von));
$bis = date('H:i', strtotime($entry->bis));
return '<li>
<b>Kalender ID ' . ($entry->kalender_id ?? '-') . '</b>
<ul>
<li><b>Uhrzeit:</b> ' . $von . ' - ' . $bis . '</li>
<li><b>Ort:</b> ' . ($entry->ort_kurzbz ?? '-') . '</li>
</ul>
</li>';
}
private function _buildMailChanged($old_entry, $new_entry)
{
$old_von = date('d.m.Y H:i', strtotime($old_entry->von));
$old_bis = date('H:i', strtotime($old_entry->bis));
$new_von = date('d.m.Y H:i', strtotime($new_entry->von));
$new_bis = date('H:i', strtotime($new_entry->bis));
$old_ort = $old_entry->ort_kurzbz ?? '-';
$new_ort = $new_entry->ort_kurzbz ?? '-';
$uhrzeit_changed = ($old_von . $old_bis) !== ($new_von . $new_bis);
$ort_changed = $old_ort !== $new_ort;
$changes = '';
if ($uhrzeit_changed)
{
$changes .= '<li>
<b>Uhrzeit:</b>
<s style="color:red;">' . $old_von . ' - ' . $old_bis . '</s>
<span style="color:green;">' . $new_von . ' - ' . $new_bis . '</span>
</li>';
}
if ($ort_changed)
{
$changes .= '<li>
<b>Ort:</b>
<s style="color:red;">' . $old_ort . '</s>
<span style="color:green;">' . $new_ort . '</span>
</li>';
}
return '<li>
<b>Kalender ID ' . ($new_entry->kalender_id ?? '-') . '</b>
<ul>' . $changes . '</ul>
</li>';
}
private function _buildMailDeleted($entry)
{
$von = date('d.m.Y H:i', strtotime($entry->von));
$bis = date('H:i', strtotime($entry->bis));
return '<li style="color:red;">
<b><s>Kalender ID ' . ($entry->kalender_id ?? '-') . '</s></b>
<ul>
<li><s>' . $von . ' - ' . $bis . '</s></li>
<li><s>' . ($entry->ort_kurzbz ?? '-') . '</s></li>
</ul>
</li>';
}
}
+429
View File
@@ -0,0 +1,429 @@
<?php
if (! defined("BASEPATH")) exit("No direct script access allowed");
class KalenderSyncLib
{
private $_ci;
private $status_map = array(
'preview' => array('planning', 'sync_preview'),
'live' => array('planning', 'sync_preview', 'preview', 'sync_live')
);
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
$this->_ci->load->model('ressource/Kalendersyncstatus_model', 'KalendersyncstatusModel');
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$this->_ci->load->library('KalenderLib');
}
public function run($studiensemester_kurzbz)
{
$this->_ci->KalendersyncstatusModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
$configs = $this->_ci->KalendersyncstatusModel->load();
if (isError($configs))
return $configs;
if (!hasData($configs))
return success([]);
$results = [];
$mail_infos_gesamt = [];
foreach (getData($configs) as $config)
{
$ziel_status = isEmptyString($config->sync_status_kurzbz) ? 'live' : $config->sync_status_kurzbz;
$relevante_stati = array_merge($this->status_map[$ziel_status], array('to_delete', 'to_delete_live', 'to_delete_preview'));
$kalender_ids_result = $this->getKalenderIds(
$config->oe_kurzbz,
$config->studiensemester_kurzbz,
$relevante_stati,
$config->ausbildungssemester,
$config->studienplan_id,
$config->datum_bis
);
if (isError($kalender_ids_result))
return $kalender_ids_result;
$kalender_ids = getData($kalender_ids_result);
$sync_result = $this->_syncKalenderIds($kalender_ids, $ziel_status);
if (isError($sync_result))
return $sync_result;
$sync_data = getData($sync_result);
if ((bool) $config->mail)
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $sync_data['mail_infos']);
$results[] = [
'kalender_syncstatus_id' => $config->kalender_syncstatus_id,
'oe_kurzbz' => $config->oe_kurzbz,
'ausbildungssemester' => $config->ausbildungssemester,
'studienplan_id' => $config->studienplan_id,
'ziel_status' => $ziel_status,
'mail' => (bool) $config->mail,
'synced' => $sync_data['synced']
];
}
if (!empty($mail_infos_gesamt))
{
$this->_ci->load->library('KalenderNotificationLib');
$this->_ci->kalendernotificationlib->sendMails($mail_infos_gesamt);
}
return success($results);
}
public function runManual($oe_kurzbz, $studiensemester_kurzbz, $ausbildungssemester = null, $studienplan_id = null, $mail = true, $datum_bis = null, $ziel_status = 'live')
{
$relevante_stati = array_merge($this->status_map[$ziel_status], array('to_delete', 'to_delete_live', 'to_delete_preview'));
$kalender_ids_result = $this->getKalenderIds(
$oe_kurzbz,
$studiensemester_kurzbz,
$relevante_stati,
$ausbildungssemester,
$studienplan_id,
$datum_bis
);
if (isError($kalender_ids_result))
return $kalender_ids_result;
$kalender_ids = getData($kalender_ids_result);
$sync_result = $this->_syncKalenderIds($kalender_ids, $ziel_status);
if (isError($sync_result))
return $sync_result;
$sync_data = getData($sync_result);
if ($mail && !empty($sync_data['mail_infos']))
{
$this->_ci->load->library('KalenderNotificationLib');
$this->_ci->kalendernotificationlib->sendMails($sync_data['mail_infos']);
}
return success(['synced' => $sync_data['synced']]);
}
public function sync()
{
$mail_infos_gesamt = [];
$synced_gesamt = 0;
$todelete_ids_result = $this->_getManuallySetStatus(array('to_delete', 'to_delete_live', 'to_delete_preview'));
if (isError($todelete_ids_result))
return $todelete_ids_result;
$todelete_result = $this->_syncKalenderIds(getData($todelete_ids_result), null);
if (isError($todelete_result))
return $todelete_result;
$todelete_data = getData($todelete_result);
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $todelete_data['mail_infos']);
$synced_gesamt += $todelete_data['synced'];
$preview_ids_result = $this->_getManuallySetStatus(array('sync_preview'));
if (isError($preview_ids_result))
return $preview_ids_result;
$preview_result = $this->_syncKalenderIds(getData($preview_ids_result), 'preview');
if (isError($preview_result))
return $preview_result;
$preview_data = getData($preview_result);
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $preview_data['mail_infos']);
$synced_gesamt += $preview_data['synced'];
$live_ids_result = $this->_getManuallySetStatus(array('sync_live'));
if (isError($live_ids_result))
return $live_ids_result;
$live_result = $this->_syncKalenderIds(getData($live_ids_result), 'live');
if (isError($live_result))
return $live_result;
$live_data = getData($live_result);
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $live_data['mail_infos']);
$synced_gesamt += $live_data['synced'];
if (!empty($mail_infos_gesamt))
{
$this->_ci->load->library('KalenderNotificationLib');
$this->_ci->kalendernotificationlib->sendMails($mail_infos_gesamt);
}
return success(['synced' => $synced_gesamt]);
}
private function _getManuallySetStatus($status_kurzbz_list)
{
if (empty($status_kurzbz_list))
return success([]);
$this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id');
$this->_ci->KalenderModel->db->where_in('status_kurzbz', $status_kurzbz_list);
$result = $this->_ci->KalenderModel->load();
if (isError($result))
return $result;
if (!hasData($result))
return success([]);
return success(array_column(getData($result), 'kalender_id'));
}
public function getKalenderIds($oe_kurzbz, $studiensemester_kurzbz, $status_kurzbz_list, $ausbildungssemester = null, $studienplan_id = null, $datum_bis = null)
{
if (empty($status_kurzbz_list))
return success([]);
$studiengang_result = $this->_getStudiengang($oe_kurzbz);
if (isError($studiengang_result))
return $studiengang_result;
$studiengang_kz = getData($studiengang_result);
if (!hasData($studiengang_result))
{
$organisationseinheiten = $this->_ci->OrganisationseinheitModel->getChilds($oe_kurzbz);
$oe_kurzbz = hasData($organisationseinheiten) ? array_column(getData($organisationseinheiten), 'oe_kurzbz') : [];
}
$this->_ci->KalenderModel->addDistinct('tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit', 'tbl_kalender.kalender_id = tbl_kalender_lehreinheit.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit', 'tbl_kalender_lehreinheit.lehreinheit_id = tbl_lehreinheit.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id');
if (!is_null($studiengang_kz))
{
$this->_ci->KalenderModel->db->where('tbl_lehrveranstaltung.studiengang_kz', $studiengang_kz);
}
else
{
$this->_ci->KalenderModel->db->where_in('tbl_lehrveranstaltung.oe_kurzbz', $oe_kurzbz);
}
$this->_ci->KalenderModel->db->where('tbl_lehreinheit.studiensemester_kurzbz', $studiensemester_kurzbz);
$this->_ci->KalenderModel->db->where_in('tbl_kalender.status_kurzbz', $status_kurzbz_list);
$this->_ci->KalenderModel->db->where('NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender nachfolger
WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id)', null, false);
if (!is_null($studienplan_id))
{
$this->_ci->KalenderModel->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_studienplan_lehrveranstaltung.lehrveranstaltung_id');
$this->_ci->KalenderModel->db->where('tbl_studienplan_lehrveranstaltung.studienplan_id', $studienplan_id);
}
if (!is_null($ausbildungssemester))
$this->_ci->KalenderModel->db->where('tbl_lehrveranstaltung.semester', $ausbildungssemester);
if (!is_null($datum_bis))
{
$end_date = date('Y-m-d', strtotime($datum_bis . ' +1 day'));
$this->_ci->KalenderModel->db->where('tbl_kalender.von <', $end_date);
}
$result = $this->_ci->KalenderModel->load();
if (isError($result))
return $result;
if (!hasData($result))
return success([]);
return success(array_column(getData($result), 'kalender_id'));
}
private function _archiveVorgaenger($vorgaenger_kalender_id, $stop_at_live = false)
{
$return_array = array();
if (!$vorgaenger_kalender_id) return success($return_array);
$current_id = $vorgaenger_kalender_id;
while ($current_id)
{
$vorgaenger = $this->_ci->KalenderModel->load(array('kalender_id' => $current_id));
if (!hasData($vorgaenger)) return success($return_array);
$vorgaenger = getData($vorgaenger)[0];
if ($stop_at_live && $vorgaenger->status_kurzbz === 'live')
return success($return_array);
if (in_array($vorgaenger->status_kurzbz, array('preview', 'live')))
{
$this->_ci->KalenderModel->update(
array('kalender_id' => $current_id),
array('status_kurzbz' => 'archived', 'status_kurzbz_max' => $vorgaenger->status_kurzbz)
);
$return_array[] = $vorgaenger;
}
$current_id = $vorgaenger->vorgaenger_kalender_id;
}
return success($return_array);
}
private function _syncKalenderIds($kalender_ids, $ziel_status)
{
if (empty($kalender_ids))
return success(['synced' => 0, 'mail_infos' => []]);
$this->_ci->KalenderModel->addSelect('tbl_kalender.*, tbl_kalender_ort.ort_kurzbz, tbl_kalender_ort.location');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id', 'LEFT');
$this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
$this->_ci->KalenderModel->addOrder('tbl_kalender.kalender_id', 'DESC');
$to_update = $this->_ci->KalenderModel->load();
if (isError($to_update))
return $to_update;
if (!hasData($to_update))
return success(['synced' => 0, 'mail_infos' => []]);
$mail_infos = [];
$synced = 0;
foreach (getData($to_update) as $entry)
{
if (in_array($entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview')))
{
$notify = array();
if ($entry->status_kurzbz === 'to_delete_live')
{
$status_max = 'live';
$notify = array('lektor', 'student');
}
else if ($entry->status_kurzbz === 'to_delete_preview')
{
$status_max = 'preview';
$notify = array('lektor');
}
else if ($entry->status_kurzbz === 'to_delete')
{
$status_max = 'planning';
}
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'deleted', 'status_kurzbz_max' => $status_max));
$mail_infos[] = array('entry' => $entry, 'new_status' => 'deleted', 'notify' => $notify);
$vorgaenger_array = $this->_archiveVorgaenger($entry->vorgaenger_kalender_id);
if (hasData($vorgaenger_array))
{
foreach(getData($vorgaenger_array) as $vorgaenger)
{
$archive_notify = array();
if ($vorgaenger->status_kurzbz === 'preview')
$archive_notify = array('lektor');
else if ($vorgaenger->status_kurzbz === 'live')
{
$archive_notify = array('student', 'lektor');
$history = $this->_ci->kalenderlib->getHistory($vorgaenger->kalender_id, false, false);
if (hasData($history))
{
$history = getData($history);
foreach ($history as $entry)
{
if ($entry->status_kurzbz === 'deleted' && $entry->status_kurzbz_max === 'preview')
{
$archive_notify = array('student');
break;
}
}
}
}
$mail_infos[] = array('entry' => $vorgaenger, 'new_status' => 'deleted', 'notify' => $archive_notify);
}
}
$synced++;
continue;
}
if ($ziel_status === 'preview' && in_array($entry->status_kurzbz, array('planning', 'sync_preview')))
{
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'preview'));
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, true);
$mail_infos[] = array('entry' => $entry, 'new_status' => 'preview', 'notify' => array('lektor'));
$synced++;
continue;
}
if ($ziel_status === 'live' && in_array($entry->status_kurzbz, array('planning', 'sync_preview', 'sync_live')))
{
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
$mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
$synced++;
continue;
}
if ($ziel_status === 'live' && $entry->status_kurzbz === 'preview')
{
$current = getData($this->_ci->KalenderModel->load(array('kalender_id' => $entry->kalender_id)))[0];
if ($current->status_kurzbz === 'archived')
continue;
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
$mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
$synced++;
}
}
return success(['synced' => $synced, 'mail_infos' => $mail_infos]);
}
private function _getStudiengang($oe_kurzbz)
{
$this->_ci->StudiengangModel->addJoin('tbl_organisationseinheit', 'oe_kurzbz');
$result = $this->_ci->StudiengangModel->loadWhere(array('oe_kurzbz' => $oe_kurzbz));
if (isError($result))
return $result;
if (!hasData($result))
return success(null);
return success(getData($result)[0]->studiengang_kz);
}
}
+178 -79
View File
@@ -17,7 +17,12 @@ class LektorLib
$this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$this->_ci->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->_ci->load->model('person/Benutzer_model', 'BenutzerModel');
$this->_ci->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
$this->_ci->load->model('ressource/Reservierung_model', 'ReservierungModel');
$this->_ci->load->model('ressource/stundenplandev_model', 'StundenplandevModel');
$this->_ci->load->library('PhrasesLib', array('lehre'));
$this->_ci->load->library('VariableLib', ['uid' => getAuthUID()]);
}
public function addLektorToLehreinheit($lehreinheit_id, $mitarbeiter_uid)
@@ -78,10 +83,13 @@ class LektorLib
public function updateLektorFromLehreinheit($lehreinheit_id, $mitarbeiter_uid, $new_data)
{
$old_uid = $mitarbeiter_uid;
$new_uid = isset($new_data['mitarbeiter_uid']) ? $new_data['mitarbeiter_uid'] : $mitarbeiter_uid;
$this->_ci->LehreinheitmitarbeiterModel->addSelect('lehre.tbl_lehreinheitmitarbeiter.*, lehre.tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.studiengang_kz');
$this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id');
$this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id');
$lehreinheit_result = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid));
$lehreinheit_result = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $old_uid));
if (isError($lehreinheit_result)) return $lehreinheit_result;
@@ -89,27 +97,47 @@ class LektorLib
$lehreinheit = getData($lehreinheit_result)[0];
$semesterstunden_alt = $lehreinheit->semesterstunden;
$semesterstunden_neu = isset($new_data['semesterstunden']) ? $new_data['semesterstunden'] : $semesterstunden_alt;
$bismelden_neu = isset($new_data['bismelden']) ? $new_data['bismelden'] : $lehreinheit->bismelden;
$neue_stunden_eingerechnet = (bool)$bismelden_neu;
$alte_stunden_eingerechnet = (bool)$lehreinheit->bismelden;
$stundenplan_update = false;
//TODO kollision check, wird vorerst nicht implementiert -> nur über das FAS möglich
if (isset($new_data['mitarbeiter_uid']) && $new_data['mitarbeiter_uid'] !== $mitarbeiter_uid)
if ($old_uid !== $new_uid)
{
$this->_ci->load->model('ressource/stundenplandev_model', 'StundenplandevModel');
$this->_ci->StundenplandevModel->addGroupBy('stundenplandev_id');
$this->_ci->StundenplandevModel->addGroupBy('mitarbeiter_uid');
$this->_ci->StundenplandevModel->addGroupBy('mitarbeiter_uid');
$verplant = $this->_ci->StundenplandevModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid));
if (hasData($verplant))
return error($this->_ci->phraseslib->t("lehre", "lektorbereitsverplant"));
$lehreinheit_data = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('mitarbeiter_uid' => $new_data['mitarbeiter_uid'], 'lehreinheit_id' => $lehreinheit_id));
$lehreinheit_data = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('mitarbeiter_uid' => $new_uid, 'lehreinheit_id' => $lehreinheit_id));
if (hasData($lehreinheit_data))
return error($this->_ci->phraseslib->t("lehre", "bereitzugeteilt"));
$this->_ci->StundenplandevModel->addGroupBy('stundenplandev_id');
$this->_ci->StundenplandevModel->addGroupBy('mitarbeiter_uid');
$verplant = $this->_ci->StundenplandevModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $old_uid));
if (hasData($verplant))
{
$kollision = $this->hasKollision(getData($verplant), $new_uid);
$ignore_kollision = $this->_ci->variablelib->getVar('ignore_kollision');
if ($kollision === false || $ignore_kollision == 'true')
{
$stundenplan_update = true;
}
else if (is_array($kollision))
{
return error( "Änderung fehlgeschlagen! Die Änderung des Lektors führt zu ".count($kollision)." Kollision(en) im LV-Plan. Deaktivieren Sie die Kollisionspruefung oder wenden Sie sich an die LV-Planung!\n zB. $kollision[0]");
}
else
{
return error($kollision);
}
}
}
$warning = '';
if (isset($new_data['semesterstunden']))
if (($semesterstunden_neu !== '' && $semesterstunden_alt !== '') && (($semesterstunden_neu > $semesterstunden_alt) || $neue_stunden_eingerechnet))
{
$studiengang_result = $this->_ci->StudiengangModel->loadWhere(array('studiengang_kz' => $lehreinheit->studiengang_kz));
if (isError($studiengang_result)) return $studiengang_result;
@@ -120,7 +148,7 @@ class LektorLib
if (isError($studiensemester_result)) return $studiensemester_result;
$studiensemester = getData($studiensemester_result)[0];
$echter_dv_result = $this->_ci->DienstverhaeltnisModel->existsDienstverhaeltnis($mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'echterdv');
$echter_dv_result = $this->_ci->DienstverhaeltnisModel->existsDienstverhaeltnis($new_uid, $studiensemester->start, $studiensemester->ende, 'echterdv');
$echter_dv = false;
@@ -129,83 +157,81 @@ class LektorLib
$echter_dv = true;
}
$neue_stunden_eingerechnet = isset($new_data['bismelden']) ? $new_data['bismelden'] : $lehreinheit->bismelden;
$alte_stunden_eingerechnet = $lehreinheit->bismelden;
$stundengrenze_result = $this->_ci->OrganisationseinheitModel->getStundengrenze($studiengang->oe_kurzbz, $echter_dv);
if (isError($stundengrenze_result)) return $stundengrenze_result;
if (($new_data['semesterstunden'] > $lehreinheit->semesterstunden) || $neue_stunden_eingerechnet)
$stundengrenze = getData($stundengrenze_result)[0];
$oe_result = $this->_ci->OrganisationseinheitModel->getChilds($stundengrenze->oe_kurzbz);
$oe_array = hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array();
$semesterstunden_alt_sql = is_null($semesterstunden_alt) ? 0 : $semesterstunden_alt;
$semesterstunden_neu_sql = is_null($semesterstunden_neu) ? 0 : $semesterstunden_neu;
if ($alte_stunden_eingerechnet && $neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) - ($semesterstunden_alt_sql) + {$this->_ci->LehreinheitmitarbeiterModel->db->escape($semesterstunden_neu_sql)}) as summe");
else if ($alte_stunden_eingerechnet && !$neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) - ($semesterstunden_alt_sql)) as summe");
else if (!$alte_stunden_eingerechnet && $neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) + ({$this->_ci->LehreinheitmitarbeiterModel->db->escape($semesterstunden_neu_sql)})) as summe");
else if (!$alte_stunden_eingerechnet && !$neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden)) as summe");
$this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id');
$this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id');
$this->_ci->LehreinheitmitarbeiterModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$this->_ci->LehreinheitmitarbeiterModel->db->where('mitarbeiter_uid', $new_uid);
$this->_ci->LehreinheitmitarbeiterModel->db->where('studiensemester_kurzbz', $lehreinheit->studiensemester_kurzbz);
$this->_ci->LehreinheitmitarbeiterModel->db->where('bismelden', true);
$this->_ci->LehreinheitmitarbeiterModel->db->where('lower(mitarbeiter_uid) NOT LIKE', '_dummy%');
if (count($oe_array) > 0)
{
$stundengrenze_result = $this->_ci->OrganisationseinheitModel->getStundengrenze($studiengang->oe_kurzbz, $echter_dv);
if (isError($stundengrenze_result)) return $stundengrenze_result;
$stundengrenze = getData($stundengrenze_result)[0];
$oe_result = $this->_ci->OrganisationseinheitModel->getChilds($stundengrenze->oe_kurzbz);
$oe_array = hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array('');
if ($alte_stunden_eingerechnet && $neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) - ($lehreinheit->semesterstunden) + {$this->_ci->LehreinheitmitarbeiterModel->db->escape($new_data['semesterstunden'])}) as summe");
else if ($alte_stunden_eingerechnet && !$neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) - ($lehreinheit->semesterstunden)) as summe");
else if (!$alte_stunden_eingerechnet && $neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) + ({$this->_ci->LehreinheitmitarbeiterModel->db->escape($new_data['semesterstunden'])})) as summe");
else if (!$alte_stunden_eingerechnet && !$neue_stunden_eingerechnet)
$this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden)) as summe");
$this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id');
$this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id');
$this->_ci->LehreinheitmitarbeiterModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$this->_ci->LehreinheitmitarbeiterModel->db->where('mitarbeiter_uid', (isset($new_data['mitarbeiter_uid']) ? $new_data['mitarbeiter_uid'] : $mitarbeiter_uid));
$this->_ci->LehreinheitmitarbeiterModel->db->where('studiensemester_kurzbz', $lehreinheit->studiensemester_kurzbz);
$this->_ci->LehreinheitmitarbeiterModel->db->where('bismelden', true);
$this->_ci->LehreinheitmitarbeiterModel->db->where('lower(mitarbeiter_uid) NOT LIKE', '_dummy%');
$this->_ci->LehreinheitmitarbeiterModel->db->where_in('tbl_studiengang.oe_kurzbz', $oe_array);
}
if(defined('FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE')
&& is_array(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE)
&& count(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE) > 0)
{
$this->_ci->LehreinheitmitarbeiterModel->db->where_not_in('tbl_studiengang.oe_kurzbz', FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE);
}
if(defined('FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE')
&& is_array(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE)
&& count(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE) > 0)
$summe_result = $this->_ci->LehreinheitmitarbeiterModel->load();
if (isError($summe_result)) return $summe_result;
if (!hasData($summe_result)) return error('Fehler beim Ermitteln der Gesamtstunden');
$summe = getData($summe_result)[0]->summe;
if ($summe > $stundengrenze->stunden)
{
if (!$echter_dv && (!$this->_ci->permissionlib->isBerechtigt('admin')))
{
$this->_ci->LehreinheitmitarbeiterModel->db->where_not_in('tbl_studiengang.oe_kurzbz', FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE);
if (!$this->LehrauftragAufFirma($new_uid))
return error("ACHTUNG: Die maximal erlaubte Semesterstundenanzahl des Lektors von $summe Stunden ($stundengrenze->stunden) wurde ueberschritten!\nDaten wurden NICHT gespeichert!\n\n");
}
else
{
$warning .= "ACHTUNG: Die maximal erlaubte Semesterstundenanzahl des Lektors von $summe Stunden ($stundengrenze->stunden) wurde ueberschritten!\nDaten wurden gespeichert!\n\n";
}
$summe_result = $this->_ci->LehreinheitmitarbeiterModel->load();
$stunden_limit_result = $this->getStundenInstitut($new_uid, $lehreinheit->studiensemester_kurzbz, $oe_array);
if (isError($summe_result)) return $summe_result;
if (!hasData($summe_result)) return error('Fehler beim Ermitteln der Gesamtstunden');
$summe = getData($summe_result)[0]->summe;
if ($summe > $stundengrenze->stunden)
if (hasData($stunden_limit_result))
{
if (!$echter_dv && (!$this->_ci->permissionlib->isBerechtigt('admin')))
$stunden_limit_array = getData($stunden_limit_result);
foreach ($stunden_limit_array as $stunden_limit)
{
if (!$this->LehrauftragAufFirma(isset($formData['mitarbeiter_uid']) ? $formData['mitarbeiter_uid'] : $mitarbeiter_uid))
return error("ACHTUNG: Die maximal erlaubte Semesterstundenanzahl des Lektors von $summe Stunden ($stundengrenze->stunden) wurde ueberschritten!\nDaten wurden NICHT gespeichert!\n\n");
}
else
{
$warning .= "ACHTUNG: Die maximal erlaubte Semesterstundenanzahl des Lektors von $summe Stunden ($stundengrenze->stunden) wurde ueberschritten!\nDaten wurden gespeichert!\n\n";
}
$stunden_limit_result = $this->getStundenInstitut($mitarbeiter_uid, $lehreinheit->studiensemester_kurzbz, $oe_array);
if (hasData($stunden_limit_result))
{
$stunden_limit_array = getData($stunden_limit_result);
foreach ($stunden_limit_array as $stunden_limit)
{
$warning .= $stunden_limit->summe . ' Stunden ' . $stunden_limit->bezeichnung . "\n";
}
$warning .= $stunden_limit->summe . ' Stunden ' . $stunden_limit->bezeichnung . "\n";
}
}
}
}
$benutzer_result = $this->_ci->BenutzerModel->load(array(isset($formData['mitarbeiter_uid']) ? $formData['mitarbeiter_uid'] : $mitarbeiter_uid));
$benutzer_result = $this->_ci->BenutzerModel->load(array($new_uid));
if (isError($benutzer_result)) return $benutzer_result;
@@ -227,12 +253,23 @@ class LektorLib
'bismelden'
);
$nullable_fields = array('stundensatz', 'semesterstunden', 'planstunden');
$updateData = array();
foreach ($updatableFields as $field)
{
$value = isset($new_data[$field]) ? $new_data[$field] : null;
if (!array_key_exists($field, $new_data))
{
continue;
}
if ($value !== null)
$value = $new_data[$field];
if (in_array($field, $nullable_fields))
{
$updateData[$field] = $value;
}
elseif ($value !== null)
{
$updateData[$field] = $value;
}
@@ -240,10 +277,24 @@ class LektorLib
$updateData['updatevon'] = getAuthUID();
$updateData['updateamum'] = date('Y-m-d H:i:s');
$result = $this->_ci->LehreinheitmitarbeiterModel->update(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid), $updateData);
$result = $this->_ci->LehreinheitmitarbeiterModel->update(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $old_uid), $updateData);
if (isError($result)) return $result;
if ($stundenplan_update)
{
$update_result = $this->_ci->StundenplandevModel->update([
'lehreinheit_id' => $lehreinheit_id,
'mitarbeiter_uid' => $old_uid,
], [
'mitarbeiter_uid' => $new_uid,
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => getAuthUID()
]);
if (isError($update_result)) return $update_result;
}
if ($warning !== '') return success(['warning' => $warning]);
return success('Erfolgreich geupdated');
@@ -347,4 +398,52 @@ class LektorLib
$this->_ci->LehreinheitmitarbeiterModel->addGroupBy('tbl_studiengang.bezeichnung');
return $this->_ci->LehreinheitmitarbeiterModel->load();
}
private function hasKollision($stunden, $mitarbeiter)
{
$kollision = array();
$ignore_zeitsperre = $this->_ci->variablelib->getVar('ignore_zeitsperre');
$ignore_reservierung = $this->_ci->variablelib->getVar('ignore_reservierung');
foreach ($stunden as $stunde)
{
$stundenplan_result = $this->_ci->StundenplandevModel->lektorHasStundenplandevEintrag($mitarbeiter, $stunde->datum, $stunde->stunde);
if (isError($stundenplan_result))
return $stundenplan_result;
if (hasData($stundenplan_result))
{
$stundenplan_result = getData($stundenplan_result)[0];
$kollision[] = "Kollision stundenplandev: $stundenplan_result->stundenplandev_id|$stundenplan_result->lektor|$stundenplan_result->ort_kurzbz|$stundenplan_result->stg_kurzbz-$stundenplan_result->semester$stundenplan_result->verband$stundenplan_result->gruppe$stundenplan_result->gruppe_kurzbz - $stundenplan_result->datum/$stundenplan_result->stunde";
}
else
{
if ($ignore_zeitsperre == 'false' && (!defined('KOLLISIONSFREIE_USER') || !in_array($mitarbeiter, unserialize(KOLLISIONSFREIE_USER))))
{
$zeitsperre_result = $this->_ci->ZeitsperreModel->checkIfZeitsperreExists($mitarbeiter, $stunde->datum, $stunde->stunde);
if (hasData($zeitsperre_result))
{
$zeitsperre_result = getData($zeitsperre_result)[0];
$kollision[] = "Kollision (Zeitsperre): $zeitsperre_result->zeitsperre_id|$zeitsperre_result->mitarbeiter_uid|$zeitsperre_result->zeitsperretyp_kurzbz - $zeitsperre_result->vondatum/$zeitsperre_result->vonstunde|$zeitsperre_result->bisdatum/$zeitsperre_result->bisstunde";
}
}
if ($ignore_reservierung == 'false' && (!defined('KOLLISIONSFREIE_USER') || !in_array($mitarbeiter, unserialize(KOLLISIONSFREIE_USER))))
{
$reservierung_result = $this->_ci->ReservierungModel->lektorHasReservierung($mitarbeiter, $stunde->datum, $stunde->stunde);
if (hasData($reservierung_result))
{
$reservierung_result = getData($reservierung_result)[0];
$kollision[] = "Kollision (Reservierung): $reservierung_result->reservierung_id|$reservierung_result->uid|$reservierung_result->ort_kurzbz|$reservierung_result->stg_kurzbz-$reservierung_result->semester$reservierung_result->verband$reservierung_result->gruppe$reservierung_result->gruppe_kurzbz - $reservierung_result->datum/$reservierung_result->stunde";
}
}
}
}
return isEmptyArray($kollision) ? false : $kollision;
}
}
+563
View File
@@ -0,0 +1,563 @@
<?php
if (! defined("BASEPATH")) exit("No direct script access allowed");
use CI3_Events as Events;
class RaumvorschlagLib
{
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
$this->_ci->load->model('ressource/Kalender_Lehreinheit_model', 'KalenderLehreinheitModel');
$this->_ci->load->model('ressource/Kalender_Event_model', 'KalenderEventModel');
$this->_ci->load->model('ressource/Kalender_Event_Teilnehmer_model', 'KalenderEventTeilnehmerModel');
$this->_ci->load->model('ressource/Kalender_Ort_model', 'KalenderOrtModel');
$this->_ci->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->_ci->load->model('education/LehreinheitMitarbeiter_model', 'LehreinheitMitarbeiterModel');
$this->_ci->load->model('ressource/Ort_model', 'OrtModel');
$this->_ci->load->model('organisation/gruppe_model', 'GruppeModel');
$this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
$this->_ci->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
$this->_ci->load->model('ressource/Stunde_model', 'StundeModel');
$this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel');
$this->_ci->load->library('CollisionChecker');
$this->_ci->load->library('KalenderLib');
$this->_ci->load->library('PhrasesLib', array('ui'));
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
}
public function getVorschlaege($kalender_id)
{
$event = $this->_ci->kalenderlib->getByKalenderId($kalender_id);
$event = $event[0];
return $this->_getVorschlaegeForEvent($event);
}
public function getVorschlaegeByLehreinheit($lehreinheit_id, $von, $bis)
{
$teilnehmer = $this->_getLehreinheitTeilnehmer($lehreinheit_id);
$event = (object) [
'kalender_id' => null,
'lehreinheit_id' => [$lehreinheit_id],
'isostart' => (new DateTime($von))->format('c'),
'isoend' => (new DateTime($bis))->format('c'),
'datum' => (new DateTime($von))->format('Y-m-d'),
'lektor' => $teilnehmer->lektor_data,
'gruppe' => $teilnehmer->gruppen_data,
];
return $this->_getVorschlaegeForEvent($event);
}
public function getVorschlaegeSlots($lehreinheit_id, $start_date, $end_date)
{
$lehreinheit_result = $this->_ci->LehreinheitModel->load($lehreinheit_id);
if (!hasData($lehreinheit_result))
return error('Lehreinheit nicht gefunden');
$lehreinheit = getData($lehreinheit_result)[0];
$block = $lehreinheit->stundenblockung;
if ($block <= 0)
return error('Stundenblockung ist ungültig');
$this->_ci->StundeModel->addOrder('stunde', 'ASC');
$stunden_result = $this->_ci->StundeModel->load();
$stunden = hasData($stunden_result) ? array_values(getData($stunden_result)) : [];
if (empty($stunden))
return error('Kein Stunden-Raster gefunden');
$teilnehmer = $this->_getLehreinheitTeilnehmer($lehreinheit_id);
$grp = $this->_splitGruppen($teilnehmer->gruppen_data);
$lektor_uids = array_column($teilnehmer->lektor_data, 'mitarbeiter_uid');
$verplante_events = $this->_ci->kalenderlib->getForRaumvorschlag(
$start_date,
$end_date,
$lektor_uids,
$grp->gruppen_kurzbz,
$grp->lehrverband_gruppen
);
$start_day = strtotime($start_date);
$end_day = strtotime($end_date);
$moegliche_slots = array();
$verplante_zeitsperren = $this->_getZeitsperen($start_date, $end_date, $lektor_uids);
while ($start_day <= $end_day)
{
$tag = date('Y-m-d', $start_day);
$verplante_tages_events = array_values(array_filter($verplante_events, function($event) use ($tag)
{
return $event->datum === $tag;
}));
foreach ($stunden as $index => $start_stunde)
{
if (!isset($stunden[$index + $block - 1]))
continue;
$end_stunde = $stunden[$index + $block - 1];
$slot_start = $tag . ' ' . $start_stunde->beginn;
$slot_end = $tag . ' ' . $end_stunde->ende;
if (!$this->_isFrei($slot_start, $slot_end, $verplante_zeitsperren, $lektor_uids, 'lektor'))
continue;
if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $lektor_uids, 'lektor'))
continue;
if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $grp->gruppen_kurzbz, 'gruppe'))
continue;
if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $grp->lehrverband_gruppen_bezeichnung, 'lehrverband'))
continue;
$moegliche_slots[] = [
'isostart' => (new DateTime($slot_start))->format('c'),
'isoend' => (new DateTime($slot_end))->format('c'),
'marker_isoend' => (new DateTime($tag . ' ' . $start_stunde->ende))->format('c'),
];
}
$start_day = strtotime('+1 day', $start_day);
}
$slots = [];
foreach ($moegliche_slots as $slot)
{
$event_obj = (object) [
'kalender_id' => null,
'lehreinheit_id' => [$lehreinheit_id],
'isostart' => $slot['isostart'],
'isoend' => $slot['isoend'],
];
$raumkandidaten = $this->_getRaumkandidaten($event_obj);
if (empty($raumkandidaten))
continue;
$ratings = $this->_getRatings($verplante_events, $slot, $raumkandidaten, $lektor_uids, $grp->gruppen_kurzbz, $grp->lehrverband_gruppen_bezeichnung);
$best = $ratings[0];
$anzahl_weitere = count($ratings) - 1;
$slots[] = [
'isostart' => $slot['isostart'],
'isoend' => $slot['isoend'],
'marker_isoend' => $slot['marker_isoend'],
'rating' => $this->_scoreToRating($best['score']),
'label' => $anzahl_weitere > 0 ? $best['ort_kurzbz'] . ' (' . $best['score'] . ') + ' . $anzahl_weitere . ' weitere' : $best['ort_kurzbz'] . ' (' . $best['score'] . ')',
'raeume' => $ratings,
];
}
return success($slots);
}
private function _getZeitsperen($start_date, $end_date, $uids)
{
if (empty($uids)) return [];
if (($this->_ci->variablelib->getVar('ignore_kollision') === 'true') || ($this->_ci->variablelib->getVar('ignore_zeitsperre') === 'true')) return [];
$this->_ci->ZeitsperreModel->addSelect('mitarbeiter_uid, vondatum, vonstunde_z.beginn as von_beginn, bisdatum, bisstunde_z.ende as bis_ende');
$this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde vonstunde_z', 'vonstunde_z.stunde = tbl_zeitsperre.vonstunde', 'LEFT');
$this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde bisstunde_z', 'bisstunde_z.stunde = tbl_zeitsperre.bisstunde', 'LEFT');
$this->_ci->ZeitsperreModel->db->where('zeitsperretyp_kurzbz !=', 'ZVerfueg');
$this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.vondatum + COALESCE(vonstunde_z.beginn, \'00:00\'))::timestamp <', $end_date);
$this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.bisdatum + COALESCE(bisstunde_z.ende, \'23:59\'))::timestamp >', $start_date);
$this->_ci->ZeitsperreModel->db->where_in('mitarbeiter_uid', $uids);
$result = $this->_ci->ZeitsperreModel->load();
if (!hasData($result)) return [];
$events = [];
foreach (getData($result) as $row)
{
$von = new DateTime($row->vondatum . ' ' . ($row->von_beginn ?? '00:00'));
$bis = new DateTime($row->bisdatum . ' ' . ($row->bis_ende ?? '23:59'));
$events[] = (object)[
'isostart' => $von->format('c'),
'isoend' => $bis->format('c'),
'lektor' => [['mitarbeiter_uid' => $row->mitarbeiter_uid]]
];
}
return $events;
}
private function _getLehreinheitTeilnehmer($lehreinheit_id)
{
$lektoren_result = $this->_ci->LehreinheitMitarbeiterModel->loadWhere(['lehreinheit_id' => $lehreinheit_id]);
$lektor_data = [];
if (hasData($lektoren_result))
{
$lektor_data = getData($lektoren_result);
}
$gruppen_result = $this->_ci->LehreinheitgruppeModel->getByLehreinheit($lehreinheit_id);
$gruppen_data = [];
if (hasData($gruppen_result))
{
$gruppen_rows = getData($gruppen_result);
foreach ($gruppen_rows as $gruppe)
{
$gruppen_data[] = (array) $gruppe;
}
}
return (object)[
'lektor_data' => $lektor_data,
'gruppen_data' => $gruppen_data,
];
}
private function _splitGruppen($gruppen_data)
{
$gruppen_kurzbz = array_values(array_filter(array_column($gruppen_data, 'gruppe_kurzbz')));
$lehrverband_gruppen = array_values(array_filter($gruppen_data, function($gruppe)
{
return empty($gruppe['gruppe_kurzbz']);
}));
$lehrverband_gruppen_bezeichnung = array_column($lehrverband_gruppen, 'bezeichnung');
return (object)[
'gruppen_kurzbz' => $gruppen_kurzbz,
'lehrverband_gruppen' => $lehrverband_gruppen,
'lehrverband_gruppen_bezeichnung' => $lehrverband_gruppen_bezeichnung
];
}
//TODO (david) umbauen auf CollisionChecks
private function _isFrei($slot_start, $slot_end, $events, $check_array, $type)
{
if (empty($check_array)) return true;
$slot_start_ts = strtotime($slot_start);
$slot_end_ts = strtotime($slot_end);
foreach ($events as $event)
{
$event_start_ts = strtotime($event->isostart);
$event_end_ts = strtotime($event->isoend);
if ($event_end_ts <= $slot_start_ts || $event_start_ts >= $slot_end_ts)
continue;
$event_uids = $this->_getIds($event, $type);
if (!empty(array_intersect($event_uids, $check_array)))
return false;
}
return true;
}
private function _scoreToRating($score)
{
if ($score >= 90)
return 'good';
if ($score >= 60)
return 'mid';
return 'bad';
}
private function _getVorschlaegeForEvent($event)
{
$raumkandidaten = $this->_getRaumkandidaten($event);
if (empty($raumkandidaten)) return [];
$lektor_uids = array_column($event->lektor, 'mitarbeiter_uid');
$grp = $this->_splitGruppen($event->gruppe);
$tages_events = $this->_ci->kalenderlib->getForRaumvorschlag(
$event->datum,
$event->datum,
$lektor_uids,
$grp->gruppen_kurzbz,
$grp->lehrverband_gruppen
);
return $this->_getRatings($tages_events, $event, $raumkandidaten, $lektor_uids, $grp->gruppen_kurzbz, $grp->lehrverband_gruppen_bezeichnung);
}
private function _getRatings($events, $event, $raumkandidaten, $lektor_uids, $gruppen_kurzbz, $lehrverband_gruppen_bezeichnung)
{
$event = (object)$event;
$lektor_davor = $this->_getEventDavor($events, $event->isostart, $lektor_uids, 'lektor');
$gruppen_davor = $this->_getEventDavor($events, $event->isostart, $gruppen_kurzbz, 'gruppe');
$lehrverband_davor = $this->_getEventDavor($events, $event->isostart, $lehrverband_gruppen_bezeichnung, 'lehrverband');
$lektor_davor_ort = $lektor_davor ? $this->_getOrtDetails($lektor_davor->ort_kurzbz) : null;
$gruppen_davor_ort = $gruppen_davor ? $this->_getOrtDetails($gruppen_davor->ort_kurzbz) : null;
$lehrverband_davor_ort = $lehrverband_davor ? $this->_getOrtDetails($lehrverband_davor->ort_kurzbz) : null;
$unique = [];
foreach ($raumkandidaten as $raum)
{
$unique[$raum->ort_kurzbz] = $raum;
}
$kandidaten = array_values($unique);
$ratings = [];
foreach ($kandidaten as $raum)
{
$rating = ['ort_kurzbz' => $raum->ort_kurzbz, 'score' => 100, 'details' => [],
'raumtyp_kurzbz' => $raum->raumtyp_kurzbz, 'max_person' => $raum->max_person];
$this->_rateLektor($rating, $raum, $lektor_davor_ort);
$this->_rateGruppen($rating, $raum, $gruppen_davor_ort);
$this->_rateGruppen($rating, $raum, $lehrverband_davor_ort);
Events::trigger('room_rating',
function & () use (&$rating) {
return $rating;
},
$raum,
$event
);
$ratings[] = $rating;
}
usort($ratings, function($a, $b)
{
return $b['score'] <=> $a['score'];
});
return $ratings;
}
private function _getOrtDetails($ort_kurzbz_array)
{
$ort_kurzbz_array = (array) $ort_kurzbz_array;
if (empty($ort_kurzbz_array)) return [];
$this->_ci->OrtModel->addSelect('ort_kurzbz, stockwerk, standort_id');
$this->_ci->OrtModel->db->where_in('ort_kurzbz', $ort_kurzbz_array);
$result = $this->_ci->OrtModel->load();
return hasData($result) ? getData($result) : [];
}
private function _rateLektor(&$rating, $raum, $lektor_davor_orte)
{
if (empty($lektor_davor_orte)) return;
foreach ($lektor_davor_orte as $ort)
{
if ($ort->ort_kurzbz === $raum->ort_kurzbz)
{
$rating['score'] += 20;
$rating['details'][] = '+20 ' . $this->_ci->phraseslib->t('ui', 'lecturer_already_here');
return;
}
}
$gleiches_gebaeude = array_filter($lektor_davor_orte, function($ort) use ($raum)
{
return $ort->standort_id === $raum->standort_id;
});
if (empty($gleiches_gebaeude))
{
$rating['score'] -= 20;
$rating['details'][] = '-20 '. $this->_ci->phraseslib->t('ui', 'lecturer_building_change');
return;
}
$diffs = array_map(function($ort) use ($raum)
{
return abs($ort->stockwerk - $raum->stockwerk);
}, $gleiches_gebaeude);
$diff = min($diffs);
if ($diff > 0)
{
$rating['score'] -= $diff * 5;
$rating['details'][] = '-' . ($diff * 5) . ' ' . $this->_ci->phraseslib->t('ui', 'lecturer_floor_change');
}
}
private function _rateGruppen(&$rating, $raum, $gruppen_davor_orte)
{
if (empty($gruppen_davor_orte)) return;
foreach ($gruppen_davor_orte as $ort)
{
if ($ort->ort_kurzbz === $raum->ort_kurzbz)
{
$rating['score'] += 10;
$rating['details'][] = '+10 ' . $this->_ci->phraseslib->t('ui', 'student_already_here');
return;
}
}
$gleiches_gebaeude = array_filter($gruppen_davor_orte, function($ort) use ($raum)
{
return $ort->standort_id === $raum->standort_id;
});
if (empty($gleiches_gebaeude))
{
$rating['score'] -= 20;
$rating['details'][] = '-20 '. $this->_ci->phraseslib->t('ui', 'student_building_change');
return;
}
$diffs = array_map(function($ort) use ($raum)
{
return abs($ort->stockwerk - $raum->stockwerk);
}, $gleiches_gebaeude);
$diff = min($diffs);
if ($diff > 0)
{
$rating['score'] -= $diff * 5;
$rating['details'][] = '-' . ($diff * 5) . ' '. $this->_ci->phraseslib->t('ui', 'student_floor_change');
}
}
private function _getEventDavor($events, $von, $uids, $type)
{
$kandidat = null;
foreach ($events as $event)
{
if ($event->isoend > $von)
continue;
//Wenn zwischen zwei Events eine 30+ Minuten Pause liegt, wird das Event davor nicht berücksichtigt
if ((strtotime($von) - strtotime($event->isoend)) > 30 * 60)
continue;
if (empty($event->ort_kurzbz))
continue;
$event_uids = $this->_getIds($event, $type);
if (empty(array_intersect($event_uids, $uids)))
continue;
if ($kandidat === null || $event->isoend > $kandidat->isoend)
$kandidat = $event;
}
return $kandidat;
}
private function _getIds($event, $type)
{
$event_uids = array();
if ($type === 'lektor')
$event_uids = array_column($event->lektor, 'mitarbeiter_uid');
else if ($type === 'gruppe')
$event_uids = array_column($event->gruppe, 'gruppe_kurzbz');
else if ($type === 'lehrverband')
$event_uids = array_column($event->gruppe, 'bezeichnung');
return $event_uids;
}
private function _getRaumkandidaten($event)
{
$raumtyp = null;
$raumtypalternativ = null;
if (!empty($event->lehreinheit_id))
{
$lehreinheit = $this->_ci->LehreinheitModel->load($event->lehreinheit_id[0]);
if (hasData($lehreinheit))
{
$lehreinheit = getData($lehreinheit)[0];
$raumtyp = $lehreinheit->raumtyp ?? null;
$raumtypalternativ = $lehreinheit->raumtypalternativ ?? null;
}
}
$this->_ci->KalenderModel->addDistinct('tbl_kalender_ort.ort_kurzbz');
$this->_ci->KalenderModel->addSelect('tbl_kalender_ort.ort_kurzbz');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id');
$this->_ci->KalenderModel->db->where('tbl_kalender.von <', $event->isoend);
$this->_ci->KalenderModel->db->where('tbl_kalender.bis >', $event->isostart);
if (!is_null($event->kalender_id))
{
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $event->kalender_id);
}
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['deleted', 'to_delete', 'to_delete_live', 'to_delete_preview', 'archived']);
$this->_ci->KalenderModel->db->where('tbl_kalender_ort.ort_kurzbz IS NOT NULL', null, false);
$this->_ci->KalenderModel->db->where(
'NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender nachfolger
WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id
)', null, false
);
$belegte = $this->_ci->KalenderModel->load();
$belegte_orte = hasData($belegte) ? array_column(getData($belegte), 'ort_kurzbz') : [];
if (empty($raumtyp))
{
$raeume = $this->_getFreieRaeume(null, $belegte_orte);
return hasData($raeume) ? getData($raeume) : [];
}
$vorschlaege = [];
$raeume = $this->_getFreieRaeume($raumtyp, $belegte_orte);
if (hasData($raeume))
$vorschlaege = getData($raeume);
if (count($vorschlaege) < 5 && !empty($raumtypalternativ))
{
$bereits_gefunden = array_merge($belegte_orte, array_column($vorschlaege, 'ort_kurzbz'));
$alternativ = $this->_getFreieRaeume($raumtypalternativ, $bereits_gefunden);
if (!isError($alternativ) && hasData($alternativ))
$vorschlaege = array_merge($vorschlaege, getData($alternativ));
}
return $vorschlaege;
}
private function _getFreieRaeume($raumtyp, $belegte_orte)
{
$this->_ci->OrtModel->addSelect('ort_kurzbz, stockwerk, standort_id, max_person, raumtyp_kurzbz');
$this->_ci->OrtModel->addJoin('public.tbl_ortraumtyp', 'ort_kurzbz');
if (!empty($raumtyp))
$this->_ci->OrtModel->db->where('raumtyp_kurzbz', $raumtyp);
else
$this->_ci->OrtModel->db->where('reservieren', true);
$this->_ci->OrtModel->db->where('aktiv', true);
$this->_ci->OrtModel->db->where("ort_kurzbz NOT LIKE '\_%'", null, false);
if (!empty($belegte_orte))
$this->_ci->OrtModel->db->where_not_in('ort_kurzbz', $belegte_orte);
$this->_ci->OrtModel->addOrder('hierarchie, ort_kurzbz');
return $this->_ci->OrtModel->load();
}
}
+22 -3
View File
@@ -80,10 +80,12 @@ class StundenplanLib
if (isError($semester_range))
return $semester_range;
$semester_range = getData($semester_range);
$this->_ci->addMeta('semester_range', $semester_range);
$this->sortStudienSemester($semester_range);
$function_error = $this->applyLoadUeberSemesterHaelfte($semester_range);
$this->_ci->addMeta('nach_apply_semester_range', $semester_range);
if ($function_error)
return $function_error;
@@ -92,13 +94,13 @@ class StundenplanLib
if (isError($benutzer_gruppen))
return $benutzer_gruppen;
$benutzer_gruppen = getData($benutzer_gruppen);
$this->_ci->addMeta('spezialgruppen', $benutzer_gruppen);
// getting the student_lehrverbaende of the student in the different studiensemester
$student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($student_uid, $semester_range);
if (isError($student_lehrverband))
return $student_lehrverband;
$student_lehrverband = getData($student_lehrverband);
$this->_ci->addMeta('studentlehrvebaende', $student_lehrverband);
$stundenplan_query = $this->_ci->StundenplanModel->getStundenplanQuery(
$start,
$end,
@@ -184,6 +186,21 @@ class StundenplanLib
return success($stundenplan_data);
}
public function getEventsByLE($lehreinheit_id, $start, $end, $stundenplan)
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel');
return $this->_ci->StundenplanModel->getStundenplanLE($lehreinheit_id, $start, $end, $stundenplan);
}
public function getEventsByLV($lehrveranstaltung_id, $start, $end, $stundenplan)
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel');
return $this->_ci->StundenplanModel->getStundenplanLV($lehrveranstaltung_id, $start, $end, $stundenplan);
}
/**
* Get stundenplan for a room
*
@@ -615,6 +632,7 @@ class StundenplanLib
$result->semester = $item->semester;
$result->verband = $item->verband;
$result->gruppe = $item->gruppe;
$result->studiensemester_kurzbz = $item->studiensemester_kurzbz;
return $result;
},
$lehrverband_query_result);
@@ -784,7 +802,8 @@ class StundenplanLib
$this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
// gets all studiensemester from the student from start_date to end_date
$semester_range = $this->_ci->StudiensemesterModel->getByDateRange($start_date, $end_date);
//$semester_range = $this->_ci->StudiensemesterModel->getByDateRange($start_date, $end_date);
$semester_range = $this->_ci->StudiensemesterModel->getContainingOrNearestByDateRange($start_date, $end_date);
if (isError($semester_range))
return $semester_range;
+392
View File
@@ -0,0 +1,392 @@
<?php
/**
* FH-Complete
*
* @package FHC-Helper
* @author FHC-Team
* @copyright Copyright (c) 2026 fhcomplete.net
* @license GPLv3
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
use \stdClass as stdClass;
class TagLib
{
/**
* Object initialization
*/
public function __construct()
{
$this->_ci =& get_instance();
// Configs
$this->_ci->load->config('stv');
// Models
$this->_ci->load->model('person/Notiz_model', 'NotizModel');
$this->_ci->load->model('system/Notiztyp_model', 'NotiztypModel');
$this->_ci->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
$this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
$this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
// Libraries
$this->_ci->load->library('PermissionLib');
$this->_ci->load->library('PrestudentLib');
$this->batchUser = $this->_ci->config->item('userAutomatedTags');
}
public function updateAutomatedTags($paramsTag)
{
// ---------------------------------
// check params
// ---------------------------------
$required = ['kurzbz', 'data', 'typeId'];
foreach ($required as $key) {
if (!isset($paramsTag[$key])) {
return error('Missing Parameter: ' . $key);
}
}
$studiensemester_kurzbz = (isset ($paramsTag['studiensemester_kurzbz']) ? $paramsTag['studiensemester_kurzbz'] : null);
$tag = $paramsTag['kurzbz'];
$inputData = $paramsTag['data'];
$typeId = $paramsTag['typeId'];
// ---------------------------------
// prepare input
// ---------------------------------
$zeitraum = [];
$arrayIds = [];
foreach ($inputData as $item) {
$id = $item['id'];
$arrayIds[] = $id;
$zeitraum[$id] = [
'von' => $item['von'] ?? null,
'bis' => $item['bis'] ?? null
];
}
$arrayIds = array_unique($arrayIds);
$result = $this->_ci->StudiensemesterModel->load($studiensemester_kurzbz);
if (isError($result)) {
return $result;
}
$data = $result->retval[0] ?? null;
$von = $data->start ?? null;
$bis = $data->ende ?? null;
// ---------------------------------
// load existing tags
// ---------------------------------
$allTags = [];
$resultAllTags = $this->_ci->NotizModel->getAllTags($tag, $von, $bis);
if (isError($resultAllTags)) {
return $resultAllTags;
}
$allTagsData = getData($resultAllTags);
if (!empty($allTagsData)) {
foreach ($allTagsData as $item) {
$allTags[$item->$typeId] = $item->notiz_id;
}
}
// ---------------------------------
// map the data
// ---------------------------------
$toRecycle = [];
$toAdd = [];
$toDelete = [];
foreach ($arrayIds as $id) {
if (isset($allTags[$id])) {
$toRecycle[$id] = $allTags[$id];
} else {
$toAdd[] = $id;
}
}
foreach ($allTags as $id => $notizId) {
if (!in_array($id, $arrayIds)) {
$toDelete[$id] = $notizId;
}
}
// ---------------------------------
// recycle (update existing)
// ---------------------------------
$countRecycled = 0;
$retagged = [];
foreach ($toRecycle as $id => $notizId)
{
$this->_updateTag($notizId, $zeitraum[$id]['von'], $zeitraum[$id]['bis']);
$countRecycled++;
$retagged[] = $id;
}
// ---------------------------------
// ADD
// ---------------------------------
$countAdded = 0;
$tagged = [];
foreach ($toAdd as $id)
{
$this->_insertTag($typeId, $id, $tag, $zeitraum[$id]['von'], $zeitraum[$id]['bis']);
$countAdded++;
$tagged[] = $id;
}
// ---------------------------------
// delete
// ---------------------------------
$countDeleted = 0;
$deleted = [];
foreach ($toDelete as $id => $notizId)
{
$result = $this->_deleteTag($notizId);
if (isError($result)) {
return $result;
}
$countDeleted++;
$deleted[] = $id;
}
// ---------------------------------
// return
// ---------------------------------
return success([
'input' => [
'tag' => $tag,
'arrayIds' => $arrayIds
],
'summary' => [
'recycled' => $countRecycled,
'added' => $countAdded,
'deleted' => $countDeleted
],
'details' => [
'existingTags' => $allTags,
'toAdd' => $toAdd,
'toRecycle' => $toRecycle,
'toDelete' => $toDelete
],
'results' => [
'retaggedIds' => $retagged,
'newTags' => $tagged,
'deletedTagsIds' => $deleted
]
]);
}
public function updateAutomatedTagsForTypeId(array $params)
{
$return = null;
$notiz_id = null;
$von = $params['von'];
$bis = $params['bis'];
$tag = $params['kurzbz'];
$id = $params['id'];
$typeId = $params['typeId'];
$this->_ci->NotizModel->addSelect('nz.notiz_id');
$this->_ci->NotizModel->addSelect($typeId);
$this->_ci->NotizModel->addJoin('public.tbl_notizzuordnung nz', 'notiz_id');
$resultAllTags = $this->_ci->NotizModel->loadWhere([
'typ' => $tag,
$typeId => $id
]);
if(hasData($resultAllTags))
{
$notiz_id = $resultAllTags->retval[0]->notiz_id;
}
//RECYCLE
if ($notiz_id !== null)
{
$resultUpdateNotiz = $this->_updateTag($notiz_id, $von, $bis);
$return = ['recycled' => $resultUpdateNotiz];
}
else
//ADD
{
$resultInsertNotiz = $this->_insertTag($typeId, $id, $tag, $von, $bis);
$return = ['added' => $resultInsertNotiz];
}
return success($return);
}
/*
* main function for rebuild Tags for typeId
* */
public function rebuildTagsForTypeId($typeId, $id, $studiensemester_kurzbz)
{
$automatedTagsRes = $this->_ci->NotiztypModel->loadWhere(array('automatisiert' => true, 'taglib IS NOT NULL' => null));
$automatedTags = hasData($automatedTagsRes) ? getData($automatedTagsRes) : [];
$result = $this->_ci->StudiensemesterModel->load($studiensemester_kurzbz);
if (isError($result))
return error('Error occurred during retrieving studiensemester');
if (empty($result->retval) || !isset($result->retval[0])) {
return error('No studiensemester found');
}
$startSem = $result->retval[0]->start ?? null;
$endeSem = $result->retval[0]->ende ?? null;
$return = [];
foreach ($automatedTags as $autoTag)
{
// getPath: must not be lost
$filePath = APPPATH . 'libraries/' . $autoTag->taglib . '.php'; // APPPATH = application/
if (file_exists($filePath)) {
require_once($filePath);
} else {
echo "File not found: " . $filePath;
continue;
}
$className = basename($autoTag->taglib);
$kurz_bz = $autoTag->typ_kurzbz;
$obj = new $className();
$criteriaIsSet = $obj->isCriteriaSetFor([
'typeId' => $typeId,
'id' => $id,
'studiensemester_kurzbz' => $studiensemester_kurzbz
]);
if (hasData($criteriaIsSet))
{
$von = isset($criteriaIsSet->retval[0]->von) ? $criteriaIsSet->retval[0]->von : '';
$bis = isset($criteriaIsSet->retval[0]->bis) ? $criteriaIsSet->retval[0]->bis : '';
$params = [
'von' => $von,
'bis' => $bis,
'kurzbz' => $autoTag->typ_kurzbz,
'typeId' => $typeId,
'id' => $id,
];
$result = $this->updateAutomatedTagsForTypeId($params);
if (isError($result))
return error('Error occurred during updateAutomatedTags' . $kurz_bz);
$return[$kurz_bz] = $result;
}
else
{
//CHECK FOR DELETE
$params = [
'von' => $startSem,
'bis' => $endeSem,
'kurzbz' => $autoTag->typ_kurzbz,
'typeId' => $typeId,
'id' => $id,
];
$result = $this->_ci->NotizModel->checkIfExistingTag($kurz_bz, $typeId, $id, $startSem, $endeSem);
if (hasData($result))
{
$notizId = $result->retval[0]->notiz_id;
$this->_deleteTag($notizId);
$return[$kurz_bz] = ['deleted' => $notizId];
}
}
}
return success($return);
}
private function _insertTag($typeId, $id, $tag, $von, $bis)
{
$resultInsert = $this->_ci->NotizModel->insert([
'titel' => 'TAG',
'text' => 'AUTOMATED TAG',
'verfasser_uid' => $this->batchUser,
'erledigt' => false,
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => 'BatchJobTagAdd',
'typ' => $tag,
'start' => $von,
'ende' => $bis
]);
if (isError($resultInsert)) {
return error('Error inserting tag for ' . $typeId . ': ' . $id);
}
$notizId = $resultInsert->retval;
$resultZuordnung = $this->_ci->NotizzuordnungModel->insert([
'notiz_id' => $notizId,
$typeId => $id
]);
if (isError($resultZuordnung)) {
return error('Error inserting relation for ' . $typeId . ': ' . $id);
}
return $notizId;
}
private function _updateTag($notiz_id, $von, $bis)
{
$resultUpdateNotiz = $this->_ci->NotizModel->update(
[
'notiz_id' => $notiz_id
],
array(
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => 'BatchJobTagUpdate',
'start' => $von,
'ende' => $bis
));
if (isError($resultUpdateNotiz))
return error ('Error occurred during Update ' . $notiz_id);
return $notiz_id;
}
private function _deleteTag($notiz_id)
{
$result = $this->_ci->NotizzuordnungModel->delete([
'notiz_id' => $notiz_id
]);
if (isError($result)) {
return error('Error occurred during delete Notizzuordnung ' . $notiz_id);
}
$result = $this->_ci->NotizModel->delete([
'notiz_id' => $notiz_id
]);
if (isError($result)) {
return error('Error occurred during delete Notiz ' . $notiz_id);
}
return success([
'deleted' => $notiz_id
]);
}
}
@@ -0,0 +1,303 @@
<?php
class LectureCollisionCheck implements ICollisionCheck
{
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
$this->_ci->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
$this->_ci->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
$this->_ci->load->library('PhrasesLib', array('ui'));
}
public function getName()
{
return 'lecture';
}
public function check($data)
{
if (!isset($data->von, $data->bis)) return [];
if (empty($data->kalender_id) && empty($data->lehreinheit_id) && empty($data->uids)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
if (!empty($data->kalender_id))
$uids = $this->_getUids($data->kalender_id);
else if (!empty($data->lehreinheit_id))
$uids = $this->_getUidsFromLehreinheit($data->lehreinheit_id);
else
$uids = $data->uids;
if (empty($uids)) return [];
$collisions = [];
$collisions = array_merge($collisions, $this->_checkLehreinheit($uids, $data));
$collisions = array_merge($collisions, $this->_checkReservierung($uids, $data));
$collisions = array_merge($collisions, $this->_checkZeitsperre($uids, $data));
return $collisions;
}
public function checkAll($kalender_ids)
{
if (empty($kalender_ids)) return [];
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$grouped = [];
$this->_ci->KalenderModel->addSelect('DISTINCT ON (tbl_kalender.kalender_id) tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit current_kalender_le', 'current_kalender_le.kalender_id = tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit current_lehreinheit', 'current_lehreinheit.lehreinheit_id = current_kalender_le.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter current_lehreinheit_ma', 'current_lehreinheit_ma.lehreinheit_id = current_lehreinheit.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter other_lehreinheithreinheit_ma', 'other_lehreinheithreinheit_ma.mitarbeiter_uid = current_lehreinheit_ma.mitarbeiter_uid');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit other_lehreinheit', 'other_lehreinheit.lehreinheit_id = other_lehreinheithreinheit_ma.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit other_kalender_le', 'other_kalender_le.lehreinheit_id = other_lehreinheit.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender other_kalender', 'other_kalender.kalender_id = other_kalender_le.kalender_id');
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
$this->_ci->KalenderModel->db->group_start();
$where_ids_chunks = array_chunk($kalender_ids,25);
foreach($where_ids_chunks as $where_ids)
{
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
}
$this->_ci->KalenderModel->db->group_end();
$this->_ci->KalenderModel->db->where(
'other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
null, false
);
$result = $this->_ci->KalenderModel->load();
if (!isError($result) && hasData($result))
{
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = true;
}
}
$this->_ci->KalenderModel->addSelect('DISTINCT ON (tbl_kalender.kalender_id) tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit current_kalender_le', 'current_kalender_le.kalender_id = tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit current_lehreinheit', 'current_lehreinheit.lehreinheit_id = current_kalender_le.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter current_lehreinheit_ma', 'current_lehreinheit_ma.lehreinheit_id = current_lehreinheit.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event_teilnehmer other_t', 'other_t.uid = current_lehreinheit_ma.mitarbeiter_uid');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event other_e', 'other_e.kalender_id = other_t.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender other_kalender', 'other_kalender.kalender_id = other_e.kalender_id');
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
$this->_ci->KalenderModel->db->group_start();
$where_ids_chunks = array_chunk($kalender_ids,25);
foreach($where_ids_chunks as $where_ids)
{
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
}
$this->_ci->KalenderModel->db->group_end();
$this->_ci->KalenderModel->db->where(
'other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
null, false
);
$result = $this->_ci->KalenderModel->load();
if (!isError($result) && hasData($result))
{
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = true;
}
}
$this->_ci->KalenderModel->addSelect('DISTINCT ON (tbl_kalender.kalender_id) tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit current_kalender_le', 'current_kalender_le.kalender_id = tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit current_lehreinheit', 'current_lehreinheit.lehreinheit_id = current_kalender_le.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter current_lehreinheit_ma', 'current_lehreinheit_ma.lehreinheit_id = current_lehreinheit.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('campus.tbl_zeitsperre z',
"z.mitarbeiter_uid = current_lehreinheit_ma.mitarbeiter_uid
AND z.zeitsperretyp_kurzbz != 'ZVerfueg'");
$this->_ci->KalenderModel->addJoin('lehre.tbl_stunde vonstunde_z', 'vonstunde_z.stunde = z.vonstunde', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_stunde bisstunde_z', 'bisstunde_z.stunde = z.bisstunde', 'LEFT');
$this->_ci->KalenderModel->db->where('(z.vondatum + COALESCE(vonstunde_z.beginn, \'00:00\'))::timestamp < tbl_kalender.bis', null, false);
$this->_ci->KalenderModel->db->where('(z.bisdatum + COALESCE(bisstunde_z.ende, \'23:59\'))::timestamp > tbl_kalender.von', null, false);
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
$this->_ci->KalenderModel->db->group_start();
$where_ids_chunks = array_chunk($kalender_ids,25);
foreach($where_ids_chunks as $where_ids)
{
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
}
$this->_ci->KalenderModel->db->group_end();
$result = $this->_ci->KalenderModel->load();
if (!isError($result) && hasData($result))
{
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = true;
}
}
return $grouped;
}
private function _getUids($kalender_id)
{
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$this->_ci->KalenderModel->addDistinct('mitarbeiter_uid, tbl_kalender_event_teilnehmer.uid');
$this->_ci->KalenderModel->addSelect('mitarbeiter_uid, tbl_kalender_event_teilnehmer.uid');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit', 'kalender_id', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter', 'lehreinheit_id', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event', 'kalender_id', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event_teilnehmer', 'tbl_kalender_event.kalender_id = tbl_kalender_event_teilnehmer.kalender_id', 'LEFT');
$this->_ci->KalenderModel->db->group_start();
$this->_ci->KalenderModel->db->where_not_in('mitarbeiter_uid', $kollisionsfreie_user);
$this->_ci->KalenderModel->db->or_where('mitarbeiter_uid IS NULL', null, false);
$this->_ci->KalenderModel->db->group_end();
$result = $this->_ci->KalenderModel->loadWhere(array(
'tbl_kalender.kalender_id' => $kalender_id
));
if (isError($result) || !hasData($result)) return [];
$data = getData($result);
$mitarbeiter_uids = array_filter(array_column($data, 'mitarbeiter_uid'));
$event_teilnehmer = array_filter(array_column($data, 'uid'));
return array_unique(array_merge($mitarbeiter_uids, $event_teilnehmer));
}
private function _getUidsFromLehreinheit($lehreinheit_id)
{
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$result = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id));
if (isError($result) || !hasData($result)) return [];
$uids = array_column(getData($result), 'mitarbeiter_uid');
$uids = array_diff(array_filter($uids), $kollisionsfreie_user);
return array_values(array_unique($uids));
}
private function _checkLehreinheit($uids, $data)
{
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$this->_ci->KalenderModel->addDistinct('mitarbeiter_uid, tbl_kalender.von, tbl_kalender.bis');
$this->_ci->KalenderModel->addSelect('mitarbeiter_uid, tbl_kalender.von, tbl_kalender.bis');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit', 'kalender_id', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter', 'lehreinheit_id', 'LEFT');
$this->_ci->KalenderModel->db->where_in('mitarbeiter_uid', $uids);
if (!empty($data->kalender_id))
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_not_in('mitarbeiter_uid', $kollisionsfreie_user);
$this->_ci->KalenderModel->db->where(
'tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
null, false
);
$result = $this->_ci->KalenderModel->loadWhere(array(
'von <' => $data->bis,
'bis >' => $data->von,
));
if (isError($result) || !hasData($result)) return [];
return array_map(function($row)
{
return [
'message' => $this->_ci->phraseslib->t('ui', 'ma_le_kollision') . ': ' . $row->mitarbeiter_uid . ' (' . date('d.m.Y H:i', strtotime($row->von)) . ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')',
'errorCode' => 'lector_collision',
];
}, getData($result));
}
private function _checkReservierung($uids, $data)
{
if ($this->_ci->variablelib->getVar('ignore_reservierung') === 'true') return [];
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$this->_ci->KalenderModel->addDistinct('tbl_kalender_event_teilnehmer.uid, tbl_kalender.von, tbl_kalender.bis');
$this->_ci->KalenderModel->addSelect('tbl_kalender_event_teilnehmer.uid, tbl_kalender.von, tbl_kalender.bis');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event', 'kalender_id', 'LEFT');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event_teilnehmer', 'tbl_kalender_event.kalender_id = tbl_kalender_event_teilnehmer.kalender_id', 'LEFT');
$this->_ci->KalenderModel->db->where_in('tbl_kalender_event_teilnehmer.uid', $uids);
if (!empty($data->kalender_id))
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_not_in('uid', $kollisionsfreie_user);
$this->_ci->KalenderModel->db->where(
'tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
null, false
);
$result = $this->_ci->KalenderModel->loadWhere(array(
'von <' => $data->bis,
'bis >' => $data->von,
));
if (isError($result) || !hasData($result)) return [];
return array_map(function($row)
{
return [
'message' => $this->_ci->phraseslib->t('ui', 'reservierung_kollision') . ': ' . $row->uid . ' (' . date('d.m.Y H:i', strtotime($row->von)) . ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')',
'errorCode' => 'reservation_collision',
];
}, getData($result));
}
private function _checkZeitsperre($uids, $data)
{
if ($this->_ci->variablelib->getVar('ignore_zeitsperre') === 'true') return [];
$this->_ci->ZeitsperreModel->addSelect('mitarbeiter_uid, vondatum, vonstunde_z.beginn as von_beginn, bisdatum, bisstunde_z.ende as bis_ende');
$this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde vonstunde_z', 'vonstunde_z.stunde = tbl_zeitsperre.vonstunde', 'LEFT');
$this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde bisstunde_z', 'bisstunde_z.stunde = tbl_zeitsperre.bisstunde', 'LEFT');
$this->_ci->ZeitsperreModel->db->where('zeitsperretyp_kurzbz !=', 'ZVerfueg');
$this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.vondatum + COALESCE(vonstunde_z.beginn, \'00:00\'))::timestamp <', $data->bis);
$this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.bisdatum + COALESCE(bisstunde_z.ende, \'23:59\'))::timestamp >', $data->von);
$this->_ci->ZeitsperreModel->db->where_in('mitarbeiter_uid', $uids);
$result = $this->_ci->ZeitsperreModel->load();
if (isError($result) || !hasData($result)) return [];
return array_map(function($row)
{
return [
'message' => $this->_ci->phraseslib->t('ui', 'ma_zeitsperre_kollision') . ': ' . $row->mitarbeiter_uid . ' (' . date('d.m.Y H:i', strtotime($row->vondatum . ' ' . $row->von_beginn)) . ' - ' . date('d.m.Y H:i', strtotime($row->bisdatum . ' ' . $row->bis_ende)) . ')',
'errorCode' => 'absences_collision',
];
}, getData($result));
}
}
@@ -0,0 +1,94 @@
<?php
class ResourcesCollisionCheck implements ICollisionCheck
{
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
$this->_ci->load->library('PhrasesLib', array('ui'));
}
public function getName()
{
return 'resources';
}
public function check($data)
{
if (!isset($data->betriebsmittel_ids, $data->von, $data->bis)) return [];
if (empty($data->betriebsmittel_ids)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
if ($this->_ci->variablelib->getVar('ignore_resources_collisions') === 'true') return [];
$this->_ci->KalenderModel->addSelect('kalender_id, von, bis, bm.beschreibung AS betriebsmittel_beschreibung');
$this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender bk', 'bk.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_kalender_gruppen_id');
$this->_ci->KalenderModel->addJoin('wawi.tbl_betriebsmittel bm', 'bm.betriebsmittel_id = bk.betriebsmittel_id');
if (!empty($data->kalender_id))
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
$this->_ci->KalenderModel->db->where_in('bk.betriebsmittel_id', $data->betriebsmittel_ids);
$result = $this->_ci->KalenderModel->loadWhere(array(
'von <' => $data->bis,
'bis >' => $data->von,
));
if (isError($result)) return [];
if (!hasData($result)) return [];
return array_map(function($row)
{
return [
'errorCode' => 'resource_collision',
'message' => $this->_ci->phraseslib->t('ui', 'resource_collision') . ': ' . $row->betriebsmittel_beschreibung . ' (' . date('d.m.Y H:i', strtotime($row->von)) . ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')'
];
}, getData($result));
}
public function checkAll($kalender_ids)
{
if (empty($kalender_ids)) return [];
$this->_ci->KalenderModel->addSelect('DISTINCT ON (tbl_kalender.kalender_id) tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender current_bk', 'current_bk.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_kalender_gruppen_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender other_bk', 'other_bk.betriebsmittel_id = current_bk.betriebsmittel_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender other_kalender', 'other_kalender.eindeutige_kalender_gruppen_id = other_bk.eindeutige_kalender_gruppen_id');
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
$this->_ci->KalenderModel->db->group_start();
$where_ids_chunks = array_chunk($kalender_ids,25);
foreach($where_ids_chunks as $where_ids)
{
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
}
$this->_ci->KalenderModel->db->group_end();
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
$result = $this->_ci->KalenderModel->load();
if (isError($result) || !hasData($result)) return [];
$grouped = [];
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = true;
}
return $grouped;
}
}
@@ -0,0 +1,90 @@
<?php
class RoomCollisionCheck implements ICollisionCheck
{
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
$this->_ci->load->library('PhrasesLib', array('ui'));
}
public function getName()
{
return 'room';
}
public function check($data)
{
if (!isset($data->ort_kurzbz, $data->von, $data->bis) || isEmptyArray($data->ort_kurzbz)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
$this->_ci->KalenderModel->addSelect('kalender_id, ort_kurzbz, von, bis');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'kalender_id');
if (!empty($data->kalender_id))
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_in('ort_kurzbz', $data->ort_kurzbz);
$result = $this->_ci->KalenderModel->loadWhere(array(
'von <' => $data->bis,
'bis >' => $data->von,
));
if (isError($result)) return [];
if (!hasData($result)) return [];
return array_map(function($row)
{
return [
'errorCode' => 'room_collision',
'message' => $this->_ci->phraseslib->t('ui', 'raum_kollision') . ': ' . $row->ort_kurzbz . ' (' . date('d.m.Y H:i', strtotime($row->von)) . ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')'
];
}, getData($result));
}
public function checkAll($kalender_ids)
{
if (empty($kalender_ids)) return [];
$this->_ci->KalenderModel->addSelect('DISTINCT ON (tbl_kalender.kalender_id) tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort current_ort', 'current_ort.kalender_id = tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort other_ort', 'other_ort.ort_kurzbz = current_ort.ort_kurzbz');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender other_kalender', 'other_kalender.kalender_id = other_ort.kalender_id');
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->group_start();
$where_ids_chunks = array_chunk($kalender_ids,25);
foreach($where_ids_chunks as $where_ids)
{
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
}
$this->_ci->KalenderModel->db->group_end();
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
$result = $this->_ci->KalenderModel->load();
if (isError($result) || !hasData($result)) return [];
$grouped = [];
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = true;
}
return $grouped;
}
}
@@ -0,0 +1,286 @@
<?php
class StudentCollisionCheck implements ICollisionCheck
{
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
$this->_ci->load->library('PhrasesLib', array('ui'));
}
public function getName()
{
return 'student';
}
public function check($data)
{
if (!isset($data->von, $data->bis)) return [];
if (!isset($data->kalender_id) && !isset($data->lehreinheit_id)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
if ($this->_ci->variablelib->getVar('kollision_student') !== 'true') return [];
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$placeholders = implode(',', array_fill(0, count($kollisionsfreie_user), '?'));
$dbModel = new DB_Model();
if (isset($data->kalender_id))
{
$qry1 = "
SELECT DISTINCT tbl_benutzergruppe.uid
FROM lehre.tbl_kalender
JOIN lehre.tbl_kalender_lehreinheit USING(kalender_id)
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
JOIN public.tbl_gruppe
ON tbl_gruppe.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND tbl_gruppe.semester = tbl_lehreinheitgruppe.semester
AND tbl_gruppe.gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz
JOIN public.tbl_benutzergruppe ON tbl_benutzergruppe.gruppe_kurzbz = tbl_gruppe.gruppe_kurzbz
AND tbl_benutzergruppe.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
WHERE tbl_kalender.kalender_id = ?
AND tbl_benutzergruppe.uid NOT IN ($placeholders)
UNION ALL
SELECT DISTINCT tbl_studentlehrverband.student_uid AS uid
FROM lehre.tbl_kalender
JOIN lehre.tbl_kalender_lehreinheit USING(kalender_id)
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
JOIN public.tbl_studentlehrverband
ON tbl_studentlehrverband.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND tbl_studentlehrverband.semester = tbl_lehreinheitgruppe.semester
AND tbl_studentlehrverband.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
AND (tbl_lehreinheitgruppe.verband = tbl_studentlehrverband.verband OR tbl_lehreinheitgruppe.verband IS NULL OR btrim(tbl_lehreinheitgruppe.verband::text) = '' OR tbl_studentlehrverband.verband IS NULL)
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
WHERE tbl_kalender.kalender_id = ?
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
";
$qry_1_param = $data->kalender_id;
}
else
{
$qry1 = "
SELECT DISTINCT tbl_benutzergruppe.uid
FROM lehre.tbl_lehreinheit
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
JOIN public.tbl_gruppe
ON tbl_gruppe.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND tbl_gruppe.semester = tbl_lehreinheitgruppe.semester
AND tbl_gruppe.gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz
JOIN public.tbl_benutzergruppe ON tbl_benutzergruppe.gruppe_kurzbz = tbl_gruppe.gruppe_kurzbz
AND tbl_benutzergruppe.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
WHERE tbl_lehreinheit.lehreinheit_id = ?
AND tbl_benutzergruppe.uid NOT IN ($placeholders)
UNION ALL
SELECT DISTINCT tbl_studentlehrverband.student_uid AS uid
FROM lehre.tbl_lehreinheit
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
JOIN public.tbl_studentlehrverband
ON tbl_studentlehrverband.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND tbl_studentlehrverband.semester = tbl_lehreinheitgruppe.semester
AND tbl_studentlehrverband.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
AND (tbl_lehreinheitgruppe.verband = tbl_studentlehrverband.verband OR tbl_lehreinheitgruppe.verband IS NULL OR btrim(tbl_lehreinheitgruppe.verband::text) = '' OR tbl_studentlehrverband.verband IS NULL)
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
WHERE tbl_lehreinheit.lehreinheit_id = ?
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
";
$qry_1_param = $data->lehreinheit_id;
}
$result1 = $dbModel->execReadOnlyQuery($qry1, array_merge(
[$qry_1_param],
$kollisionsfreie_user,
[$qry_1_param],
$kollisionsfreie_user
));
if (isError($result1) || !hasData($result1)) return [];
$curUids = array_flip(array_column(getData($result1), 'uid'));
$exclude_kalender = isset($data->kalender_id) ? "AND tbl_kalender.kalender_id != ?" : "";
$exclude_kalender_param = isset($data->kalender_id) ? [$data->kalender_id] : [];
$qry2 = "
SELECT DISTINCT tbl_kalender.kalender_id, tbl_kalender.von, tbl_kalender.bis, tbl_benutzergruppe.uid
FROM lehre.tbl_kalender
JOIN lehre.tbl_kalender_lehreinheit ON tbl_kalender_lehreinheit.kalender_id = tbl_kalender.kalender_id
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
JOIN public.tbl_gruppe
ON tbl_gruppe.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND tbl_gruppe.semester = tbl_lehreinheitgruppe.semester
AND tbl_gruppe.gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz
JOIN public.tbl_benutzergruppe ON tbl_benutzergruppe.gruppe_kurzbz = tbl_gruppe.gruppe_kurzbz
AND tbl_benutzergruppe.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
WHERE tbl_kalender.von < ?
AND tbl_kalender.bis > ?
$exclude_kalender
AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND tbl_benutzergruppe.uid NOT IN ($placeholders)
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
WHERE vorgaenger.vorgaenger_kalender_id = tbl_kalender.kalender_id
)
UNION ALL
SELECT DISTINCT tbl_kalender.kalender_id, tbl_kalender.von, tbl_kalender.bis, tbl_studentlehrverband.student_uid AS uid
FROM lehre.tbl_kalender
JOIN lehre.tbl_kalender_lehreinheit ON tbl_kalender_lehreinheit.kalender_id = tbl_kalender.kalender_id
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
JOIN public.tbl_studentlehrverband
ON tbl_studentlehrverband.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND tbl_studentlehrverband.semester = tbl_lehreinheitgruppe.semester
AND tbl_studentlehrverband.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
AND (tbl_lehreinheitgruppe.verband = tbl_studentlehrverband.verband OR tbl_lehreinheitgruppe.verband IS NULL OR btrim(tbl_lehreinheitgruppe.verband::text) = '' OR tbl_studentlehrverband.verband IS NULL)
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
WHERE tbl_kalender.von < ?
AND tbl_kalender.bis > ?
$exclude_kalender
AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
WHERE vorgaenger.vorgaenger_kalender_id = tbl_kalender.kalender_id
)
";
$result2 = $dbModel->execReadOnlyQuery($qry2, array_merge(
[$data->bis, $data->von], $exclude_kalender_param, $kollisionsfreie_user,
[$data->bis, $data->von], $exclude_kalender_param, $kollisionsfreie_user
));
if (isError($result2) || !hasData($result2)) return [];
$conflicts = [];
foreach (getData($result2) as $row)
{
if (isset($curUids[$row->uid]))
{
$conflicts[] = [
'message' =>
$this->_ci->phraseslib->t('ui', 'student_kollision')
. ': ' . $row->uid
. ' (' . date('d.m.Y H:i', strtotime($row->von))
. ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')',
'errorCode' => 'student_collision'
];
}
}
return $conflicts;
}
public function checkAll($kalender_ids)
{
if (empty($kalender_ids)) return [];
if ($this->_ci->variablelib->getVar('kollision_student') !== 'true') return [];
$dbModel = new DB_Model();
$placeholders = implode(',', array_fill(0, count($kalender_ids), '?'));
$sql = "
SELECT DISTINCT current_kalender.kalender_id, current_benutzergruppe.uid
FROM lehre.tbl_kalender current_kalender
JOIN lehre.tbl_kalender_lehreinheit current_kalender_le ON current_kalender_le.kalender_id = current_kalender.kalender_id
JOIN lehre.tbl_lehreinheit current_lehreinheit ON current_lehreinheit.lehreinheit_id = current_kalender_le.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe current_lehreinheitgruppe ON current_lehreinheitgruppe.lehreinheit_id = current_lehreinheit.lehreinheit_id
JOIN public.tbl_gruppe current_gruppe
ON current_gruppe.studiengang_kz = current_lehreinheitgruppe.studiengang_kz
AND current_gruppe.semester = current_lehreinheitgruppe.semester
AND current_gruppe.gruppe_kurzbz = current_lehreinheitgruppe.gruppe_kurzbz
JOIN public.tbl_benutzergruppe current_benutzergruppe ON current_benutzergruppe.gruppe_kurzbz = current_gruppe.gruppe_kurzbz
AND current_benutzergruppe.studiensemester_kurzbz = current_lehreinheit.studiensemester_kurzbz
JOIN lehre.tbl_kalender other_kalender
ON other_kalender.kalender_id != current_kalender.kalender_id
AND other_kalender.von < current_kalender.bis
AND other_kalender.bis > current_kalender.von
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
WHERE vorgaenger.vorgaenger_kalender_id = other_kalender.kalender_id
)
JOIN lehre.tbl_kalender_lehreinheit other_kalender_le ON other_kalender_le.kalender_id = other_kalender.kalender_id
JOIN lehre.tbl_lehreinheit other_lehreinheit ON other_lehreinheit.lehreinheit_id = other_kalender_le.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe other_lehreinheitgruppe ON other_lehreinheitgruppe.lehreinheit_id = other_lehreinheit.lehreinheit_id
JOIN public.tbl_gruppe other_gruppe
ON other_gruppe.studiengang_kz = other_lehreinheitgruppe.studiengang_kz
AND other_gruppe.semester = other_lehreinheitgruppe.semester
AND other_gruppe.gruppe_kurzbz = other_lehreinheitgruppe.gruppe_kurzbz
JOIN public.tbl_benutzergruppe other_benutzergruppe
ON other_benutzergruppe.gruppe_kurzbz = other_gruppe.gruppe_kurzbz
AND other_benutzergruppe.uid = current_benutzergruppe.uid
AND other_benutzergruppe.studiensemester_kurzbz = other_lehreinheit.studiensemester_kurzbz
WHERE current_kalender.kalender_id IN ($placeholders)
UNION ALL
SELECT DISTINCT current_kalender.kalender_id, current_studentlehrverband.student_uid AS uid
FROM lehre.tbl_kalender current_kalender
JOIN lehre.tbl_kalender_lehreinheit current_kalender_le ON current_kalender_le.kalender_id = current_kalender.kalender_id
JOIN lehre.tbl_lehreinheit current_lehreinheit ON current_lehreinheit.lehreinheit_id = current_kalender_le.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe current_lehreinheitgruppe ON current_lehreinheitgruppe.lehreinheit_id = current_lehreinheit.lehreinheit_id
JOIN public.tbl_studentlehrverband current_studentlehrverband
ON current_studentlehrverband.studiengang_kz = current_lehreinheitgruppe.studiengang_kz
AND current_studentlehrverband.semester = current_lehreinheitgruppe.semester
AND current_studentlehrverband.studiensemester_kurzbz = current_lehreinheit.studiensemester_kurzbz
AND (current_lehreinheitgruppe.verband = current_studentlehrverband.verband OR current_lehreinheitgruppe.verband IS NULL OR btrim(current_lehreinheitgruppe.verband::text) = '' OR current_studentlehrverband.verband IS NULL)
AND (current_lehreinheitgruppe.gruppe = current_studentlehrverband.gruppe OR current_lehreinheitgruppe.gruppe IS NULL OR btrim(current_lehreinheitgruppe.gruppe::text) = '' OR current_studentlehrverband.gruppe IS NULL)
JOIN lehre.tbl_kalender other_kalender
ON other_kalender.kalender_id != current_kalender.kalender_id
AND other_kalender.von < current_kalender.bis
AND other_kalender.bis > current_kalender.von
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
WHERE vorgaenger.vorgaenger_kalender_id = other_kalender.kalender_id
)
JOIN lehre.tbl_kalender_lehreinheit other_kalender_le ON other_kalender_le.kalender_id = other_kalender.kalender_id
JOIN lehre.tbl_lehreinheit other_lehreinheit ON other_lehreinheit.lehreinheit_id = other_kalender_le.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe other_lehreinheitgruppe ON other_lehreinheitgruppe.lehreinheit_id = other_lehreinheit.lehreinheit_id
JOIN public.tbl_studentlehrverband other_slv
ON other_slv.studiengang_kz = other_lehreinheitgruppe.studiengang_kz
AND other_slv.semester = other_lehreinheitgruppe.semester
AND other_slv.studiensemester_kurzbz = other_lehreinheit.studiensemester_kurzbz
AND other_slv.student_uid = current_studentlehrverband.student_uid
AND (other_lehreinheitgruppe.verband = other_slv.verband OR other_lehreinheitgruppe.verband IS NULL OR btrim(other_lehreinheitgruppe.verband::text) = '' OR other_slv.verband IS NULL)
AND (other_lehreinheitgruppe.gruppe = other_slv.gruppe OR other_lehreinheitgruppe.gruppe IS NULL OR btrim(other_lehreinheitgruppe.gruppe::text) = '' OR other_slv.gruppe IS NULL)
WHERE current_kalender.kalender_id IN ($placeholders)
";
$result = $dbModel->execReadOnlyQuery($sql, array_merge($kalender_ids, $kalender_ids));
if (isError($result) || !hasData($result)) return [];
$grouped = [];
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = true;
}
return $grouped;
}
}
@@ -0,0 +1,413 @@
<?php
class VerbandCollisionCheck implements ICollisionCheck
{
private $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
$this->_ci->load->library('PhrasesLib', array('ui'));
}
public function getName()
{
return 'verband';
}
public function check($data)
{
if (!isset($data->von, $data->bis)) return [];
if (!isset($data->kalender_id) && !isset($data->lehreinheit_id)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
$kollision_student = $this->_ci->variablelib->getVar('kollision_student') === 'false';
$kollision_reservierung = $this->_ci->variablelib->getVar('ignore_reservierung') === 'false';
if (!isset($data->kalender_id)) $kollision_reservierung = false;
if (!$kollision_student && !$kollision_reservierung) return [];
$dbModel = new DB_Model();
$collisions = [];
$group_matching_qry = "
(
(
current_lehreinheitguppe.gruppe_kurzbz IS NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
AND (
current_lehreinheitguppe.verband IS NULL
OR (
current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
)
)
)
OR
(
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND current_gruppe.direktinskription IS NOT TRUE
AND other_gruppe.direktinskription IS NOT TRUE
)
OR
(
(
current_lehreinheitguppe.gruppe_kurzbz IS NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND other_gruppe.direktinskription IS NOT TRUE
)
OR
(
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
AND current_gruppe.direktinskription IS NOT TRUE
)
)
)
";
if ($kollision_student)
{
$union_event = "";
if ($kollision_reservierung)
{
$union_event = "
UNION
SELECT tbl_kalender_event_teilnehmer.studiengang_kz, tbl_kalender_event_teilnehmer.semester, tbl_kalender_event_teilnehmer.verband, tbl_kalender_event_teilnehmer.gruppe, tbl_kalender_event_teilnehmer.gruppe_kurzbz, tbl_kalender_event_teilnehmer.kalender_id
FROM lehre.tbl_kalender_event_teilnehmer
WHERE tbl_kalender_event_teilnehmer.rolle_kurzbz = 'teilnehmer'
";
}
$other_lehreinheitgruppe_subquery = "
SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
FROM lehre.tbl_kalender_lehreinheit
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
". $union_event ."
";
if (isset($data->kalender_id))
{
$sql_gruppen = "
SELECT
other_kalender.von,
other_kalender.bis,
COALESCE(
other_lehreinheitguppe.gruppe_kurzbz,
UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
COALESCE(other_lehreinheitguppe.verband::text, '') ||
COALESCE(other_lehreinheitguppe.gruppe::text, '')
) AS gruppenname
FROM lehre.tbl_kalender current_kalender
JOIN (
". $other_lehreinheitgruppe_subquery ."
) current_lehreinheitguppe ON current_lehreinheitguppe.kalender_id = current_kalender.kalender_id
LEFT JOIN public.tbl_gruppe current_gruppe
ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
JOIN lehre.tbl_kalender other_kalender
ON other_kalender.kalender_id != current_kalender.kalender_id
AND other_kalender.von < ?
AND other_kalender.bis > ?
JOIN (
". $other_lehreinheitgruppe_subquery ."
) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
LEFT JOIN public.tbl_gruppe other_gruppe
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
LEFT JOIN public.tbl_studiengang stg
ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
WHERE current_kalender.kalender_id = ?
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
AND ". $group_matching_qry ."
AND other_kalender.kalender_id NOT IN (
SELECT vorgaenger_kalender_id
FROM lehre.tbl_kalender
WHERE vorgaenger_kalender_id IS NOT NULL
)
";
$params = [$data->bis, $data->von, $data->kalender_id];
}
else
{
$sql_gruppen = "
SELECT
other_kalender.von,
other_kalender.bis,
COALESCE(
other_lehreinheitguppe.gruppe_kurzbz,
UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
COALESCE(other_lehreinheitguppe.verband::text, '') ||
COALESCE(other_lehreinheitguppe.gruppe::text, '')
) AS gruppenname
FROM lehre.tbl_lehreinheitgruppe current_lehreinheitguppe
LEFT JOIN public.tbl_gruppe current_gruppe
ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
JOIN lehre.tbl_kalender other_kalender
ON other_kalender.von < ?
AND other_kalender.bis > ?
JOIN (
". $other_lehreinheitgruppe_subquery ."
) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
LEFT JOIN public.tbl_gruppe other_gruppe
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
LEFT JOIN public.tbl_studiengang stg
ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
WHERE current_lehreinheitguppe.lehreinheit_id = ?
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
AND ". $group_matching_qry ."
AND other_kalender.kalender_id NOT IN (
SELECT vorgaenger_kalender_id
FROM lehre.tbl_kalender
WHERE vorgaenger_kalender_id IS NOT NULL
)
";
$params = [$data->bis, $data->von, $data->lehreinheit_id];
}
$result = $dbModel->execReadOnlyQuery($sql_gruppen, $params);
if (!isError($result) && hasData($result))
{
foreach (getData($result) as $row)
{
$collisions[] = [
'message' => $this->_ci->phraseslib->t('ui', 'verband_kollision') . ': ' . $row->gruppenname . ' (' . date('d.m.Y H:i', strtotime($row->von)) . ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')',
'errorCode' => 'verband_collision',
];
}
}
}
if ($kollision_reservierung && !$kollision_student)
{
$sql_reservierung = "
SELECT
other_kalender.von,
other_kalender.bis,
COALESCE(
other_event_teilnehmer.gruppe_kurzbz,
UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_event_teilnehmer.semester ||
COALESCE(other_event_teilnehmer.verband::text, '') ||
COALESCE(other_event_teilnehmer.gruppe::text, '')
) AS gruppenname
FROM lehre.tbl_kalender_event_teilnehmer current_event_teilnehmer
LEFT JOIN public.tbl_gruppe current_gruppe
ON current_gruppe.gruppe_kurzbz = current_event_teilnehmer.gruppe_kurzbz
JOIN lehre.tbl_kalender other_kalender
ON other_kalender.kalender_id != ?
AND other_kalender.von < ?
AND other_kalender.bis > ?
JOIN lehre.tbl_kalender_event_teilnehmer other_event_teilnehmer
ON other_event_teilnehmer.kalender_id = other_kalender.kalender_id
AND other_event_teilnehmer.rolle_kurzbz = 'teilnehmer'
LEFT JOIN public.tbl_gruppe other_gruppe
ON other_gruppe.gruppe_kurzbz = other_event_teilnehmer.gruppe_kurzbz
LEFT JOIN public.tbl_studiengang stg
ON stg.studiengang_kz = other_event_teilnehmer.studiengang_kz
WHERE current_event_teilnehmer.kalender_id = ?
AND current_event_teilnehmer.rolle_kurzbz = 'teilnehmer'
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND current_event_teilnehmer.studiengang_kz = other_event_teilnehmer.studiengang_kz
AND current_event_teilnehmer.semester = other_event_teilnehmer.semester
AND (
(
current_event_teilnehmer.gruppe_kurzbz IS NULL
AND other_event_teilnehmer.gruppe_kurzbz IS NULL
AND (
current_event_teilnehmer.verband IS NULL
OR (
current_event_teilnehmer.verband = other_event_teilnehmer.verband
AND (current_event_teilnehmer.gruppe IS NULL OR other_event_teilnehmer.gruppe IS NULL OR current_event_teilnehmer.gruppe = other_event_teilnehmer.gruppe)
)
)
)
OR
(
current_event_teilnehmer.gruppe_kurzbz IS NOT NULL
AND other_event_teilnehmer.gruppe_kurzbz IS NOT NULL
AND current_gruppe.direktinskription IS NOT TRUE
AND other_gruppe.direktinskription IS NOT TRUE
)
OR
(
(
current_event_teilnehmer.gruppe_kurzbz IS NULL
AND other_event_teilnehmer.gruppe_kurzbz IS NOT NULL
AND other_gruppe.direktinskription IS NOT TRUE
)
OR
(
current_event_teilnehmer.gruppe_kurzbz IS NOT NULL
AND other_event_teilnehmer.gruppe_kurzbz IS NULL
AND current_gruppe.direktinskription IS NOT TRUE
)
)
)
AND other_kalender.kalender_id NOT IN (
SELECT vorgaenger_kalender_id
FROM lehre.tbl_kalender
WHERE vorgaenger_kalender_id IS NOT NULL
)
";
$result = $dbModel->execReadOnlyQuery($sql_reservierung, [
$data->kalender_id,
$data->bis,
$data->von,
$data->kalender_id,
]);
if (!isError($result) && hasData($result))
{
foreach (getData($result) as $row)
{
$collisions[] = [
'errorCode' => 'reservation_collision',
'message' => $this->_ci->phraseslib->t('ui', 'reservierung_kollision') . ': ' . $row->gruppenname . ' (' . date('d.m.Y H:i', strtotime($row->von)) . ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')'
];
}
}
}
return $collisions;
}
public function checkAll($kalender_ids)
{
if (empty($kalender_ids)) return [];
$dbModel = new DB_Model();
$placeholders = implode(',', array_fill(0, count($kalender_ids), '?'));
$sql = "
SELECT DISTINCT ON (current_kalender.kalender_id) current_kalender.kalender_id
FROM lehre.tbl_kalender current_kalender
JOIN (
SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
FROM lehre.tbl_kalender_lehreinheit
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
UNION
SELECT tbl_kalender_event_teilnehmer.studiengang_kz, tbl_kalender_event_teilnehmer.semester, tbl_kalender_event_teilnehmer.verband, tbl_kalender_event_teilnehmer.gruppe,
tbl_kalender_event_teilnehmer.gruppe_kurzbz, tbl_kalender_event_teilnehmer.kalender_id
FROM lehre.tbl_kalender_event_teilnehmer
) current_lehreinheitguppe ON current_lehreinheitguppe.kalender_id = current_kalender.kalender_id
LEFT JOIN public.tbl_gruppe current_gruppe
ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
JOIN lehre.tbl_kalender other_kalender
ON other_kalender.kalender_id != current_kalender.kalender_id
AND other_kalender.von < current_kalender.bis
AND other_kalender.bis > current_kalender.von
JOIN (
SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
FROM lehre.tbl_kalender_lehreinheit
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
UNION
SELECT tbl_kalender_event_teilnehmer.studiengang_kz, tbl_kalender_event_teilnehmer.semester, tbl_kalender_event_teilnehmer.verband, tbl_kalender_event_teilnehmer.gruppe,
tbl_kalender_event_teilnehmer.gruppe_kurzbz, tbl_kalender_event_teilnehmer.kalender_id
FROM lehre.tbl_kalender_event_teilnehmer
) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
LEFT JOIN public.tbl_gruppe other_gruppe
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
WHERE current_kalender.kalender_id IN ({$placeholders})
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
AND (
(
current_lehreinheitguppe.gruppe_kurzbz IS NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
AND (
current_lehreinheitguppe.verband IS NULL
OR (
current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
)
)
)
OR
(
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND current_gruppe.direktinskription IS NOT TRUE
AND other_gruppe.direktinskription IS NOT TRUE
)
OR
(
(
current_lehreinheitguppe.gruppe_kurzbz IS NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND other_gruppe.direktinskription IS NOT TRUE
)
OR
(
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
AND current_gruppe.direktinskription IS NOT TRUE
)
)
)
AND other_kalender.kalender_id NOT IN (
SELECT vorgaenger_kalender_id
FROM lehre.tbl_kalender
WHERE vorgaenger_kalender_id IS NOT NULL
)
";
$result = $dbModel->execReadOnlyQuery($sql, $kalender_ids);
if (isError($result) || !hasData($result)) return [];
$grouped = [];
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = true;
}
return $grouped;
}
}
+109 -48
View File
@@ -28,6 +28,7 @@ class StudentListLib
private $_allowedStgs = [];
private $_selects = [];
private $_joins = [];
private $_wheres = [];
/**
* Gets the CI instance, loads model and prepares default values
@@ -40,6 +41,8 @@ class StudentListLib
{
$this->_ci =& get_instance(); // get code igniter instance
$this->_ci->load->config('stv');
$this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel');
if (isset($params['allowedStgs']))
@@ -47,8 +50,6 @@ class StudentListLib
// Add default SELECTs
$this->addSelect("b.uid");
if (defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
$this->addSelect('tag_data_agg.tags');
$this->addSelect('titelpre');
$this->addSelect('nachname');
$this->addSelect('vorname');
@@ -72,6 +73,13 @@ class StudentListLib
$this->addSelect('pls.status_kurzbz AS status');
$this->addSelect('pls.datum AS status_datum');
$this->addSelect('pls.bestaetigtam AS status_bestaetigung');
$this->addSelect("
CASE
WHEN pls.status_kurzbz IN ('Interessent','Aufgenommener','Bewerber','Wartender')
THEN pls.ausbildungssemester
ELSE v.semester
END AS semester_berechnet
");
$this->addSelect(
"(SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp='email' AND person_id=p.person_id AND zustellung LIMIT 1) AS mail_privat",
false
@@ -111,7 +119,7 @@ class StudentListLib
) prest
WHERE laststatus NOT IN ('Abbrecher', 'Abgewiesener', 'Absolvent')
AND priorisierung <= tbl_prestudent.priorisierung
) || ' (' || COALESCE(tbl_prestudent.priorisierung::text, ' '::text) || ')' AS priorisierung_relativ", false); // TODO(chris): overwrite in fetchStudents
) || ' (' || COALESCE(tbl_prestudent.priorisierung::text, ' '::text) || ')' AS priorisierung_relativ", false);
$this->addSelect('mentor');
$this->addSelect('b.aktiv AS bnaktiv');
$this->addSelect('unruly');
@@ -119,7 +127,7 @@ class StudentListLib
// Add default JOINs
$this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
$this->addJoin('public.tbl_person p', 'person_id');
$this->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT'); // TODO(chris): overwrite in fetchStudents
$this->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT');
$this->addJoin('public.tbl_prestudentstatus pls', '
pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL)
AND pls.prestudent_id=tbl_prestudent.prestudent_id
@@ -129,40 +137,14 @@ class StudentListLib
$this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT');
$this->addJoin("v", "", ""); // Will be replaced later
$this->addJoin("ps", "", ""); // Will be replaced later
if (defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED) {
$this->_ci->load->config('stv');
$tags = $this->_ci->config->item('stv_prestudent_tags');
$whereTags = '';
if (is_array($tags) && !isEmptyArray($tags)) {
$tags = array_keys($tags);
foreach ($tags as $key => $tag) {
$tags[$key] = $this->_ci->PrestudentModel->escape($tag);
}
$whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")";
}
$subQueryTag = "(
SELECT
tag.prestudent_id,
COALESCE(json_agg(tag ORDER BY tag.done), '[]'::json) AS tags
FROM (
SELECT DISTINCT ON (n.notiz_id)
n.notiz_id AS id,
nt.typ_kurzbz,
array_to_json(nt.bezeichnung_mehrsprachig)->>0 AS beschreibung,
n.text AS notiz,
nt.style,
n.erledigt AS done,
nz.prestudent_id
FROM public.tbl_notizzuordnung AS nz
JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id
JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz " . $whereTags . "
) AS tag
GROUP BY tag.prestudent_id
) AS tag_data_agg";
$this->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT');
// Add SELECTs and JOINs from config
$config = $this->_ci->config->item('list_columns') ?: [];
foreach ($config as $conf) {
$this->addSelect($conf['default']);
if (isset($conf['joins']))
foreach ($conf['joins'] as $join)
call_user_func_array([$this, 'addJoin'], $join);
}
}
@@ -249,11 +231,7 @@ class StudentListLib
*/
public function addWhere($key, $value = null, $escape = true)
{
if (!is_array($key) && is_array($value)) {
$this->_ci->PrestudentModel->db->where_in($key, $value, $escape);
} else {
$this->_ci->PrestudentModel->db->where($key, $value, $escape);
}
$this->_wheres[] = [$key, $value, $escape, false];
}
/**
@@ -267,11 +245,7 @@ class StudentListLib
*/
public function addOrWhere($key, $value = null, $escape = true)
{
if (!is_array($key) && is_array($value)) {
$this->_ci->PrestudentModel->db->or_where_in($key, $value, $escape);
} else {
$this->_ci->PrestudentModel->db->or_where($key, $value, $escape);
}
$this->_wheres[] = [$key, $value, $escape, true];
}
/**
@@ -283,8 +257,9 @@ class StudentListLib
*/
public function execute($studiensemester_kurzbz)
{
$stdsemEsc = $studiensemester_kurzbz ? $this->_ci->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
$this->addSelectAndJoinForTagsIfConfigured($studiensemester_kurzbz);
$stdsemEsc = $studiensemester_kurzbz ? $this->_ci->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
$this->addSelect(
"public.get_rolle_prestudent(
@@ -315,6 +290,20 @@ class StudentListLib
foreach ($this->_selects as $select)
$this->_ci->PrestudentModel->addSelect($select[0], $select[1]);
foreach ($this->_wheres as $where) {
if (!is_array($where[0]) && is_array($where[1])) {
if ($where[3])
$this->_ci->PrestudentModel->db->or_where_in($where[0], $where[1], $where[2]);
else
$this->_ci->PrestudentModel->db->where_in($where[0], $where[1], $where[2]);
} else {
if ($where[3])
$this->_ci->PrestudentModel->db->or_where($where[0], $where[1], $where[2]);
else
$this->_ci->PrestudentModel->db->where($where[0], $where[1], $where[2]);
}
}
$this->_ci->PrestudentModel->addOrder('nachname');
$this->_ci->PrestudentModel->addOrder('vorname');
@@ -325,6 +314,78 @@ class StudentListLib
//------------------------------------------------------------------------------------------------------------------
// Protected methods
/**
* Add Select and Join for Tags if configured
*
* @param string studiensemester_kurzbz
*
*/
protected function addSelectAndJoinForTagsIfConfigured($studiensemester_kurzbz)
{
if (defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED) {
$this->_ci->load->config('stv');
$tags = $this->_ci->config->item('stv_prestudent_tags');
$whereTags = '';
if (is_array($tags) && !isEmptyArray($tags)) {
$tags = array_keys($tags);
foreach ($tags as $key => $tag) {
$tags[$key] = $this->_ci->PrestudentModel->escape($tag);
}
$whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")";
}
$studiensemester_kurzbz_escaped = $this->_ci->PrestudentModel->escape($studiensemester_kurzbz);
$subQueryTag = "(
SELECT
tag.prestudent_id,
COALESCE(json_agg(tag ORDER BY tag.done, tag.prioritaet), '[]'::json) AS tags
FROM (
SELECT DISTINCT ON (n.notiz_id)
n.notiz_id AS id,
nt.typ_kurzbz,
nt.bezeichnung_mehrsprachig[(
SELECT index
FROM tbl_sprache
WHERE sprache=" . $this->_ci->PrestudentModel->escape(getUserLanguage()) . "
)] AS beschreibung,
n.text AS notiz,
nt.style,
n.erledigt AS done,
nt.prioritaet AS prioritaet,
nt.automatisiert AS automatisiert,
nz.prestudent_id,
n.start,
n.ende
FROM public.tbl_notizzuordnung AS nz
JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id AND nz.prestudent_id IS NOT NULL
JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz " . $whereTags . "
WHERE
COALESCE(n.start, '1970-01-01') <= (
SELECT
ende
FROM
public.tbl_studiensemester
WHERE
studiensemester_kurzbz = " . $studiensemester_kurzbz_escaped . "
)
AND COALESCE(n.ende, '2170-12-31') >= (
SELECT
start
FROM
public.tbl_studiensemester
WHERE
studiensemester_kurzbz = " . $studiensemester_kurzbz_escaped . "
)
) AS tag
GROUP BY tag.prestudent_id
) AS tag_data_agg";
$this->addSelect('tag_data_agg.tags');
$this->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT');
}
}
/**
* Get alias of a table or select statement
*
@@ -0,0 +1,81 @@
<?php
/**
* Description of dd_auto
*
* @author ma0068
*/
class CoreDoubleDegreeTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('codex/Mobilitaet_model', 'MobilitaetModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$this->ci->MobilitaetModel->addJoin('bis.tbl_gsprogramm', 'gsprogramm_id');
$this->ci->MobilitaetModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->MobilitaetModel-> loadWhere(array(
'gsprogrammtyp_kurzbz' => 'Double',
'studiensemester_kurzbz' => $semester
));
$data = $result->retval;
$doubledegree_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->start,
'bis' => $item->ende
];
}, $data);
return (object) array(
'data' => $doubledegree_data,
'typeId' => 'prestudent_id'
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->MobilitaetModel->addSelect('prestudent_id');
$this->ci->MobilitaetModel->addSelect('start as von');
$this->ci->MobilitaetModel->addSelect('ende as bis');
$this->ci->MobilitaetModel->addJoin('bis.tbl_gsprogramm', 'gsprogramm_id');
$this->ci->MobilitaetModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->MobilitaetModel->loadWhere(array(
'gsprogrammtyp_kurzbz' => 'Double',
'studiensemester_kurzbz' => $semester,
'prestudent_id' => $prestudent_id
));
if(hasData($result))
{
//array mit prestudent_id, von und bis
return $result;
}
else
return null;
}
}
@@ -0,0 +1,81 @@
<?php
/**
* Description unruly
* Test for different typeId
*
* @author ma0068
*/
class CoreFiftyFiveTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('person/Person_model', 'PersonModel');
$this->ci-> load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'person_id' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$result = $this->ci->StudiensemesterModel->loadWhere(array(
'studiensemester_kurzbz' => $semester
));
$data = $result->retval[0];
$semVon = $data->start;
$semBis = $data->ende;
$result = $this->ci->PersonModel->getFiftyFivers($semVon, $semBis);
$data = $result->retval;
$fiftyFiveData = array_map(function($item) {
return [
'id' => $item->person_id
];
}, $data);
return (object) array(
'data' => $fiftyFiveData,
'typeId' => 'person_id'
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'person_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$person_id = $params['id'];
$typeId = $params['typeId'];
$result = $this->ci->StudiensemesterModel->loadWhere(array(
'studiensemester_kurzbz' => $semester
));
$data = $result->retval[0];
$semVon = $data->start;
$semBis = $data->ende;
$result = $this->ci->PersonModel->isFiftyFive($semVon, $semBis, $person_id);
if(hasData($result))
{
return $result;
}
else
return null;
}
}
@@ -0,0 +1,63 @@
<?php
/**
* Description of out_auto
*
* @author ma0068
*/
class CoreIncomingTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('codex/Bisio_model', 'BisioModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$result = $this->ci->BisioModel->getIncomingsOfSemester($semester);
$data = $result->retval;
$outgoing_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->von,
'bis' => $item->bis
];
}, $data);
return (object) array(
'data' => $outgoing_data,
'typeId' => 'prestudent_id',
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$result = $this->ci->BisioModel->isPrestudentIncoming($semester, $prestudent_id);
if (hasData($result)) {
return $result;
}
else
return null;
}
}
@@ -0,0 +1,64 @@
<?php
/**
* Description of jgv_auto (Jahrgangsvertretung)
*
* @author ma0068
*/
class CoreJgvTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$result = $this->ci->BenutzerfunktionModel->getPrestudentsOfJgv($semester);
$data = $result->retval;
$jgv_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->datum_von,
'bis' => $item->datum_bis
];
}, $data);
return (object) array(
'data' => $jgv_data,
'typeId' => 'prestudent_id'
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$result = $this->ci->BenutzerfunktionModel->isJgv($semester, $prestudent_id);
if(hasData($result))
{
return $result;
}
else
return null;
}
}
@@ -0,0 +1,112 @@
<?php
/**
* Description of zgv_auto
*
* @author ma0068
*/
class CoreMissingZgvTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('crm/Prestudent_model', 'PrestudentModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id');
$this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id');
$this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$this->ci->PrestudentModel->db->group_start();
$this->ci->PrestudentModel->db->where('zgvdatum', null);
$this->ci->PrestudentModel->db->where('typ', 'b');
$this->ci->PrestudentModel->db->or_group_start();
$this->ci->PrestudentModel->db->where('zgvmadatum', null);
$this->ci->PrestudentModel->db->where('typ', 'm');
$this->ci->PrestudentModel->db->group_end();
$this->ci->PrestudentModel->db->group_end();
$result = $this->ci->PrestudentModel-> loadWhere(array(
'bn.aktiv' => true,
'studiensemester_kurzbz' => $semester
));
$data = $result->retval;
$zgvmissing_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => null,
'bis' => null
];
}, $data);
return (object) array(
'typeId' => 'prestudent_id',
'data' => $zgvmissing_data
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->PrestudentModel->addSelect('prestudent_id');
$this->ci->PrestudentModel->addSelect('start as von');
$this->ci->PrestudentModel->addSelect('ende as bis');
$this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id');
//add studiensemester also here for manual rebuild
$this->ci->PrestudentModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id');
$this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$this->ci->PrestudentModel->db->group_start();
$this->ci->PrestudentModel->db->where('zgvdatum', null);
$this->ci->PrestudentModel->db->where('typ', 'b');
$this->ci->PrestudentModel->db->or_group_start();
$this->ci->PrestudentModel->db->where('zgvmadatum', null);
$this->ci->PrestudentModel->db->where('typ', 'm');
$this->ci->PrestudentModel->db->group_end();
$this->ci->PrestudentModel->db->group_end();
$this->ci->PrestudentModel->db->limit(1);
$result = $this->ci->PrestudentModel-> loadWhere(array(
'bn.aktiv' => true,
'studiensemester_kurzbz' => $semester,
'prestudent_id' => $prestudent_id
));
if(hasData($result))
{
return $result;
}
else
return null;
}
}
@@ -0,0 +1,63 @@
<?php
/**
* Description of out_auto
*
* @author ma0068
*/
class CoreOutgoingTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('codex/Bisio_model', 'BisioModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$result = $this->ci->BisioModel->getOutgoingsOfSemester($semester);
$data = $result->retval;
$outgoing_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->von,
'bis' => $item->bis
];
}, $data);
return (object) array(
'data' => $outgoing_data,
'typeId' => 'prestudent_id',
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$result = $this->ci->BisioModel->isPrestudentOutgoing($semester, $prestudent_id);
if (hasData($result)) {
return $result;
}
else
return null;
}
}
@@ -0,0 +1,80 @@
<?php
/**
* Description of prewh_auto
*
* @author ma0068
*/
class CorePreabbrecherTagLib
{
protected $ci;
const TYP_ABMELDUNG = ['Abmeldung', 'AbmeldungStgl'];
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$this->ci->StudierendenantragModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$this->ci->StudierendenantragModel->db->where_in('typ', self::TYP_ABMELDUNG);
$this->ci->StudierendenantragModel->db->where('studiensemester_kurzbz', $semester);
$result = $this->ci->StudierendenantragModel->getWithLastStatusWhere([
'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED
]);
$data = $result->retval;
$prewiederholer_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->start,
'bis' => $item->ende
];
}, $data);
return (object) array(
'data' => $prewiederholer_data,
'typeId' => 'prestudent_id',
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->StudierendenantragModel->addSelect('prestudent_id');
$this->ci->StudierendenantragModel->addSelect('start as von');
$this->ci->StudierendenantragModel->addSelect('ende as bis');
$this->ci->StudierendenantragModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$this->ci->StudierendenantragModel->db->where_in('typ', self::TYP_ABMELDUNG);
$this->ci->StudierendenantragModel->db->where('studiensemester_kurzbz', $semester);
$this->ci->StudierendenantragModel->db->where('prestudent_id', $prestudent_id);
$result = $this->ci->StudierendenantragModel->getWithLastStatusWhere([
'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED
]);
if(hasData($result))
{
return $result;
}
else
return null;
}
}
@@ -0,0 +1,76 @@
<?php
/**
* Description of prewh_auto
*
* @author bambi
*/
class CorePrewiederholerTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->PrestudentstatusModel-> loadWhere(array(
'statusgrund_id' => 15,
'studiensemester_kurzbz' => $semester
));
$data = $result->retval;
$prewiederholer_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->start,
'bis' => $item->ende
];
}, $data);
return (object) array(
'data' => $prewiederholer_data,
'typeId' => 'prestudent_id',
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->PrestudentstatusModel->addSelect('prestudent_id');
$this->ci->PrestudentstatusModel->addSelect('start as von');
$this->ci->PrestudentstatusModel->addSelect('ende as bis');
$this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->PrestudentstatusModel->loadWhere(array(
'statusgrund_id' => 15,
'studiensemester_kurzbz' => $semester,
'prestudent_id' => $prestudent_id
));
if(hasData($result))
{
return $result;
}
else
return null;
}
}
@@ -0,0 +1,79 @@
<?php
/**
* Description of dd_auto
*
* @author ma0068
*/
class CoreStbErhoehtTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('crm/Konto_model', 'KontoModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$this->ci->KontoModel->addJoin('public.tbl_prestudent', 'person_id');
$this->ci->KontoModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->KontoModel-> loadWhere(array(
'buchungstyp_kurzbz' => 'StudiengebuehrErhoeht',
'studiensemester_kurzbz' => $semester
));
$data = $result->retval;
$konto_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->start,
'bis' => $item->ende
];
}, $data);
return (object) array(
'data' => $konto_data,
'typeId' => 'prestudent_id'
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->KontoModel->addSelect('prestudent_id');
$this->ci->KontoModel->addSelect('start as von');
$this->ci->KontoModel->addSelect('ende as bis');
$this->ci->KontoModel->addJoin('public.tbl_prestudent', 'person_id');
$this->ci->KontoModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->KontoModel-> loadWhere(array(
'buchungstyp_kurzbz' => 'StudiengebuehrErhoeht',
'studiensemester_kurzbz' => $semester,
'prestudent_id' => $prestudent_id
));
if(hasData($result))
{
return $result;
}
else
return null;
}
}
@@ -0,0 +1,76 @@
<?php
/**
* Description of wiedereinstieg_auto
*
* @author ma0068
*/
class CoreUnterbrecherTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->PrestudentstatusModel-> loadWhere(array(
'status_kurzbz' => 'Unterbrecher',
'studiensemester_kurzbz' => $semester
));
$data = $result->retval;
$unterbrecher_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->start,
'bis' => $item->ende
];
}, $data);
return (object) array(
'data' => $unterbrecher_data,
'typeId' => 'prestudent_id'
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->PrestudentstatusModel->addSelect('prestudent_id');
$this->ci->PrestudentstatusModel->addSelect('start as von');
$this->ci->PrestudentstatusModel->addSelect('ende as bis');
$this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->PrestudentstatusModel-> loadWhere(array(
'status_kurzbz' => 'Unterbrecher',
'studiensemester_kurzbz' => $semester,
'prestudent_id' => $prestudent_id
));
if(hasData($result))
{
return $result;
}
else
return null;
}
}
@@ -0,0 +1,76 @@
<?php
/**
* Description of wh_auto
*
* @author bambi
*/
class CoreWiederholerTagLib
{
protected $ci;
public function __construct()
{
$this->ci = get_instance();
$this->ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
}
public function getZuordnungIds(array $params)
{
if(!isset($params['studiensemester_kurzbz']))
{
return (object) array(
'idArray' => []
);
}
$semester = $params['studiensemester_kurzbz'];
$this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->PrestudentstatusModel-> loadWhere(array(
'statusgrund_id' => 16,
'studiensemester_kurzbz' => $semester
));
$data = $result->retval;
$wiederholer_data = array_map(function($item) {
return [
'id' => $item->prestudent_id,
'von' => $item->start,
'bis' => $item->ende
];
}, $data);
return (object) array(
'typeId' => 'prestudent_id',
'data' => $wiederholer_data
);
}
public function isCriteriaSetFor(array $params)
{
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
return false;
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->PrestudentstatusModel->addSelect('prestudent_id');
$this->ci->PrestudentstatusModel->addSelect('start as von');
$this->ci->PrestudentstatusModel->addSelect('ende as bis');
$this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$result = $this->ci->PrestudentstatusModel->loadWhere(array(
'statusgrund_id' => 16,
'studiensemester_kurzbz' => $semester,
'prestudent_id' => $prestudent_id,
));
if(hasData($result))
{
return $result;
}
else
return null;
}
}
+192
View File
@@ -0,0 +1,192 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* LvVw Menu library
*/
class LvVwLib
{
protected $_ci = null;
public $config = [];
public function __construct()
{
// Get code igniter instance
$this->_ci =& get_instance();
// Load Tree-config
$this->_ci->load->config('treemenu/custom/lvvw');
$this->config = $this->_ci->config->item('root');
// Load Libraries
$this->_ci->load->library('treemenu/base/StgLib');
// Load Model
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
}
public function stg($path_template)
{
$permittedStgs = $this->getPermittedStudiengangKzs();
if (!$permittedStgs)
return [];
$this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
'"type": "verband",' .
'"id": "lv/%1$s",' .
'"gruppe_kurzbz": null,' .
'"semester": null,' .
'"verband": null,' .
'"gruppe": null,' .
'"lehrverband": true,' .
'"stg_kz": "%1$s"' .
"}', studiengang_kz)] AS draggable", false);
return $this->_ci->stglib->studiengang($path_template, $permittedStgs);
}
public function semester($path_template, $has_children, $stg)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if (!$has_children)
$this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
$this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
'"type": "verband",' .
'"id": "lv/%1$s/%2$s",' .
'"gruppe_kurzbz": null,' .
'"semester": "%2$s",' .
'"verband": null,' .
'"gruppe": null,' .
'"lehrverband": true,' .
'"stg_kz": "%1$s"' .
"}', v.studiengang_kz, v.semester)] AS draggable", false);
return $this->_ci->stglib->semester($path_template, $stg->studiengang_kz);
}
public function verband($path_template, $stg, $semester)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
$this->_ci->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
$this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
'"type": "verband",' .
'"id": "lv/%1$s/%2$s/%3$s",' .
'"gruppe_kurzbz": null,' .
'"semester": "%2$s",' .
'"verband": "%3$s",' .
'"gruppe": null,' .
'"lehrverband": true,' .
'"stg_kz": "%1$s"' .
"}', v.studiengang_kz, v.semester, v.verband)] AS draggable", false);
$this->_ci->StudiengangModel->addGroupBy('v.studiengang_kz, v.semester');
return $this->_ci->stglib->verband($path_template, $stg->studiengang_kz, $semester);
}
public function group($path_template, $stg, $semester, $verband)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
$this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
if ($verband === null) {
$this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
'"type": "verband",' .
'"id": "grp/%1$s/%2$s/%3$s",' .
'"gruppe_kurzbz": "%3$s",' .
'"semester": "%2$s",' .
'"verband": null,' .
'"gruppe": null,' .
'"lehrverband": false,' .
'"stg_kz": "%1$s"' .
"}', studiengang_kz, semester, gruppe_kurzbz)] AS draggable", false);
return $this->_ci->stglib->group($path_template, $stg->studiengang_kz, $semester);
}
$this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
'"type": "verband",' .
'"id": "lv/%1$s/%2$s/%3$s/%4$s",' .
'"gruppe_kurzbz": null,' .
'"semester": "%2$s",' .
'"verband": "%3$s",' .
'"gruppe": "%4$s",' .
'"lehrverband": true,' .
'"stg_kz": "%1$s"' .
"}', v.studiengang_kz, v.semester, v.verband, v.gruppe)] AS draggable", false);
return $this->_ci->stglib->verbandsgroup($path_template, $stg->studiengang_kz, $semester, $verband);
}
public function orgform($path_template, $stg)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if (!$stg->mischform)
return [];
$this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
return $this->_ci->stglib->orgform($path_template, $stg->studiengang_kz);
}
protected function getPermittedStudiengangKzs()
{
$permittedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('admin') ?: [];
$permittedStgs = array_merge($permittedStgs, $this->_ci->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
return $permittedStgs;
}
protected function getStgFromUrl($stg)
{
$permittedStgs = $this->getPermittedStudiengangKzs();
if (!$permittedStgs)
return null;
$this->_ci->StudiengangModel->db->where_in('studiengang_kz', $permittedStgs);
$stg = $this->_ci->StudiengangModel->loadWhere([
'LOWER(CONCAT(typ, kurzbz)) =' => $stg
]);
if (!hasData($stg))
return null;
return current(getData($stg));
}
}
@@ -0,0 +1,257 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* StudVw Menu library
*/
class StudVwLib
{
protected $_ci = null;
public $config = [];
public $redirect_method = [
'interessenten' => 'filter',
'bewerbungnichtabgeschickt' => 'filter',
'bewerbungabgeschickt' => 'filter',
'zgv' => 'filter',
'statusbestaetigt' => 'filter',
'statusbestaetigtrtnichtangemeldet' => 'filter',
'statusbestaetigtrtangemeldet' => 'filter',
'reihungstestnichtangemeldet' => 'filter',
'reihungstestangemeldet' => 'filter',
'bewerber' => 'filter',
'bewerberrtnichtangemeldet' => 'filter',
'bewerberrtangemeldet' => 'filter',
'bewerberrtangemeldetteilgenommen' => 'filter',
'bewerberrtangemeldetnichtteilgenommen' => 'filter',
'aufgenommen' => 'filter',
'warteliste' => 'filter',
'absage' => 'filter',
'outgoing' => 'inout',
'shared_studies' => 'inout'
];
public function __construct()
{
// Get code igniter instance
$this->_ci =& get_instance();
// Load Tree-config
$this->_ci->load->config('treemenu/stg_base');
$this->config = $this->_ci->config->item('root');
// Load Libraries
$this->_ci->load->library('treemenu/base/StgLib');
// Load Model
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
}
public function stg($path_template)
{
$permittedStgs = $this->getPermittedStudiengangKzs();
if (!$permittedStgs)
return [];
return $this->_ci->stglib->studiengang($path_template, $permittedStgs);
}
public function prestudent($path_template, $stg)
{
// Check permission
if ($this->getStgFromUrl($stg) === null)
return [];
return [
[
'path' => sprintf($path_template, '1'),
'name' => ['lehre', 'prestudent'],
'no_sem_reload' => true
]
];
}
public function stdsem($path_template, $stg)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
return $this->_ci->stglib->studiensemester($path_template, $stg->studiengang_kz);
}
public function semester($path_template, $stg, $orgform)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if ($orgform !== null) {
$orgform = $this->getOrgform($orgform);
if ($orgform === null)
return [];
$orgform = $orgform->orgform_kurzbz;
}
return $this->_ci->stglib->semester($path_template, $stg->studiengang_kz, $orgform);
}
public function verband($path_template, $stg, $semester, $orgform)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if ($orgform !== null) {
$orgform = $this->getOrgform($orgform);
if ($orgform === null)
return [];
$orgform = $orgform->orgform_kurzbz;
}
$this->_ci->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
return $this->_ci->stglib->verband($path_template, $stg->studiengang_kz, $semester, $orgform);
}
public function group($path_template, $stg, $semester, $verband, $orgform)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if ($orgform !== null) {
$orgform = $this->getOrgform($orgform);
if ($orgform === null)
return [];
$orgform = $orgform->orgform_kurzbz;
}
$this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
if ($verband === null)
return $this->_ci->stglib->group($path_template, $stg->studiengang_kz, $semester, $orgform);
return $this->_ci->stglib->verbandsgroup($path_template, $stg->studiengang_kz, $semester, $verband, $orgform);
}
public function orgform($path_template, $stg)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if (!$stg->mischform)
return [];
return $this->_ci->stglib->orgform($path_template, $stg->studiengang_kz);
}
public function incoming($has_children, $path_template, $stg)
{
if ($stg === null)
return $this->inout('incoming', $has_children, $path_template);
return $this->filter('incoming', $has_children, $path_template, $stg);
}
public function filter($original_method, $has_children, $path_template, $stg)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
// TODO(chris): phrasen
$item = [
'path' => sprintf($path_template, '1'),
'name' => ['treemenu', 'filter_' . $original_method]
];
if (!$has_children)
$item['leaf'] = true;
return [ $item ];
}
public function inout($original_method, $has_children, $path_template)
{
if (!$this->_ci->permissionlib->isBerechtigt('inout/uebersicht'))
return [];
// TODO(chris): phrasen
$item = [
'path' => sprintf($path_template, '1'),
'name' => ['treemenu', 'inout_' . $original_method]
];
if (!$has_children)
$item['leaf'] = true;
return [ $item ];
}
protected function getOrgform($orgform)
{
$this->_ci->load->model('codex/Orgform_model', 'OrgformModel');
$orgform = $this->_ci->OrgformModel->loadWhere([
'LOWER(orgform_kurzbz) =' => $orgform
]);
if (!hasData($orgform))
return null;
return current(getData($orgform));
}
protected function getPermittedStudiengangKzs()
{
$permittedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('admin') ?: [];
$permittedStgs = array_merge($permittedStgs, $this->_ci->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
return $permittedStgs;
}
protected function getStgFromUrl($stg)
{
$permittedStgs = $this->getPermittedStudiengangKzs();
if (!$permittedStgs)
return null;
$this->_ci->StudiengangModel->db->where_in('studiengang_kz', $permittedStgs);
$stg = $this->_ci->StudiengangModel->loadWhere([
'LOWER(CONCAT(typ, kurzbz)) =' => $stg
]);
if (!hasData($stg))
return null;
return current(getData($stg));
}
}
@@ -0,0 +1,148 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Tempus Menu library
*/
class TempusLib
{
protected $_ci = null;
public $config = [];
public function __construct()
{
// Get code igniter instance
$this->_ci =& get_instance();
// Load Tree-config
$this->_ci->load->config('treemenu/custom/tempus');
$this->config = $this->_ci->config->item('root');
// Load Libraries
$this->_ci->load->library('treemenu/base/StgLib');
// Load Model
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
}
public function stg($path_template)
{
$permittedStgs = $this->getPermittedStudiengangKzs();
if (!$permittedStgs)
return [];
return $this->_ci->stglib->studiengang($path_template, $permittedStgs);
}
public function semester($path_template, $has_children, $stg)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if (!$has_children)
$this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
return $this->_ci->stglib->semester($path_template, $stg->studiengang_kz);
}
public function verband($path_template, $stg, $semester)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
$this->_ci->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
$this->_ci->StudiengangModel->addGroupBy('v.studiengang_kz, v.semester');
return $this->_ci->stglib->verband($path_template, $stg->studiengang_kz, $semester);
}
public function group($path_template, $stg, $semester, $verband)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
$this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
if ($verband === null) {
$this->_ci->load->model('organisation/Gruppe_model', 'GruppeModel');
$this->_ci->GruppeModel->addSelect('semester');
return $this->_ci->stglib->group($path_template, $stg->studiengang_kz, $semester);
}
return $this->_ci->stglib->verbandsgroup($path_template, $stg->studiengang_kz, $semester, $verband);
}
public function orgform($path_template, $stg)
{
$stg = $this->getStgFromUrl($stg);
if ($stg === null)
return [];
if (!$stg->mischform)
return [];
$this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
$this->_ci->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
$this->_ci->StudienordnungModel->addSelect("p.orgform_kurzbz");
return $this->_ci->stglib->orgform($path_template, $stg->studiengang_kz);
}
protected function getPermittedStudiengangKzs()
{
$permittedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('admin') ?: [];
$permittedStgs = array_merge($permittedStgs, $this->_ci->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
$permittedStgs = array_merge($permittedStgs, $this->_ci->permissionlib->getSTG_isEntitledFor('lehre/lvplan') ?: []);
return $permittedStgs;
}
protected function getStgFromUrl($stg)
{
$permittedStgs = $this->getPermittedStudiengangKzs();
if (!$permittedStgs)
return null;
$this->_ci->StudiengangModel->db->where_in('studiengang_kz', $permittedStgs);
$stg = $this->_ci->StudiengangModel->loadWhere([
'LOWER(CONCAT(typ, kurzbz)) =' => $stg
]);
if (!hasData($stg))
return null;
return current(getData($stg));
}
}
@@ -0,0 +1,313 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Stg Base library
*/
class StgLib
{
protected $_ci = null;
public function __construct()
{
// Get code igniter instance
$this->_ci =& get_instance();
}
public function studiengang($path_template, $permittedStgs = [])
{
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->_ci->StudiengangModel->addDistinct();
$this->_ci->StudiengangModel->addSelect("FORMAT(" . $this->_ci->StudiengangModel->escape($path_template) . ", LOWER(CONCAT(typ, kurzbz))) AS path");
$this->_ci->StudiengangModel->addSelect(
"CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name",
false
);
$this->_ci->StudiengangModel->addSelect("studiengang_kz AS title");
$this->_ci->StudiengangModel->addSelect("studiengang_kz AS search");
$this->_ci->StudiengangModel->addSelect('erhalter_kz');
$this->_ci->StudiengangModel->addSelect('typ');
$this->_ci->StudiengangModel->addSelect('kurzbz');
$this->_ci->StudiengangModel->addSelect('studiengang_kz');
$this->_ci->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
$this->_ci->StudiengangModel->addOrder('erhalter_kz');
$this->_ci->StudiengangModel->addOrder('typ');
$this->_ci->StudiengangModel->addOrder('kurzbz');
if ($permittedStgs)
$this->_ci->StudiengangModel->db->where_in('studiengang_kz', $permittedStgs);
$result = $this->_ci->StudiengangModel->loadWhere(['v.aktiv' => true]);
return getData($result) ?: [];
}
public function semester($path_template, $studiengang_kz, $orgform_kurzbz = null)
{
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->_ci->StudiengangModel->addDistinct();
$this->_ci->StudiengangModel->addSelect("FORMAT(" . $this->_ci->StudiengangModel->escape($path_template) . ", semester) AS path", false);
$this->_ci->StudiengangModel->addSelect("CONCAT(
UPPER(CONCAT(typ, kurzbz)),
'-',
semester,
(
SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END
FROM public.tbl_lehrverband
WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester
ORDER BY verband, gruppe LIMIT 1
)
) AS name", false);
$this->_ci->StudiengangModel->addSelect('semester');
$this->_ci->StudiengangModel->addSelect('v.studiengang_kz AS stg_kz');
$this->_ci->StudiengangModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
$this->_ci->StudiengangModel->addOrder('semester');
if ($orgform_kurzbz !== null) {
$this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($orgform_kurzbz) . " AS orgform_kurzbz", false);
$this->_ci->StudiengangModel->addDistinct();
$this->_ci->StudiengangModel->db->group_start();
$this->_ci->StudiengangModel->db->where('v.semester', 0);
$this->_ci->StudiengangModel->db->or_where('v.orgform_kurzbz', $orgform_kurzbz);
$this->_ci->StudiengangModel->db->group_end();
}
$result = $this->_ci->StudiengangModel->loadWhere([
'studiengang_kz' => $studiengang_kz,
'v.aktiv' => true
]);
return getData($result) ?: [];
}
public function group($path_template, $studiengang_kz, $semester, $orgform_kurzbz = null)
{
$this->_ci->load->model('organisation/Gruppe_model', 'GruppeModel');
$this->_ci->GruppeModel->addDistinct();
$this->_ci->GruppeModel->addSelect("FORMAT(" . $this->_ci->GruppeModel->escape($path_template) . ", gruppe_kurzbz) AS path", false);
$this->_ci->GruppeModel->addSelect("CONCAT(gruppe_kurzbz, ' (', bezeichnung, ')') AS name", false);
$this->_ci->GruppeModel->addSelect('sort');
$this->_ci->GruppeModel->addSelect('gruppe_kurzbz');
$this->_ci->GruppeModel->addSelect($this->_ci->GruppeModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->_ci->GruppeModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
$this->_ci->GruppeModel->addOrder('sort');
$this->_ci->GruppeModel->addOrder('gruppe_kurzbz');
$where = [
'studiengang_kz' => $studiengang_kz,
'semester' => $semester,
'lehre' => true,
'sichtbar' => true,
'aktiv' => true,
'direktinskription' => false
];
if ($orgform_kurzbz !== null)
$where['orgform_kurzbz'] = $orgform_kurzbz;
$result = $this->_ci->GruppeModel->loadWhere($where);
return getData($result) ?: [];
}
public function verband($path_template, $studiengang_kz, $semester, $orgform_kurzbz = null)
{
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->_ci->StudiengangModel->addSelect("FORMAT(" . $this->_ci->StudiengangModel->escape($path_template) . ", verband) AS path", false);
$this->_ci->StudiengangModel->addSelect("CONCAT(
UPPER(CONCAT(typ, kurzbz)),
'-',
semester,
verband,
(
SELECT
CASE
WHEN bezeichnung IS NULL OR bezeichnung=''
THEN ''::TEXT
ELSE CONCAT(' (', bezeichnung, ')')
END
FROM public.tbl_lehrverband
WHERE studiengang_kz=v.studiengang_kz
AND semester=v.semester
AND verband=v.verband
ORDER BY gruppe
LIMIT 1
)
) AS name", false);
$this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($semester) . ' AS semester');
$this->_ci->StudiengangModel->addSelect('verband');
$this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->_ci->StudiengangModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
$this->_ci->StudiengangModel->addOrder('verband');
$this->_ci->StudiengangModel->addGroupBy('path, name, verband');
$where = [
'v.studiengang_kz' => $studiengang_kz,
'v.semester' => $semester,
'v.verband !=' => '',
'v.aktiv' => true
];
if ($orgform_kurzbz !== null && $semester) // NOTE(chris): on semester 0 show all?
$where['v.orgform_kurzbz'] = $orgform_kurzbz;
$result = $this->_ci->StudiengangModel->loadWhere($where);
return getData($result) ?: [];
}
public function verbandsgroup($path_template, $studiengang_kz, $semester, $verband, $orgform_kurzbz = null)
{
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
$this->_ci->StudiengangModel->addDistinct();
$this->_ci->StudiengangModel->addSelect("FORMAT(
" . $this->_ci->StudiengangModel->escape($path_template) . ",
gruppe
) AS path", false);
$this->_ci->StudiengangModel->addSelect("CONCAT(
UPPER(CONCAT(typ, kurzbz)),
'-',
semester,
verband,
gruppe,
(
SELECT
CASE
WHEN bezeichnung IS NULL OR bezeichnung=''
THEN ''::TEXT
ELSE CONCAT(' (', bezeichnung, ')')
END
FROM public.tbl_lehrverband
WHERE studiengang_kz=v.studiengang_kz
AND semester=v.semester
AND verband=v.verband
AND gruppe=v.gruppe
ORDER BY gruppe
LIMIT 1
)
) AS name", false);
$this->_ci->StudiengangModel->addSelect('v.semester');
$this->_ci->StudiengangModel->addSelect('v.verband');
$this->_ci->StudiengangModel->addSelect('gruppe');
$this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
$this->_ci->StudiengangModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
$this->_ci->StudiengangModel->addOrder('gruppe');
$where = [
'v.studiengang_kz' => $studiengang_kz,
'v.semester' => $semester,
'v.verband' => $verband,
'v.gruppe !=' => '',
'v.aktiv' => true
];
if ($orgform_kurzbz !== null && $semester) // NOTE(chris): on semester 0 show all?
$where['v.orgform_kurzbz'] = $orgform_kurzbz;
$result = $this->_ci->StudiengangModel->loadWhere($where);
return getData($result) ?: [];
}
public function orgform($path_template, $studiengang_kz)
{
$this->_ci->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
$this->_ci->StudienordnungModel->addDistinct();
$this->_ci->StudienordnungModel->addSelect("FORMAT(
" . $this->_ci->StudienordnungModel->escape($path_template) . ",
LOWER(p.orgform_kurzbz)
) AS path");
$this->_ci->StudienordnungModel->addSelect("p.orgform_kurzbz AS name");
$this->_ci->StudienordnungModel->addSelect("studiengang_kz AS stg_kz");
$this->_ci->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id');
$result = $this->_ci->StudienordnungModel->loadWhere([
'aktiv' => true,
'studiengang_kz' => $studiengang_kz,
'p.orgform_kurzbz !=' => 'DDP'
]);
return getData($result) ?: [];
}
public function studiensemester($path_template, $studiengang_kz)
{
$number_displayed_past_studiensemester = null;
$this->_ci->load->model('system/Variable_model', 'VariableModel');
$result = $this->_ci->VariableModel->getVariables(getAuthUID(), ['number_displayed_past_studiensemester']);
if (isError($result))
return [];
$data = getData($result);
if ($data && isset($data['number_displayed_past_studiensemester'])) {
$number_displayed_past_studiensemester = $data['number_displayed_past_studiensemester'];
} else {
$this->_ci->load->config('stv');
$number_displayed_past_studiensemester = $this->_ci->config->item('number_displayed_past_studiensemester_default');
}
$this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->_ci->StudiensemesterModel->addPlusMinus(null, $number_displayed_past_studiensemester);
$this->_ci->StudiensemesterModel->addSelect("studiensemester_kurzbz AS name");
$this->_ci->StudiensemesterModel->addSelect("FORMAT(
" . $this->_ci->StudiensemesterModel->escape($path_template) . ",
LOWER(studiensemester_kurzbz)
) AS path", false);
$this->_ci->StudiensemesterModel->addSelect($this->_ci->StudiensemesterModel->escape($studiengang_kz) . " AS stg_kz", false);
$this->_ci->StudiensemesterModel->addOrder('ende');
$result = $this->_ci->StudiensemesterModel->load();
return getData($result) ?: [];
}
}
@@ -13,6 +13,7 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
protected $dienstverhaeltnis_id;
protected $vertragsbestandteil_id;
protected $gehaltstyp_kurzbz;
protected $gehaltsanpassungtyp_kurzbz = '';
protected $von;
protected $bis;
protected $anmerkung;
@@ -21,6 +22,7 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
protected $valorisierungssperre;
protected $valorisierung;
protected $auszahlungen;
protected $gehaltstyp_bezeichnung;
protected $insertamum;
protected $insertvon;
@@ -39,6 +41,10 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id);
isset($data->vertragsbestandteil_id) && $this->setVertragsbestandteil_id($data->vertragsbestandteil_id);
isset($data->gehaltstyp_kurzbz) && $this->setGehaltstyp_kurzbz($data->gehaltstyp_kurzbz);
//isset($data->gehaltsanpassungtyp_kurzbz) && $this->setGehaltsanpassungtyp_kurzbz($data->gehaltsanpassungtyp_kurzbz);
if (!empty($data->gehaltsanpassungtyp_kurzbz)) {
$this->setGehaltsanpassungtyp_kurzbz($data->gehaltsanpassungtyp_kurzbz);
}
isset($data->von) && $this->setVon($data->von);
isset($data->bis) && $this->setBis($data->bis);
isset($data->anmerkung) && $this->setAnmerkung($data->anmerkung);
@@ -47,7 +53,8 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
isset($data->valorisierungssperre) && $this->setValorisierungssperre($data->valorisierungssperre);
isset($data->valorisierung) && $this->setValorisierung($data->valorisierung);
isset($data->auszahlungen) && $this->setAuszahlungen($data->auszahlungen);
isset($data->gehaltstyp_bezeichnung) && $this->setGehaltstyp_bezeichnung($data->gehaltstyp_bezeichnung);
isset($data->insertamum) && $this->setInsertamum($data->insertamum);
isset($data->insertvon) && $this->setInsertvon($data->insertvon);
isset($data->updateamum) && $this->setUpdateamum($data->updateamum);
@@ -75,6 +82,11 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
return $this->gehaltstyp_kurzbz;
}
public function getGehaltsanpassungtyp_kurzbz()
{
return $this->gehaltsanpassungtyp_kurzbz;
}
public function getVon()
{
return $this->von;
@@ -178,6 +190,13 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
return $this;
}
public function setGehaltsanpassungtyp_kurzbz($gehaltsanpassungtyp_kurzbz)
{
$this->markDirty('gehaltsanpassungtyp_kurzbz', $this->gehaltsanpassungtyp_kurzbz, $gehaltsanpassungtyp_kurzbz);
$this->gehaltsanpassungtyp_kurzbz = $gehaltsanpassungtyp_kurzbz;
return $this;
}
public function setVon($von)
{
$this->markDirty('von', $this->von, $von);
@@ -206,6 +225,10 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
$grundbetrag = number_format($grundbetrag, 2, '.', '');
}
$this->markDirty('grundbetrag', $this->grundbetrag, $grundbetrag);
if(in_array('grundbetrag', $this->modifiedcolumns))
{
$this->setBetrag_valorisiert($grundbetrag);
}
$this->grundbetrag = $grundbetrag;
return $this;
}
@@ -242,6 +265,13 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
return $this;
}
public function setGehaltstyp_bezeichnung($gehaltstyp_bezeichnung)
{
$this->markDirty('gehaltstyp_bezeichnung', $this->gehaltstyp_bezeichnung, $gehaltstyp_bezeichnung);
$this->gehaltstyp_bezeichnung = $gehaltstyp_bezeichnung;
return $this;
}
public function setInsertamum($insertamum)
{
$this->markDirty('insertamum', $this->insertamum, $insertamum);
@@ -284,6 +314,7 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(),
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'gehaltstyp_kurzbz' => $this->getGehaltstyp_kurzbz(),
'gehaltsanpassungtyp_kurzbz' => $this->getGehaltsanpassungtyp_kurzbz(),
'von' => $this->getVon(),
'bis' => $this->getBis(),
'anmerkung' => $this->getAnmerkung(),
@@ -312,6 +343,7 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()}
vertragsbestandteil_id: {$this->getVertragsbestandteil_id()}
gehaltstyp_kurzbz: {$this->getGehaltstyp_kurzbz()}
gehaltsanpassungtyp_kurzbz: {$this->getGehaltsanpassungtyp_kurzbz()}
von: {$this->getVon()}
bis: {$this->getBis()}
anmerkung: {$this->getAnmerkung()}
+106
View File
@@ -44,4 +44,110 @@ class Bisio_model extends DB_Model
else
return success("Bisio not found");
}
/**
* Gets outgoing students of certain Semester
* @param String studiensemester_kurzbz
* @return array of prestudent_ids
*/
public function getOutgoingsOfSemester($studiensemester_kurzbz)
{
$query = "
SELECT DISTINCT ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis
FROM bis.tbl_bisio
JOIN public.tbl_student USING (student_uid)
JOIN public.tbl_prestudent ps USING (prestudent_id)
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
WHERE ss.studiensemester_kurzbz = ?
AND nation_code <> 'A'
AND (
tbl_bisio.von <= ss.ende
AND (
tbl_bisio.bis >= ss.start
OR tbl_bisio.bis IS NULL
)
)
";
return $this->execQuery($query, array($studiensemester_kurzbz));
}
/**
* Gets incoming students of certain Semester
* @param String studiensemester_kurzbz
* @return array of prestudent_ids
*/
public function getIncomingsOfSemester($studiensemester_kurzbz)
{
$query = "
SELECT DISTINCT ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis
FROM bis.tbl_bisio
JOIN public.tbl_student USING (student_uid)
JOIN public.tbl_prestudent ps USING (prestudent_id)
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
WHERE ss.studiensemester_kurzbz = ?
AND nation_code = 'A'
AND (
tbl_bisio.von <= ss.ende
AND (
tbl_bisio.bis >= ss.start
OR tbl_bisio.bis IS NULL
)
)
";
return $this->execQuery($query, array($studiensemester_kurzbz));
}
public function isPrestudentOutgoing($studiensemester_kurzbz, $prestudent_id)
{
$query = "
SELECT
ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis
FROM bis.tbl_bisio
JOIN public.tbl_student USING (student_uid)
JOIN public.tbl_prestudent ps USING (prestudent_id)
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
WHERE ss.studiensemester_kurzbz = ?
AND nation_code <> 'A'
AND (
tbl_bisio.von <= ss.ende
AND (
tbl_bisio.bis >= ss.start
OR tbl_bisio.bis IS NULL
)
)
AND ps.prestudent_id = ?
";
return $this->execQuery($query, array($studiensemester_kurzbz, $prestudent_id));
}
public function isPrestudentIncoming($studiensemester_kurzbz, $prestudent_id)
{
$query = "
SELECT
ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis
FROM bis.tbl_bisio
JOIN public.tbl_student USING (student_uid)
JOIN public.tbl_prestudent ps USING (prestudent_id)
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
WHERE ss.studiensemester_kurzbz = ?
AND nation_code = 'A'
AND (
tbl_bisio.von <= ss.ende
AND (
tbl_bisio.bis >= ss.start
OR tbl_bisio.bis IS NULL
)
)
AND ps.prestudent_id = ?
";
return $this->execQuery($query, array($studiensemester_kurzbz, $prestudent_id));
}
}
+2 -1
View File
@@ -57,7 +57,7 @@ class Dokument_model extends DB_Model
$qry = " SELECT
a.akte_id,
a.bezeichnung,
dok.bezeichnung,
a.dokument_kurzbz,
a.titel_intern,
a.anmerkung_intern,
@@ -83,6 +83,7 @@ class Dokument_model extends DB_Model
inhalt
FROM
public.tbl_akte a
JOIN public.tbl_dokument dok ON (dok.dokument_kurzbz = a.dokument_kurzbz)
WHERE
a.person_id = ?
AND a.dokument_kurzbz NOT IN (
+1 -1
View File
@@ -204,7 +204,7 @@ class Student_model extends DB_Model
Events::trigger(
'generate_student_uid',
function ($value) use ($uid) {
function ($value) use (&$uid) {
$uid = $value;
},
$stgkzl,
@@ -395,6 +395,80 @@ EOSQL;
return $this->execReadOnlyQuery($qry, $params);
}
public function getOffeneStunden($lehreinheit_ids)
{
if (!is_array($lehreinheit_ids))
$lehreinheit_ids = [$lehreinheit_ids];
if (empty($lehreinheit_ids))
return success([]);
$db = new DB_Model();
$placeholders = implode(',', array_fill(0, count($lehreinheit_ids), '?'));
$qry = "WITH eventdauer AS (
SELECT
tbl_kalender_lehreinheit.lehreinheit_id,
tbl_kalender.von,
tbl_kalender.bis,
tbl_kalender.kalender_id
FROM lehre.tbl_lehreinheit
JOIN lehre.tbl_kalender_lehreinheit USING(lehreinheit_id)
JOIN lehre.tbl_kalender USING(kalender_id)
WHERE tbl_lehreinheit.lehreinheit_id IN ($placeholders)
AND NOT EXISTS (SELECT 1 FROM lehre.tbl_kalender nachfolger
WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id)
AND tbl_kalender.status_kurzbz NOT IN ('deleted', 'todelete', 'archived')
GROUP BY tbl_kalender_lehreinheit.lehreinheit_id, tbl_kalender.von, tbl_kalender.bis, tbl_kalender.kalender_id
),
raster AS (
SELECT
eventdauer.lehreinheit_id,
eventdauer.kalender_id,
eventdauer.von,
eventdauer.bis,
vonstunde.stunde AS vonstunde_nr,
bisstunde.stunde AS bisstunde_nr
FROM eventdauer
LEFT JOIN lehre.tbl_stunde vonstunde ON eventdauer.von::time = vonstunde.beginn
LEFT JOIN lehre.tbl_stunde bisstunde ON eventdauer.bis::time = bisstunde.ende
),
unterrichtsdauer AS (
SELECT
raster.lehreinheit_id,
raster.kalender_id,
sum(EXTRACT(EPOCH FROM (LEAST(stunde.ende, raster.bis::time) - GREATEST(stunde.beginn, raster.von::time))) / 60) AS minuten
FROM raster JOIN lehre.tbl_stunde stunde ON stunde.beginn < raster.bis::time AND stunde.ende > raster.von::time
WHERE raster.vonstunde_nr IS NULL OR raster.bisstunde_nr IS NULL
GROUP BY raster.lehreinheit_id, raster.kalender_id
),
verplantestunden AS (
SELECT raster.lehreinheit_id, raster.kalender_id,
CASE
WHEN raster.vonstunde_nr IS NOT NULL AND raster.bisstunde_nr IS NOT NULL
THEN (raster.bisstunde_nr - raster.vonstunde_nr + 1)
ELSE coalesce(unterrichtsdauer.minuten, 0) / 45
END AS verplantestunde
FROM raster LEFT JOIN unterrichtsdauer ON unterrichtsdauer.lehreinheit_id = raster.lehreinheit_id AND unterrichtsdauer.kalender_id = raster.kalender_id
),
verplant_gesamt AS (
SELECT lehreinheit_id, SUM(verplantestunde) AS verplant
FROM verplantestunden
GROUP BY lehreinheit_id
)
SELECT
lema.lehreinheit_id,
lema.mitarbeiter_uid,
lema.planstunden,
ROUND(coalesce(verplant_gesamt.verplant, 0), 2) AS verplant,
ROUND((lema.planstunden - coalesce(verplant_gesamt.verplant, 0)), 2) AS offenestunden
FROM lehre.tbl_lehreinheitmitarbeiter lema
LEFT JOIN verplant_gesamt ON verplant_gesamt.lehreinheit_id = lema.lehreinheit_id
WHERE lema.lehreinheit_id IN ($placeholders)";
return $db->execReadOnlyQuery($qry, array_merge($lehreinheit_ids, $lehreinheit_ids));
}
private function getLVTmp($stg_kz = null)
{
$qry = "SELECT DISTINCT ON(lehrveranstaltung_id) *,
@@ -719,7 +793,7 @@ EOSQL;
return "tag_data_agg AS (
SELECT
lehreinheit_id,
COALESCE(json_agg(tag ORDER BY done), '[]'::json) AS tags
COALESCE(json_agg(tag ORDER BY done, prioritaet), '[]'::json) AS tags
FROM (
SELECT DISTINCT ON (public.tbl_notiz.notiz_id)
tbl_notiz.notiz_id AS id,
@@ -728,7 +802,9 @@ EOSQL;
text AS notiz,
style,
erledigt AS done,
lehreinheit_id
lehreinheit_id,
prioritaet,
automatisiert
FROM public.tbl_notizzuordnung
JOIN public.tbl_notiz ON tbl_notizzuordnung.notiz_id = tbl_notiz.notiz_id
JOIN public.tbl_notiz_typ ON tbl_notiz.typ = tbl_notiz_typ.typ_kurzbz
@@ -341,7 +341,7 @@ class Lehreinheitgruppe_model extends DB_Model
$this->db->where('lehreinheit_id', $lehreinheit_id);
$this->db->where('studiengang_kz', $gruppen_array->studiengang_kz);
if (!isEmptyString($gruppen_array->semester))
if (!isEmptyString((string)$gruppen_array->semester))
{
$this->db->where('semester', $gruppen_array->semester);
}
@@ -444,30 +444,37 @@ class Lehreinheitgruppe_model extends DB_Model
)
ELSE tbl_gruppe.beschreibung
END AS beschreibung");
$this->addSelect("CASE
WHEN tbl_lehreinheitgruppe.gruppe_kurzbz IS NULL THEN
(
SELECT EXISTS (
SELECT 1
FROM lehre.tbl_stundenplandev
WHERE lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id
AND studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND semester = tbl_lehreinheitgruppe.semester
AND TRIM(COALESCE(verband, '')) = TRIM(tbl_lehreinheitgruppe.verband)
AND TRIM(COALESCE(gruppe, '')) = TRIM(tbl_lehreinheitgruppe.gruppe)
AND (gruppe_kurzbz IS NULL OR gruppe_kurzbz = '')
)
)
ELSE
$this->addSelect("
CASE
WHEN trim(COALESCE(tbl_lehreinheitgruppe.gruppe_kurzbz, '')) = '' THEN
(
SELECT EXISTS (
SELECT 1
FROM lehre.tbl_stundenplandev
WHERE lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id
AND gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz
FROM lehre.tbl_stundenplandev sp
WHERE sp.lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id
AND sp.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND sp.semester = tbl_lehreinheitgruppe.semester
AND trim(COALESCE(sp.verband, '')) = trim(COALESCE(tbl_lehreinheitgruppe.verband, ''))
AND trim(COALESCE(sp.gruppe, '')) = trim(COALESCE(tbl_lehreinheitgruppe.gruppe, ''))
AND trim(COALESCE(sp.gruppe_kurzbz, '')) = ''
)
)
END AS verplant");
ELSE
(
SELECT EXISTS (
SELECT 1
FROM lehre.tbl_stundenplandev sp
WHERE sp.lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id
AND sp.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
AND sp.semester = tbl_lehreinheitgruppe.semester
AND trim(COALESCE(sp.verband, '')) = trim(COALESCE(tbl_lehreinheitgruppe.verband, ''))
AND trim(COALESCE(sp.gruppe, '')) = trim(COALESCE(tbl_lehreinheitgruppe.gruppe, ''))
AND trim(COALESCE(sp.gruppe_kurzbz, '')) = trim(COALESCE(tbl_lehreinheitgruppe.gruppe_kurzbz, ''))
)
)
END AS verplant
");
$this->addJoin('tbl_studiengang', 'studiengang_kz', 'LEFT');
$this->addJoin('public.tbl_gruppe', 'gruppe_kurzbz', 'LEFT');
@@ -1245,7 +1245,7 @@ class Lehrveranstaltung_model extends DB_Model
{
return "
SELECT
lehrveranstaltung_id, tbl_lehrveranstaltung.kurzbz as lv_kurzbz, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, bezeichnung_english as lv_bezeichnung_english, studiengang_kz,
distinct on (lehrveranstaltung_id) lehrveranstaltung_id, tbl_lehrveranstaltung.kurzbz as lv_kurzbz, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, bezeichnung_english as lv_bezeichnung_english, studiengang_kz,
tbl_studienplan_lehrveranstaltung.semester, tbl_lehrveranstaltung.sprache,
ects as lv_ects, semesterstunden, anmerkung, lehre, lehreverzeichnis as lv_lehreverzeichnis, tbl_lehrveranstaltung.aktiv,
planfaktor as lv_planfaktor, planlektoren as lv_planlektoren, planpersonalkosten as lv_planpersonalkosten,
@@ -29,10 +29,14 @@ class Lvgesamtnote_model extends DB_Model
$this->addSelect("lv.bezeichnung AS lehrveranstaltung_bezeichnung");
$this->addSelect("lv.studiengang_kz");
$this->addSelect("UPPER(stg.typ || stg.kurzbz) AS studiengang");
$this->addSelect("person.vorname");
$this->addSelect("person.nachname");
$this->addJoin("lehre.tbl_note n", "note");
$this->addJoin("lehre.tbl_lehrveranstaltung lv", "lehrveranstaltung_id");
$this->addJoin("public.tbl_studiengang stg", "studiengang_kz");
$this->addJoin("public.tbl_benutzer benutzer", "uid = student_uid", "LEFT");
$this->addJoin("public.tbl_person person", "person_id", "LEFT");
$this->db->where($this->dbTable . ".freigabedatum <", "NOW()", false);
@@ -188,6 +188,7 @@ class Studierendenantrag_model extends DB_Model
* Get the studiengang and ausbildungssemester the student was in
* for the studiensemester the antrag was committed for
*
*
* @param integer $antrag_id
*
* @return stdClass
@@ -242,6 +243,28 @@ class Studierendenantrag_model extends DB_Model
);
}
/**
* Get the studiengang and the studienplan the student is in
*
* @param integer $antrag_id
*
* @return stdClass
*/
public function getStgAndDetails($antrag_id)
{
$this->addSelect('p.studiengang_kz');
$this->addSelect('stg.orgform_kurzbz');
$this->addSelect('stg.bezeichnung');
$this->addJoin('public.tbl_prestudent p', 'prestudent_id');
$this->addJoin('public.tbl_studiengang stg', 'studiengang_kz');
$this->addLimit(1);
return $this->load(
$antrag_id
);
}
public function getStgEmail($antrag_id)
{
$this->addJoin('public.tbl_prestudent p', 'prestudent_id');
@@ -148,7 +148,7 @@ class Zeugnisnote_model extends DB_Model
*
* @return object
*/
public function getZeugnisnoten($student_uid, $studiensemester_kurzbz)
public function getZeugnisnoten($student_uid, $studiensemester_kurzbz, $lehrveranstaltung_id = null)
{
$params = array();
$where='';
@@ -163,6 +163,11 @@ class Zeugnisnote_model extends DB_Model
$where.=" AND vw_student_lehrveranstaltung.studiensemester_kurzbz= ?";
$params[] = $studiensemester_kurzbz;
}
if($lehrveranstaltung_id != null)
{
$where .= " AND vw_student_lehrveranstaltung.lehrveranstaltung_id = ?";
$params[] = $lehrveranstaltung_id;
}
$where2='';
@@ -176,6 +181,11 @@ class Zeugnisnote_model extends DB_Model
$where2 .= " AND studiensemester_kurzbz= ?";
$params[] = $studiensemester_kurzbz;
}
if($lehrveranstaltung_id != null)
{
$where2 .=" AND lehrveranstaltung_id = ?";
$params[] = $lehrveranstaltung_id;
}
$qry = "SELECT
a.*,
@@ -188,7 +198,10 @@ class Zeugnisnote_model extends DB_Model
lv.semester AS semester_lv,
lv.ects AS ects_lv,
lv.zeugnis,
lv.bezeichnung_english AS lehrveranstaltung_bezeichnung_english
lv.bezeichnung_english AS lehrveranstaltung_bezeichnung_english,
s.verband,
person.vorname,
person.nachname
FROM (
SELECT vw_student_lehrveranstaltung.lehrveranstaltung_id, uid,
vw_student_lehrveranstaltung.studiensemester_kurzbz, note, punkte, uebernahmedatum, benotungsdatum,
@@ -231,6 +244,8 @@ class Zeugnisnote_model extends DB_Model
ORDER BY sort
) a
LEFT JOIN public.tbl_student s ON (a.uid = s.student_uid)
LEFT JOIN public.tbl_benutzer benutzer ON benutzer.uid = s.student_uid
LEFT JOIN public.tbl_person person ON benutzer.person_id = person.person_id
LEFT JOIN public.tbl_studiengang stg1 ON (s.studiengang_kz = stg1.studiengang_kz)
LEFT JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
LEFT JOIN public.tbl_studiengang stg2 ON (lv.studiengang_kz = stg2.studiengang_kz)";
@@ -11,4 +11,26 @@ class Gruppe_model extends DB_Model
$this->dbTable = 'public.tbl_gruppe';
$this->pk = 'gruppe_kurzbz';
}
public function search($query_words)
{
$this->addSelect('gruppe_kurzbz,
studiengang_kz,
semester,
bezeichnung,
gid,
\'false\' as lehrverband');
$this->db->where(array('sichtbar' => true, 'aktiv' => true, 'lehre' => true, 'direktinskription' => false, 'semester IS NOT NULL' => null));
$this->db->group_start();
foreach ($query_words as $word)
{
$this->db->group_start();
$this->db->where('gruppe_kurzbz ILIKE', "%" . $word . "%");
$this->db->or_where('bezeichnung ILIKE', "%" . $word . "%");
$this->db->group_end();
}
$this->db->group_end();
return $this->load();
}
}

Some files were not shown because too many files have changed in this diff Show More