Compare commits

..

1640 Commits

Author SHA1 Message Date
Johann Hoffmann 1feb4ff4fd code cleanup 2025-07-15 09:43:38 +02:00
Johann Hoffmann 34865bc0c0 code cleanup 2025-07-14 17:04:56 +02:00
Johann Hoffmann 8cd0f4c8bd parameterized server/user/pw for both browser url calls & cli calls; 2025-07-14 16:47:41 +02:00
Johann Hoffmann ffaf360ea0 proof of concept Blackbox TestSuite using httpful to call Bookmark API Controller and test for expected responses; cleanup old phpunit testing attempt relics; WIP enhancing the script/helper functions further; 2025-07-14 15:44:27 +02:00
Paolo f888dcc72d Removed directory tests and all its content 2025-06-10 11:56:11 +02:00
Szabo Mónika 664796c69f using phpunit to test controllers which are running in codeigniter3 requires further request/response mocking; setup of swagger-ui and swagger openapi doc generation for bookmark.php; WIP integration tests with ci3 & phpunit, maybe annotation generation solution for swagger annotations 2025-05-05 18:37:00 +02:00
Johann Hoffmann 37fa899540 phpunit test cases runnable; WIP teaching phpunit what a codeigniter3 is 2025-04-30 17:32:23 +02:00
Andreas Österreicher 24b19a1d8b Workaround für Bug in Firefox ab Version 137 wodruch der Weiter Button nicht immer ganz
angezeigt wird
2025-04-30 10:33:37 +02:00
Andreas Österreicher edcd2aa1df Merge branch 'feature-61464/infocenter_ausbildungssemester' 2025-04-28 13:23:38 +02:00
Harald Bamberger 9410388a7a tune order by to sort nearest active dv first 2025-04-24 15:40:58 +02:00
Harald Bamberger a196da03d2 change order by to ensure latest dv is sorted first 2025-04-24 10:52:47 +02:00
Harald Bamberger 34eb2ab80c check permission system_change_outputformat in final exam on degree program oe_kurzbz 2025-04-22 11:11:46 +02:00
Harald Bamberger ced54d76d5 Merge branch 'feature-55980/gehaltsbestandteile_export_filtern_summieren' 2025-04-17 18:43:51 +02:00
Harald Bamberger 7b30869f7c make where clause more precise 2025-04-17 18:28:26 +02:00
ma0048 d4012232ab ausbildungssemester hinzugefuegt 2025-04-17 11:01:33 +02:00
Harald Bamberger ac5e95e6b9 dbchanges: add columns lvexport and lvexport_sum to hr.tbl_gehalstyp, add gehaltstyp zulage_allin, set zulage_allin for gbs attached to vbs freitext allin 2025-04-17 08:20:30 +02:00
Harald Bamberger b323f91999 Merge branch 'feature-60851/FhcApi_Factory_Refactoring' 2025-04-15 16:49:17 +02:00
Harald Bamberger 99587fd064 Merge branch 'master' into feature-60851/FhcApi_Factory_Refactoring 2025-04-15 16:20:34 +02:00
Harald Bamberger b67b19bd1a handle condition when endpoint has not been set 2025-04-15 15:38:27 +02:00
ma0068 26d7d17169 delete unneeded code, fix permission issue 2025-04-15 15:21:36 +02:00
Harald Bamberger b2a7ec6e67 add component names, Modal dynamically import new phrases plugin to created app 2025-04-15 14:52:24 +02:00
Harald Bamberger 9c5ebc902d fix typos, remove duplicate attribute 2025-04-15 14:51:10 +02:00
Harald Bamberger 3669e0df40 check if entry in tbl_studentlehrverband exits and update or insert on result 2025-04-15 08:24:16 +02:00
Harald Bamberger 26bf1e33d4 close button tags 2025-04-14 17:32:13 +02:00
kindlm e8a233e503 Merge remote-tracking branch 'origin/master' 2025-04-14 17:13:15 +02:00
kindlm 1cb29ce8bb Task #61376 CIS Gesamtnote Berechtigung für OE 2025-04-14 17:13:03 +02:00
Harald Bamberger 31c1b087e5 fix typo, readd showallformats lookup since isBerechtigtDocAndOdt is an array of oe_kurzbzs 2025-04-11 17:51:34 +02:00
Harald Bamberger 9f94c8fafd fix typo 2025-04-11 17:22:37 +02:00
Harald Bamberger a5b8e7dc8b fix typo 2025-04-11 17:14:54 +02:00
Harald Bamberger f7138b2cfc prevent loading old phrasen plugin when Modal component is used, only commented out since plugin is maybe needed in ModalApp in some cases 2025-04-11 17:00:39 +02:00
Harald Bamberger 7f7a423e65 prevent loading old and new FhcAlert plugin resulting in two FhcAlert Apps and showing e.g. two delete confirm Dialogs 2025-04-11 16:57:20 +02:00
Harald Bamberger 75338a89c7 fix edit modal for bankdata not opening 2025-04-11 16:55:35 +02:00
Harald Bamberger 3c3e2ae662 add name to studentenverwaltung app 2025-04-11 16:53:39 +02:00
Harald Bamberger f45e0105b0 fix typo 2025-04-07 15:54:32 +02:00
Harald Bamberger 242cee2b62 Merge branch 'feature-61228/FHC4_Studierendenverwaltung_SetNameAttributes' into feature-60851/FhcApi_Factory_Refactoring 2025-04-07 13:26:49 +02:00
Harald Bamberger 48a9ca0ff4 Merge branch 'master' into feature-61228/FHC4_Studierendenverwaltung_SetNameAttributes 2025-04-07 13:23:24 +02:00
Harald Bamberger cbd3c86e59 studiensemester dropdown order desc 2025-04-07 11:44:25 +02:00
cgfhtw 49cfeddfa2 LvTemplateUebersicht: use new API 2025-04-04 12:35:51 +02:00
cgfhtw 93689e3906 $fhcApi on plugins: error => warning 2025-04-04 12:35:33 +02:00
ma0068 92a05c4711 reset config use_vuejs_dev_version 2025-04-04 09:35:37 +02:00
ma0068 bef3e88e92 name attributes for components added 2025-04-04 09:33:44 +02:00
Harald Bamberger 8c0325b693 fix template compilation errors 2025-04-03 16:35:29 +02:00
Harald Bamberger 9572bdf3eb Merge branch 'master' into feature-60851/FhcApi_Factory_Refactoring 2025-04-03 15:58:45 +02:00
Harald Bamberger 97782b7f1d Merge branch 'feature-60863/Betragspalte_Sachaufwand' 2025-04-03 11:12:31 +02:00
Harald Bamberger 315b763380 Merge branch 'master' into feature-60863/Betragspalte_Sachaufwand 2025-04-03 11:10:52 +02:00
Andreas Österreicher b41baad89d Merge branch 'Monika70-lvgesamtnoteverwalten' 2025-04-03 07:43:02 +02:00
Andreas Österreicher cc51e7f04a Merge branch 'lvgesamtnoteverwalten' of github.com:Monika70/FHC-Core into Monika70-lvgesamtnoteverwalten 2025-04-03 07:38:03 +02:00
Andreas Österreicher 2a2e2ea193 Warteliste Message angepasst damit die Tagesgrenze korrekt vom
Wartenden-Status ermittelt wird
2025-04-02 16:55:31 +02:00
Harald Bamberger a54f7531bf add column betrag to table hr.tbl_sachaufwand 2025-04-02 16:07:09 +02:00
Andreas Österreicher 7345dd258d Merge branch 'feature-56033/Beurteilungsformulare_neue_Kategorien_ab_SS2025' 2025-04-01 11:17:51 +02:00
Andreas Österreicher 8a7290359a Merge branch 'master' into feature-56033/Beurteilungsformulare_neue_Kategorien_ab_SS2025 2025-04-01 10:52:04 +02:00
Harald Bamberger e809e48262 fix order of parameters 2025-03-31 15:40:18 +02:00
kindlm 86158e6f28 Merge remote-tracking branch 'origin/master' 2025-03-30 00:40:14 +01:00
kindlm 7c61ee55c2 Fragensumme in Übersicht eingefügt 2025-03-30 00:40:08 +01:00
Andreas Österreicher 5197037126 Merge branch 'feature-60880/pep_finetuning_spring_231' 2025-03-28 08:59:00 +01:00
kindlm 1e2a4d202f Fix Typo PrueferIn 2025-03-27 13:57:44 +01:00
kindlm b32f60874c Merge remote-tracking branch 'origin/master' 2025-03-27 11:55:58 +01:00
kindlm 78c23699d5 TinyMCE-Editor bei Ampeldetails 2025-03-27 11:55:41 +01:00
Andreas Österreicher 8178368113 Merge branch 'feature-40953/LV-Template_Uebersichtsseite' 2025-03-27 09:34:06 +01:00
Andreas Österreicher 392c15da77 Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2025-03-27 09:32:59 +01:00
cgfhtw c780b29732 load new API in old API 2025-03-26 09:20:58 +01:00
kindlm f55c309692 Fehlende Tabellen beim Löschen von Personen ergänzt 2025-03-25 16:33:13 +01:00
kindlm c569af6d0f Löschen bei Personensuche löscht auch Testtooleinträge 2025-03-25 16:07:42 +01:00
kindlm ce54cf3c9c Bugfixes Studentenmeldung 2025-03-25 16:07:09 +01:00
kindlm fae299847e Messaging-Fenster scrollt automatisch nach oben 2025-03-25 15:56:55 +01:00
kindlm 742ae40d98 Link Zugangscode öffnet nicht sondern kopiert in zwischenablage 2025-03-25 15:56:30 +01:00
Andreas Österreicher 4c38d88840 Merge branch 'feature-61109/infocenter_anzahlung_auf_kaution_aendern' 2025-03-24 16:45:49 +01:00
ma0048 7126ab4561 - "Kaution" - column: buchungstyp von anzahlung auf kaution geandert 2025-03-24 14:33:34 +01:00
cgfhtw 9f06fbcf93 refactor fhcApi 2025-03-24 13:38:49 +01:00
Andreas Österreicher a6ee6a8c0f ReihungstestJob angepasst damit Drittstaatenkaution berücksichtigt wird.
Fehler behoben beim setzen des Abgewiesenen Status das nicht in allen
Fällen funktioniert hat
2025-03-24 11:45:58 +01:00
Andreas Österreicher 45f3acf922 Merge branch 'feature-37620/reihungslisten' 2025-03-24 10:24:01 +01:00
Andreas Österreicher 08e38078a0 Removed duplicate Confirm 2025-03-24 09:57:46 +01:00
Andreas Österreicher 410231a427 Merge branch 'master' into feature-37620/reihungslisten 2025-03-24 09:18:26 +01:00
Cristina b18b3b62a7 Merge remote-tracking branch 'origin/feature-40953/LV-Template_Uebersichtsseite' into feature-40953/LV-Template_Uebersichtsseite
# Conflicts:
#	system/phrasesupdate.php
2025-03-20 13:29:49 +01:00
Cristina 2a4f1af69f Added phrase lizenzkategorie to Softwarebereitstellung app 2025-03-20 11:41:47 +01:00
Cristina b8417869b5 Added phrase lizenzkategorie to Softwarebereitstellung app 2025-03-20 11:18:26 +01:00
ma0048 0a2bd1bdde - stundengrenze bei dummy nicht beruecksichtigen 2025-03-18 14:02:23 +01:00
Harald Bamberger f6352211f2 Merge branch 'feature-55614/Uebersichten_LV_TPL_QK_OP' 2025-03-17 12:56:59 +01:00
Szabo Mónika 2901847788 Update lvgesamtnoteverwalten.php
Der Lehrveranstaltungstyp wurde in der E-Mail über die freigegebenen Noten hinzugefügt.
2025-03-12 15:11:00 +01:00
Andreas Österreicher dc51e9bd85 Merge branch 'bug-56084/PHP_Notice_bei_Lehrauftrag_Erteilen_Bestellen' 2025-03-12 12:08:49 +01:00
Harald Bamberger 129637cf4f add phrases for lvdev overviews 2025-03-12 12:05:34 +01:00
Harald Bamberger ff65852643 neues recht basis/verwaltet_oe 2025-03-12 08:21:03 +01:00
Cristina ed2f895d8b Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2025-03-11 17:35:34 +01:00
Cristina f219a19dec Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-03-11 16:31:48 +01:00
Harald Bamberger 1f5925e860 searchbar restults mobile improve css selector, alter student result view 2025-03-10 17:11:03 +01:00
Harald Bamberger b9823a0278 set overscrollbehavior none for all dashboard-items 2025-03-10 14:39:31 +01:00
Harald Bamberger 2b4ccab2f1 studiengang info widget decrease size of headings 2025-03-10 14:30:28 +01:00
Harald Bamberger fad5f8b9d0 increase height of iframe especially for mobile view 2025-03-10 11:28:29 +01:00
Johann Hoffmann d349a64ca8 fix news widget carousel (re)initialization after resize 2025-03-06 16:19:49 +01:00
Andreas Österreicher 21e3169d8d Merge branch 'bug/pep_suche_lehre' 2025-03-06 11:58:56 +01:00
ma0048 740a473c8d tagheaderfilter fix 2025-03-06 11:55:25 +01:00
Cristina 83fe68c04e Removed 2 methods getNonQuellkursLvs and getNonQuellkursLvsAutocompleteSuggestions from Lehrveranstaltung_model.php 2025-03-06 10:39:00 +01:00
Andreas Österreicher c84ffdf893 Merge branch 'pep_deploy_2025_03_06' 2025-03-06 10:36:26 +01:00
Cristina eedbab21a2 Added phrases for Softwarebereitstellung 2025-03-06 09:58:15 +01:00
Cristina 3a83d468ef Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2025-03-06 09:50:55 +01:00
Cristina 85ef49bb62 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-03-06 09:48:58 +01:00
Cristina aab0dd7fc7 Added / Adapted Model queries and api Controller regarding for Lehrveranstaltung- and Studienjahr Model 2025-03-06 09:40:40 +01:00
Harald Bamberger bd7669ff5b Merge branch 'merge_FHC4_C4' 2025-03-05 17:37:16 +01:00
Harald Bamberger 00b766cb69 tweak mobility form behavior 2025-03-05 17:35:27 +01:00
ma0048 663ff947b0 prepare for deploy 2025-03-05 15:19:24 +01:00
ma0048 11ba9c9911 Merge branch 'refs/heads/feature-55289/pep_fine_tuning' into pep_deploy_2025_03_06
# Conflicts:
#	system/dbupdate_3.4.php
2025-03-05 15:15:57 +01:00
ma0048 f942836453 Merge remote-tracking branch 'origin/feature-54945/filtercomponent_custom_headerfilter_datum' into pep_deploy_2025_03_06
# Conflicts:
#	public/js/tabulator/filters/defaultHeaderFilter.js
2025-03-05 15:14:49 +01:00
Alexei Karpenko 2cbbcc9039 changed Projektarbeitsbeurteilung phrase 2025-03-05 14:52:55 +01:00
SimonGschnell 97ee1f8144 fix(News Widget animation): fixes the animation bug when changing the width of the News widget from 1 to >1 2025-03-05 13:42:37 +01:00
SimonGschnell c22118a26c fix(VueRouter News Ansicht):News ansicht konnte nicht geladen werden weil viewData im Cms controller nicht uebergeben wurde aber im CisRouterView verwendet wird 2025-03-05 10:49:03 +01:00
SimonGschnell c677c48b00 fix(StudiengangsInformationen API data): fixes little error when checking if the uid is a mitarbeiter or not 2025-03-05 10:47:45 +01:00
ma0068 188e6db759 bugfix: update sqls with LEFT condiiton 2025-03-05 08:49:42 +01:00
ma0068 588834d73f add click event to enable new choice for lehreinheit dropdown 2025-03-04 15:11:22 +01:00
Harald Bamberger fe4c14f75f Merge branch 'merge_FHC4_C4' 2025-03-04 14:40:13 +01:00
ma0068 45fd48a50e add watcher for resetting lehreinheit 2025-03-04 14:33:20 +01:00
ma0068 d39dfbc41b use loadItems with second condition 2025-03-04 14:11:40 +01:00
ma0068 e69a9eeadb set 1st condition to not disabled 2025-03-04 14:02:50 +01:00
ma0068 eb958d19c8 set 3rd condition to not disabled 2025-03-04 14:00:13 +01:00
ma0068 358480600e add condition existing lehreinheit and not existing lv_id 2025-03-04 13:58:02 +01:00
ma0068 d5eae17ba5 extend queries for lehrveranstaltung_id to see dropdown 2025-03-04 13:49:39 +01:00
Harald Bamberger 93ff868501 ensure student_uids is an array even if only one uid is passed 2025-03-04 11:23:46 +01:00
ma0068 701c57966f tab contact - field plz: numberformat validation only for Austria 2025-03-04 10:53:03 +01:00
ma0068 c2691f867d form Abschlusspruefung as modal 2025-03-04 09:57:25 +01:00
ma0068 8320de66bc redesign dropdown mobility-support with overriding filtercomponent 2025-03-04 08:26:07 +01:00
Harald Bamberger 091aa1917b set maxwidth for frozen actions column 2025-03-03 17:17:25 +01:00
ma0068 f471321b98 Merge branch 'merge_FHC4_C4' of github.com:FH-Complete/FHC-Core into merge_FHC4_C4 2025-03-03 16:40:15 +01:00
ma0068 1944152d13 redesign dropdown mobility-properties with overriding filtercomopnent actions 2025-03-03 16:40:05 +01:00
Harald Bamberger 9aa8c33e83 fix use of confirm dialog with rewritten factory calls 2025-03-03 15:26:54 +01:00
ma0068 20fc528107 Use Modal for Mobility Tab 2025-03-03 15:10:01 +01:00
Paolo c028a769cc TableWidget bug: the bootstrapVersion was provided with the tableUniqueId, not needed 2025-03-03 13:44:40 +01:00
ma0068 50ec93f5c1 extend function getLesFromLvIds for studiensemesterkurzb and aggregation lehreinheit_id 2025-03-03 13:43:19 +01:00
Alexei Karpenko e61b6b447c Abgabetool: removed hyperlink from benoten button quickinfo 2025-03-03 13:37:33 +01:00
Alexei Karpenko 037811c24c Paarbeitsabgabe: replaced num_rows_sem with new paiscurrent variable 2025-03-03 12:39:07 +01:00
ma0068 da9afa5c67 Merge branch 'merge_FHC4_C4' of github.com:FH-Complete/FHC-Core into merge_FHC4_C4 2025-03-03 11:54:13 +01:00
Harald Bamberger 409a70bdf9 add form as first param 2025-03-03 11:47:30 +01:00
ma0068 05a6109c27 Merge branch 'merge_FHC4_C4' of github.com:FH-Complete/FHC-Core into merge_FHC4_C4 2025-03-03 11:46:12 +01:00
ma0068 b50a4a16d1 change form parameter mobility and add param studiensemester_kurzbz to function get LVsandLesByStudent 2025-03-03 11:45:31 +01:00
Harald Bamberger 1fbc552d30 fix factory losing enpoints when person search is called before 2025-03-03 10:45:02 +01:00
Harald Bamberger 28f11d7550 Merge branch 'bhdev_tabulator6' into merge_FHC4_C4 2025-02-28 14:35:17 +01:00
Alexei Karpenko a63c321f97 added Projektarbeitsbeurteilung phrases 2025-02-28 12:09:26 +01:00
Alexei Karpenko c07c4ef4c9 Merge branch 'master' into feature-56033/Beurteilungsformulare_neue_Kategorien_ab_SS2025 2025-02-27 15:46:09 +01:00
Harald Bamberger 80b67ad416 add tabulator6 2025-02-27 11:35:21 +01:00
ma0048 55312848a3 Merge remote-tracking branch 'origin/feature-55289/pep_fine_tuning' into feature-55289/pep_fine_tuning 2025-02-27 09:08:29 +01:00
ma0048 737c9937c9 - namen bei tags
- phrasen hinzugefuegt
2025-02-27 09:07:23 +01:00
Andreas Österreicher 1cecdcb8ef Berechtigung fuer begrenzte Reports umbenannt 2025-02-26 16:24:46 +01:00
Harald Bamberger fe98eb2784 add missing .js file extension to import statement 2025-02-26 15:34:49 +01:00
ma0048 ab20943493 - filter aus dem defaultfilter entfernt
- tagfilter hinzugefuegt
- clear filter hinzugefuegt
- persistence default auf false gesetzt
2025-02-24 08:58:35 +01:00
Harald Bamberger ba594a320b Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-24 08:50:04 +01:00
Harald Bamberger 9876976c70 Merge branch 'master' into merge_FHC4_C4 2025-02-24 08:46:48 +01:00
Johann Hoffmann 7a0a2d756d load lv entry as meta info when querying stundenplan by lva & show titel in ger/eng; also show currently active Studiensemester; roomInfo constant defined aswell; 2025-02-21 14:16:11 +01:00
Johann Hoffmann 844c31885e defined row min height & event max height props; month event click opens lv modal; fixed off by one date state; 2025-02-20 16:25:57 +01:00
Johann Hoffmann 3d467524e4 change Stundenplan/Rauminfo currentDay on prev/next event by certain offset and update url/browser history 2025-02-20 12:59:28 +01:00
Johann Hoffmann 1d9ea5d091 router click intercepter does not resolve internally when only matched route was the Fallback matchAll route; cleanup routes.php & Stundenplan controller from viewData and verbose reroutes; overflow setting on years page; 2025-02-20 11:22:30 +01:00
kindlm dd2a13d92d Korrektur DMS-Link 2025-02-19 18:02:30 +01:00
kindlm 2946d59e7a Merge remote-tracking branch 'origin/master' 2025-02-19 18:01:46 +01:00
Andreas Österreicher 7c57a145bd Merge branch 'hotfix-55802/Composer_dead_github_repository' 2025-02-19 15:49:48 +01:00
Andreas Österreicher 661be92fed Merge branch 'bug-54831/Logs_Viewer_Filter_Error' 2025-02-19 15:40:25 +01:00
Paolo 37f86f651e Fixed string casting of the condition for the filter component
Fixed CSS for the error box in the logs viewer filter
2025-02-19 15:37:51 +01:00
Harald Bamberger 11e8ffb22c Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-19 14:25:04 +01:00
Harald Bamberger 157ffd00f2 Merge branch 'master' into merge_FHC4_C4 2025-02-19 14:24:14 +01:00
Andreas Österreicher bbd70749fe Projektexport angepasst damit die Überschriften aufgrund der
Beschreibung erstellt werden anstatt auf Basis der Bezeichnung da diese
öfter abgeschnitten werden und es dadurch gleich benannte Spalten gibt
und dadurch eine nicht korrekt angezeigt wird
2025-02-19 11:41:46 +01:00
Johann Hoffmann 714d74d9aa url widget template fix 2025-02-19 11:25:29 +01:00
Johann Hoffmann b817458222 lv menu events send phrasenkey to enable responsive localization in myLv 2025-02-18 17:36:48 +01:00
Johann Hoffmann cb42ba110e adapt new calendar url format for rauminfo page; readded vue router dashboard fallback since there are possible url combinations that can not be resolved properly; 2025-02-18 16:31:05 +01:00
Johann Hoffmann 8e76d93a5a consistent naming of calendar modes in english; fixed routerguard to work with router.push on mode or date changes inside stpl component; 2025-02-18 14:48:14 +01:00
Johann Hoffmann e2e537b09c fix calendar mode watch/emit handling; WIP roomInfo routes 2025-02-18 10:55:46 +01:00
Johann Hoffmann d45a41b949 defined new CI routes to differentiate between 5 cases CI doesnt handle anymore but vue router does; define Stundenplan/:lv_id? route for old links to redirect to new route Stundenplan/:mode/:focus_date/lv_id; new route with props route param handling to put them into viewData to always check for the same object; define day as allowed init mode; WIP same thing for raum calendar page; 2025-02-18 10:18:39 +01:00
Alexei Karpenko 9fb2ea4ae3 Projektarbeitsbeurteilung: added authorization (Berechtigungen) check to document export 2025-02-17 19:03:53 +01:00
kindlm a557cd8d7c Merge remote-tracking branch 'origin/master' 2025-02-17 16:50:26 +01:00
kindlm b89eef0525 Minor Bug/Typo-fixes in testtool
- Soundtest aus testseite.php ausgeblendet
- Studiengangsname nach Login aus Studienordnung
- Bei Übersicht wird nun auch Text angezeigt, wenn ein Bild ausgegeben wird
2025-02-17 16:50:07 +01:00
Alexei Karpenko 57eec9b940 adapted document export to new Projektarbeit version (percent assessment) 2025-02-14 23:47:19 +01:00
Alexei Karpenko 7083955702 changed Proektarbeitsbeurteilung phrases 2025-02-14 16:44:33 +01:00
Harald Bamberger 48ef35c0e9 Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-14 14:58:46 +01:00
Harald Bamberger f6f06c4d5e use attribute binding since value should be boolean 2025-02-14 14:58:12 +01:00
Harald Bamberger b01400d21c remove unused data declaration 2025-02-14 14:55:57 +01:00
Harald Bamberger 92ba4aea9a return year as number not as string 2025-02-14 14:53:19 +01:00
Johann Hoffmann 7fed1d231c p.t( -> $p.t( in stundenplan & mylv components, added missing phrasen; WIP adding phrasen keys for noten, maybe for lva titles 2025-02-14 14:49:28 +01:00
Johann Hoffmann 3a1055d87e computed phrasen in column titles student profil for zutrittsgruppen/betriebsmittel; samilar to mitarbeiter profil 2025-02-14 13:54:02 +01:00
Johann Hoffmann bb69e07340 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2025-02-14 13:35:48 +01:00
Johann Hoffmann ff8d1c78fd funktionen/betriebsmittel table in profil & viewprofil got computed phrasen title; provide computed language reference in fhc app from phrasen plugin to watch for language changes to reevaluate computed phrasen in columns with; added some phrasen; 2025-02-14 13:34:52 +01:00
Harald Bamberger 350980c5df Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-14 13:33:52 +01:00
Harald Bamberger cff606815e fix TransitionGroup children have to be keyed when adding a new widget to dashboard 2025-02-14 13:33:29 +01:00
Harald Bamberger ee0e5fe40e Merge branch 'master' into merge_FHC4_C4 2025-02-14 13:25:14 +01:00
Johann Hoffmann ff60de5772 anrechnungen reload page on languageChange in php template site with cis4Reload attribute set; 2025-02-14 11:26:14 +01:00
Andreas Österreicher 470eac7d3c Merge branch 'feature-46784/cronjob_reihungstest_warteliste_anpassen' 2025-02-14 08:18:16 +01:00
Johann Hoffmann 40db480489 stundenplan widget header format as per fhc locale 2025-02-13 17:46:28 +01:00
Johann Hoffmann 43e3fdcc46 remove log 2025-02-13 17:28:34 +01:00
Johann Hoffmann 4de9441699 fix accessing fhc language locale .locale -> .LC_TIME 2025-02-13 17:25:24 +01:00
Johann Hoffmann 47293a81d3 avoid persisting invisible column definitions on funktionen table 2025-02-13 13:40:24 +01:00
Johann Hoffmann 139a2f900f watch for changing betriebsmittel & funktionen data; wait for loaded viewData before rendering greeting; 2025-02-13 12:41:24 +01:00
Johann Hoffmann 2d5309f97d fix invisible funktionen/betriebsmittel tabulator columns; fix phrasen roleInfo studentViewProfil; 2025-02-13 12:06:41 +01:00
Alexei Karpenko de895362be changed Projektarbeitsbeurteilung phrases even more 2025-02-12 19:28:27 +01:00
Alexei Karpenko 92f3f0d89c changed Projektarbeitsbeurteilung phrases 2025-02-12 19:15:43 +01:00
Harald Bamberger 2f47cc7966 Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-12 17:58:37 +01:00
Harald Bamberger 9bcd566bee fix TransitionGroup children have to be keyed and duplicate attribute v-bind 2025-02-12 17:57:53 +01:00
Harald Bamberger a6e0f10f32 use correct path to searchbar.css 2025-02-12 17:56:10 +01:00
Johann Hoffmann 480bef3b0d student profile role info verband/gruppe/semester links to old cis list; reworked role info data to also work in english lol; 2025-02-12 17:24:37 +01:00
Johann Hoffmann e6edd42737 profil remove console.log, added missing phrase 2025-02-12 14:34:52 +01:00
Johann Hoffmann 60e12e1ab7 dont load any studiengang related infos for mitarbeiter 2025-02-12 14:04:23 +01:00
Harald Bamberger 09aae4c82b Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-12 13:47:24 +01:00
Harald Bamberger d8438b4f4c Merge branch 'master' into merge_FHC4_C4 2025-02-12 13:44:39 +01:00
Johann Hoffmann a9e3a85d99 format gebdatum for profil in sql; fix show telefonnummer in profil; 2025-02-12 13:44:32 +01:00
Johann Hoffmann 8525c82305 set menuEntry href based on link form -> no href on menus without full url, hash links on menus dont trigger routing anymore; news widget check if carousel exists on mounted nextTick; 2025-02-12 11:56:12 +01:00
SimonGschnell bcb88c0cb7 refactor(Calendar Month View): instead of using border when highlighting the current day, uses box-shadow so that the content inside the highlighted day does not shift because of the width of the additional border 2025-02-12 11:11:23 +01:00
ma0068 ca187efce4 bugfix: deleted outputJson returns 2025-02-11 15:58:31 +01:00
Johann Hoffmann bdb312cf56 img parse only after usual procedure failed 2025-02-11 15:16:07 +01:00
Johann Hoffmann 2b27b55f40 attempt sanitizing raum content when content is just h1 + img tag; sanitize tables on raum contents sites 2025-02-11 15:05:22 +01:00
Andreas Österreicher f25a969a6b Merge branch 'feature-33683/digi_anw_core_ss2025' 2025-02-11 13:19:30 +01:00
Johann Hoffmann fe4351fc87 lv info ort content link when content_id was expanded 2025-02-11 11:23:50 +01:00
Johann Hoffmann eabe8ef401 CalendarDate patch schaltjahr 2025-02-11 10:15:22 +01:00
Harald Bamberger 36d3af91f1 Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-11 09:44:38 +01:00
ma0048 df685133b5 - date filter 2025-02-11 08:58:00 +01:00
Johann Hoffmann 4936cfd61c added roomInfo to app routes & remove old views; stundenplan reservierungen for MA working WIP roomInformation/roomContent link from lvinfo event ort_kurzbz; 2025-02-10 17:05:27 +01:00
Johann Hoffmann deea005f5b recommit anw related core changes without wrongfully merged branches tail of feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp 2025-02-10 14:24:15 +01:00
Alexei Karpenko 4ccbdecc48 added phrases for new Beurteilungsformular 2025 2025-02-10 13:37:53 +01:00
ma0048 83baa0ed8b - fehlende phrase 2025-02-10 12:59:18 +01:00
ma0068 bca95bcb66 change dateFormat Tab Notizen 2025-02-10 11:04:02 +01:00
ma0068 f653c2c054 change dateFormat Tab Mobility 2025-02-07 14:06:48 +01:00
ma0068 72649f4177 change dateFormat Tab Contact 2025-02-07 13:52:17 +01:00
ma0068 5ae9a99de4 change dateformats Tab Status 2025-02-07 13:39:51 +01:00
ma0068 5ec886e815 Tab Abschlusspruefung: return nothing in case of null date 2025-02-07 13:21:58 +01:00
ma0068 21ecbf482f change dateformate Betriebsmittel 2025-02-07 13:16:59 +01:00
Harald Bamberger acc57bbebd fix problem with vanishing factory entries when called via Form.js computed factory 2025-02-07 11:46:02 +01:00
ma0068 3db367b255 bugfix Uhrzeit, datumsformat for tab abschlusspruefung 2025-02-07 09:34:07 +01:00
Harald Bamberger 6ac91dc016 add mustache brackets to phrases in template 2025-02-06 16:26:28 +01:00
Harald Bamberger cb46dff548 fix props declarations 2025-02-06 16:25:41 +01:00
Harald Bamberger 83321ac2ab fix props declarations 2025-02-06 16:25:00 +01:00
Harald Bamberger 4fe801ddf9 fix props declarations 2025-02-06 16:24:34 +01:00
Harald Bamberger a507533f40 use getStudiengangByKz to get stgtyp and stg_oe_kurzbz for checking showallformats permission, add and use phrase notekommpruefung 2025-02-06 16:23:42 +01:00
Harald Bamberger 0cca508881 add Studiengang Endpoint getStudiengangByKz 2025-02-06 16:19:27 +01:00
Johann Hoffmann fc06ffe0e5 fix jumping into march 01 from january 29 2025-02-06 13:18:19 +01:00
Harald Bamberger 3ce803684a change prop type to String since an uid is passed 2025-02-06 11:33:38 +01:00
Harald Bamberger e4e6849351 cleanup duplicate attribute definition 2025-02-06 11:31:25 +01:00
Harald Bamberger 2008fc2a15 remove duplicate attribute definition 2025-02-06 11:26:35 +01:00
Harald Bamberger 422ce28703 use correct phrases category 2025-02-06 11:25:57 +01:00
Harald Bamberger 9d0e365516 use tabulator header filters 2025-02-05 18:49:46 +01:00
Harald Bamberger 3fff535713 prevent custom defaultHeaderFilter breaking tristate built-in filter 2025-02-05 18:49:07 +01:00
Harald Bamberger 9745621975 remove duplicate pharse bankverbindung category person 2025-02-05 17:08:20 +01:00
Johann Hoffmann a0ddde4978 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2025-02-05 17:02:55 +01:00
Johann Hoffmann e901d414a0 lane overlay div up to certain % instead of all day opaque or not; defined hours length and calculating accurate lane width from that; 2025-02-05 17:02:21 +01:00
Harald Bamberger 61ec4ce6c1 Merge branch 'master' into merge_FHC4_C4 2025-02-05 16:58:20 +01:00
Harald Bamberger 4410baf7ac Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-05 16:57:52 +01:00
Harald Bamberger 99c3403009 check against information schema if column exists 2025-02-05 16:55:48 +01:00
Johann Hoffmann b198b6a961 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2025-02-05 16:05:04 +01:00
Johann Hoffmann b8823052f5 deactivate old month page css for day number and events in favor of new computed style (can be redesigned but is being handled in js instead of css class); save & inject/provide observed resize from already existing ResizeObserver to be able to access concrete container width/height values we already had all the time anyway; added some comment to 2year old TODO concerning calendar breakpoints; check if navbar is showing before toggling programmatically; remove some unused code; week time line spawns in dayLane which is representing today to avoid caluclating left/right offsets -> WIP accurately retrieving lane width somehow else, currently approximated; 2025-02-05 16:03:20 +01:00
Andreas Österreicher 40d2a657c6 Merge branch 'feature-28394/zeiterfassung_50_tage_ansicht_als_vorgesetzter_fuer_mitarbeiter' 2025-02-05 14:07:44 +01:00
SimonGschnell 7c8508da0e update(Infoterminal authentification): adds a query parameter to the infoterminal view that enables authentification 2025-02-05 12:50:23 +01:00
Harald Bamberger d038119a3b adapt infoterminal page so that login can be forced 2025-02-05 11:41:02 +01:00
SimonGschnell d889756302 update(Calendar exports): viewdata update 2025-02-05 11:03:19 +01:00
SimonGschnell 9ec57b6ce7 update(calendar exports): adds icons to the calendar exports buttons 2025-02-05 09:26:00 +01:00
Johann Hoffmann d70cd58698 past shadow on day page if it is today; current time line on day & week page; mobile checkup; close lvInfoModal on stundenplan unmount; 2025-02-04 18:04:41 +01:00
Andreas Österreicher a1841a0071 Merge branch 'Monika70-AnzahlStudenten' 2025-02-04 17:05:17 +01:00
Andreas Österreicher 1436d12a53 Added Default Config NICHT_ZUGELASSENE 2025-02-04 17:03:19 +01:00
Andreas Österreicher b177420cb1 Merge branch 'AnzahlStudenten' of https://github.com/Monika70/FHC-Core into Monika70-AnzahlStudenten 2025-02-04 16:56:44 +01:00
Andreas Österreicher faeb0fbf4b Merge branch 'master' of github.com:FH-Complete/FHC-Core 2025-02-04 16:48:27 +01:00
Andreas Österreicher 749c147f8e Phrase für Unruly angepasst 2025-02-04 16:48:01 +01:00
SimonGschnell 9082c3cb8c feature(Calendar Exports): uses the old enpoints to export excel,csv,ical1,ical2 documents 2025-02-04 14:37:34 +01:00
SimonGschnell cc5a14ea02 update(Sprachen.js): switches colors for the currently active sprache 2025-02-04 14:37:34 +01:00
ma0048 c56c71a508 - fixed bug 2025-02-04 12:05:15 +01:00
ma0048 50fa3d6f94 - faktor in eigener spalte 2025-02-04 10:42:59 +01:00
Harald Bamberger 03c192cbbf Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-03 16:58:45 +01:00
Harald Bamberger b10ee208ff pad only in y direction 2025-02-03 16:58:25 +01:00
Harald Bamberger 63239b3fb6 Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-02-03 16:14:23 +01:00
Harald Bamberger 1a0601ebc0 Merge branch 'feature-54856/FHC4_Studierendenverwaltung_In_Out' into merge_FHC4_C4 2025-02-03 16:06:06 +01:00
Harald Bamberger 5843d1d58e Merge branch 'master' into merge_FHC4_C4 2025-02-03 15:53:55 +01:00
kindlm 0059bc11f3 Merge remote-tracking branch 'origin/master' 2025-02-03 10:42:06 +01:00
kindlm fbd02e02f1 Rufzeichen bei Phrase entfernt 2025-02-03 10:41:41 +01:00
Cristina ac98420130 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-02-03 10:39:45 +01:00
Johann Hoffmann 11ad8ae1c8 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2025-01-31 14:10:26 +01:00
Johann Hoffmann c1918726df Stundenplan Week Page smaller breakpoints style handling; searchbar emit action finished on default link click; month stundenplan past days use opacity-50 class; Day page height fix of right col; 2025-01-31 14:09:05 +01:00
ma0068 dbd7adc96c adapt inline form validations, edit validation in final exam tab 2025-01-31 12:55:34 +01:00
SimonGschnell 0892b94c93 update(legacyLinkHelper): fixes little regex bugs 2025-01-31 12:08:40 +01:00
ma0068 ec46dbd10d Validation during delete for extension mobility, add field lehreinheit to dropdown and backend 2025-01-30 14:56:48 +01:00
Andreas Österreicher ecbc1c8d09 Merge branch 'sonstiges-55231/bfi-anrechnung-infobox-ausblenden' 2025-01-30 14:56:24 +01:00
Andreas Österreicher 07194cfaff - Index für lehre.tbl_anrechnungen hinzugefügt um Ladezeiten zu verbessern
- Bugfix fuer Detailseite der Lehrenden
2025-01-30 14:54:16 +01:00
Cristina 3eb1f7b06b Added array 'display_infobox' to config file anrechnung.php and adapted code to display only if set to true 2025-01-30 12:08:28 +01:00
ma0068 304433d76f Merge branch 'merge_FHC4_C4' of github.com:FH-Complete/FHC-Core into merge_FHC4_C4 2025-01-30 11:07:17 +01:00
ma0068 7cf0060e40 delete testoutputs 2025-01-30 11:07:03 +01:00
Cristina f2917b9ed7 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-01-30 10:23:56 +01:00
Szabo Mónika 51ba1d3fb9 Update lehrstunde.rdf.php
Studenten mit den in der vilesci.config.inc.php hinterlegten Noten sollten nicht zur AnzahlStudenten im Tempus gezählt werden.
Config Eintrag:
//Studierende mit diesen Noten werden von der AnzahlStudenten im Tempus abgezogen
define('NICHT_ZUGELASSENE',serialize(array(6, 20, NULL)));
2025-01-30 09:35:06 +01:00
ma0048 9cd7caa6ba added missing file 2025-01-30 09:08:53 +01:00
ma0048 42a09ffa9e - lehrform beim faktor hinzugefuegt
- indexes
- delete restrict -> delete cascade bei der faktor tabelle
- neues recht fuer reports -> direktzugriff
2025-01-29 15:21:01 +01:00
SimonGschnell b855c404e4 update(Cis Profil picture): instead of using cover, uses contain for the cis profile picture and adds a black border and background color 2025-01-29 14:33:42 +01:00
SimonGschnell 062e6e5f90 update(Sprachen.js): updates the usage of the classes fhc-entry in the Sprachen.js component 2025-01-29 14:04:36 +01:00
SimonGschnell 10c718b78c update(CalendarDate):changes the stop watcher function 2025-01-29 12:10:16 +01:00
ma0068 06dcad755b Backendvalidation insert and update, validation local tabulator array 2025-01-29 07:38:21 +01:00
Harald Bamberger 5b12e5eea7 Merge branch 'feature-5534/Gehaltsgraph_Valorisierung' 2025-01-28 18:37:18 +01:00
Harald Bamberger e068abd124 rename functions since they manipulate data for using it in a chart 2025-01-28 18:35:25 +01:00
Harald Bamberger d7cbe475bf Merge branch 'master' into feature-5534/Gehaltsgraph_Valorisierung 2025-01-28 17:39:19 +01:00
Harald Bamberger 7f645b363f Merge branch 'master' into merge_FHC4_C4 2025-01-28 16:54:08 +01:00
Harald Bamberger 402691b5cd Merge branch 'feature-53903/PV21_Valorisierungs_akutelle_Liste_ausgeben_ohne_Valorisierungskonfiguration' 2025-01-28 16:40:35 +01:00
Harald Bamberger 6a2a4c22b3 Merge branch 'master' into feature-53903/PV21_Valorisierungs_akutelle_Liste_ausgeben_ohne_Valorisierungskonfiguration 2025-01-28 16:14:39 +01:00
Paolo 0426e3498f Hotfix: replaced the dead github repository from https://github.com/tomazdragar/SimpleCropper.git to https://github.com/deveshsinghal22/SimpleCropper.git 2025-01-28 15:45:40 +01:00
Cristina 9a53880b9d Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2025-01-28 13:58:58 +01:00
Cristina 9a4211c980 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-01-28 13:58:14 +01:00
ma0068 dacde5f5fd Merge branch 'merge_FHC4_C4' of github.com:FH-Complete/FHC-Core into merge_FHC4_C4 2025-01-28 13:31:44 +01:00
ma0068 d906e9b4a3 edit missing fileextensions 2025-01-28 13:31:24 +01:00
SimonGschnell bd3eeff684 update(Stundenplan Style): changes the background/color styles for Calendar events in the different views 2025-01-28 13:22:57 +01:00
Harald Bamberger ad0fccab6a Merge branch 'master' into merge_FHC4_C4 2025-01-28 13:20:32 +01:00
SimonGschnell 9a3221e88e update(Fhc.js): installs font contrast directive in the global app 2025-01-28 13:13:02 +01:00
Harald Bamberger 4cd1bc3d63 Merge branch 'feature-18073/No-Reply-for-Sanchomails' 2025-01-28 13:05:53 +01:00
SimonGschnell 8991ab86a5 update(fhc-entry css class): instead of hard coding the color the css rules uses the filter:brightness function to highlight or darken elements 2025-01-28 13:04:43 +01:00
Harald Bamberger 4258e60b8b Merge branch 'master' into feature-18073/No-Reply-for-Sanchomails 2025-01-28 13:03:53 +01:00
SimonGschnell 9816521291 directive(text color contrast): adds a directive that determines a suitable font color based on the background color of the element through a directive 2025-01-28 13:01:24 +01:00
Harald Bamberger 7f6744047f check in ci mail config if constants in global config are defined 2025-01-28 11:26:01 +01:00
Harald Bamberger 39c2e44719 sancho default sender konfigurierbar machen 2025-01-28 10:22:30 +01:00
Harald Bamberger a89ca4e143 Merge branch 'feature-53938/StV_Tab_Noten_fertigstellen' into merge_FHC4_C4 2025-01-28 09:49:53 +01:00
ma0068 d96cc5672e child components Zweck/Purpose and Aufenthaltsfoerderung/Support 2025-01-28 09:39:24 +01:00
Harald Bamberger 519aa2f9b2 Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4 2025-01-27 18:34:42 +01:00
Harald Bamberger 872f883ce1 Merge branch 'bug-52531/Studierendenverwaltung/Adressenhandling' into merge_FHC4_C4 2025-01-27 18:29:48 +01:00
Harald Bamberger 637a7b1d17 Merge branch 'feature-53936/StudierendenVerwaltung_Studierendenliste_Anzahl_einblenden' into merge_FHC4_C4 2025-01-27 18:20:31 +01:00
Harald Bamberger db70a7869c Merge branch 'feature-54564/FHC-4_Studierendenverwaltung_Abschlusspruefung' into merge_FHC4_C4 2025-01-27 18:17:50 +01:00
Harald Bamberger a60ce78d18 Merge branch 'feature-40280/FHC4_Studierendenverwaltung_Pruefung' into merge_FHC4_C4 2025-01-27 17:39:47 +01:00
Harald Bamberger 2b5d23782b Merge branch 'feature-47784/FHC-4/CleanupTasks' into merge_FHC4_C4 2025-01-27 17:13:15 +01:00
SimonGschnell ec23974129 update(searchbar): makes the searchbar more visible by adding additional border and adding a search icon at the beginning of the searchbar 2025-01-27 15:13:27 +01:00
SimonGschnell e53dae24e6 update(Calendar Locale): updates the locale used by the english language to en-GB instead of en-US 2025-01-27 13:24:47 +01:00
SimonGschnell 8afc2ab433 addition(InfoTerminal): adds the Infoterminal page to the cis4 2025-01-27 11:50:51 +01:00
SimonGschnell 467072b94e update(Stundenplan.js): adds event beginn & ende time to the event display in Wochen/Tages Ansicht 2025-01-24 12:17:31 +01:00
SimonGschnell 38a083742d update(MyLv Noten farbe): uses db positiv column to determine the color of the grade in the MyLv component 2025-01-24 11:18:46 +01:00
ma0068 c69910a338 Child component Purpose.js for tableview 2025-01-24 11:00:50 +01:00
Harald Bamberger d6abfbbc23 fix typo 2025-01-23 16:33:03 +01:00
Harald Bamberger 87220e1789 move tbl_valorisierung_* to core since they are used in vertragsbestandteillib and gehaltsbestandteillib 2025-01-23 16:13:47 +01:00
Paolo d2cce86131 - controllers/api/frontend/v1/Filter->applyFilterFields validate filterFields as an array
- FilterCmptLib->applyFilterFields evaluate each elements of filterFields as an array
2025-01-23 15:40:56 +01:00
Harald Bamberger c5d79f750e add parameter withvalorisationhistory to use valorisation history or not 2025-01-23 15:31:17 +01:00
SimonGschnell 9b348aed11 fix(Dashboard News): fixes carousel animations when skipping news 2025-01-23 13:20:57 +01:00
SimonGschnell e7df262cc5 update(News Dashboard): next and previous icons don't stay active after clicking them 2025-01-23 10:41:55 +01:00
Harald Bamberger af79090de0 modify to consider valorisation history, TODO cleanup valorisation tables dependency on FHC-Core-Personalverwaltung Extension 2025-01-22 17:18:22 +01:00
Harald Bamberger 8ce4b452ec use encryption parameters in lamda function and return replacement string 2025-01-22 17:16:47 +01:00
Johann Hoffmann 8133d73cff remove route logging & catchAll fallback 2025-01-22 16:47:14 +01:00
Johann Hoffmann 9350838ebc set menu entry active when clicked 2025-01-22 16:43:37 +01:00
Johann Hoffmann 10e4032718 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2025-01-22 15:16:59 +01:00
Johann Hoffmann de8a206f27 delete cms app and move dom magic to respective components; profil vue router integration; profil component reloads with watcher on uid property; profiLUpdateRequest app->comp TODO; deleted profil app; 2025-01-22 15:16:15 +01:00
Harald Bamberger 4c46a5f5c7 modify regex to match optional table alias and ignore column alias equal to column name 2025-01-22 15:09:20 +01:00
SimonGschnell 065f6bdede update(News Dashboard): updates the stylesheet so that the layout of the news is responsive 2025-01-22 13:36:59 +01:00
Johann Hoffmann bb8ebdd465 initial route through router implicit; ci route tag only for debugging purposes. 2025-01-22 10:49:53 +01:00
Johann Hoffmann c7f3398b11 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2025-01-21 16:42:58 +01:00
Johann Hoffmann e9b01b7fa8 vue router merge cms & fhc app; viewData check and fetch in dashboard and widgets if not originating from that php controller; lvinfo app delete; code cleanup profil; WIP profil routing; 2025-01-21 16:42:23 +01:00
Harald Bamberger 781e2dbd15 Merge branch 'feature-54841/DVs_Abhaengigkeit_zu_SAP_Extension_beseitigen' 2025-01-21 14:29:05 +01:00
SimonGschnell d72bc4fa44 update(News DashboardWidget): updates how to betreff is queried from the XML 2025-01-21 14:20:40 +01:00
Harald Bamberger d9532d7607 Merge branch 'master' into feature-54841/DVs_Abhaengigkeit_zu_SAP_Extension_beseitigen 2025-01-21 13:40:26 +01:00
Werner Masik 1853e44cf3 add valorized data for chart display 2025-01-21 12:58:09 +01:00
SimonGschnell 381b6a75db update(News DashboardWidget): doesn't render news which don't have a topic 2025-01-21 09:40:22 +01:00
Alexei Karpenko e65322965f sancho mail: added config for haeder/footer image path, renamed custom mail config entries to sancho mail config entries, images are always attached inline (when using Code Igniter) 2025-01-20 16:24:56 +01:00
Harald Bamberger 899c36c52c default sancho image comes from global config now 2025-01-20 15:10:52 +01:00
Harald Bamberger 71d1a808f8 Merge branch 'master' into feature-18073/No-Reply-for-Sanchomails 2025-01-20 13:36:17 +01:00
SimonGschnell ff0ee68229 refactor(BookmarkWidget) 2025-01-17 12:47:04 +01:00
ma0048 0d99cc35d4 - phrasen angepasst 2025-01-16 15:59:36 +01:00
Johann Hoffmann 0ec3ba8e69 intercept a tag clicks and attempt vue routing to avoid having to know about vue router configuration; routes include Stundenplan, MyLv; 2025-01-16 15:16:33 +01:00
Andreas Österreicher 1489706027 Merge branch 'Monika70-Export' 2025-01-16 13:22:51 +01:00
Andreas Österreicher 103df5afe5 Merge branch 'Export' of https://github.com/Monika70/FHC-Core into Monika70-Export 2025-01-16 13:21:14 +01:00
Andreas Österreicher ba2b41f63a Merge branch 'feature-55289/pep_fine_tuning' 2025-01-16 13:12:26 +01:00
SimonGschnell 4b2a1cd7f6 update(Url.js): adds scrolling behavior to the Bookmark widget 2025-01-16 11:32:19 +01:00
SimonGschnell 46c033ad77 update(NewsWidget):reduces z-index so that it does not overlap modals, add light background to the next/prev buttons for visibility 2025-01-16 11:10:03 +01:00
SimonGschnell aef0e34b93 update(Calendar/Header.js):icon reihenfolge sowie icon fuer Tagesansicht wurden angepasst 2025-01-16 10:41:21 +01:00
ma0048 f381ef229e - index tbl_lehrveranstaltung_faktor_lvid hinzugefuegt
- sortierung gleichgezogen
2025-01-16 10:38:01 +01:00
Alexei Karpenko ece4f4a8b5 sancho mails: enabled removing of header/footer and custom header/footer images in code igniter code, legacy code: global ids for images are created only if config is set 2025-01-15 16:52:11 +01:00
SimonGschnell 09b2615d82 update(FhcAlert.js): if the request was aborted, no error message is shown to the user 2025-01-15 14:42:13 +01:00
Szabo Mónika f1234c0b99 Update studentenexportextended.xls.php
Zusätzliche Spalte Person_id hinzufügen
2025-01-15 14:37:06 +01:00
SimonGschnell 7b46db7100 update(LegacyLinkReplaceHelper.js):adds constants for the replacement strategies when the pattern has groups that should be added as path_segements or query_parameters 2025-01-15 14:15:03 +01:00
Johann Hoffmann f60f735fa8 FhcApp uses vueRouter4; CisApp checks for global router instance and routes internally as long as a path/routename/component setup is defined, if that is not the case use the provided href link; WIP moving apps like Profil, MyLv etc into components to be navigated by FhcApp; 2025-01-15 14:10:08 +01:00
Harald Bamberger fd67974d55 fix typo 2025-01-15 13:35:58 +01:00
SimonGschnell bae7b330f8 feature(LegacyLinkReplacementHelper.js): adds a helper file with multiple functions that replace relative or absolute legacy links with new links that use the new app_root and ci_router 2025-01-15 13:34:54 +01:00
Harald Bamberger a1a9e96bc0 permission basis/gehaelter 2025-01-15 13:34:16 +01:00
Andreas Österreicher aab0f339ab Merge branch 'feature-55316/international_skills_credits_entfernen_neue_massnahmen' 2025-01-15 13:06:04 +01:00
SimonGschnell cf57fe5086 replaces the old relative paths inside the content html with absolute paths that use the new app_root path 2025-01-15 09:45:03 +01:00
Harald Bamberger d4bb06c4f6 Merge branch 'feature-54920/DB_Model_encrypted_columns_spaltenname_enthaelt_anderen_spaltennamen' 2025-01-15 09:20:54 +01:00
Harald Bamberger 0770ec2bd8 Merge branch 'master' into feature-54920/DB_Model_encrypted_columns_spaltenname_enthaelt_anderen_spaltennamen 2025-01-15 09:03:41 +01:00
Alexei Karpenko 13d86edcfc sancho mails: added CUSTOM_MAIL_USE_IMAGES config for sending mails without header/footer, removed option to hide mail html 2025-01-14 17:24:40 +01:00
SimonGschnell 516554c1e3 update(CalendarDate.js): uses phrasen.user_locale for calculations and watches for changes on the user_locale 2025-01-14 11:43:50 +01:00
ma0048 50aca4a545 - umbenennung auf internatinal credits 2025-01-14 11:00:26 +01:00
Johann Hoffmann cf32974652 fhc chart just accepts chartOptions to maximize highcharts usability; statsComponent multiselect ux improvement; 2025-01-13 17:36:09 +01:00
Alexei Karpenko 6c858141fd deleted mailtest file 2025-01-13 16:22:45 +01:00
SimonGschnell 907107d78d update(searchbar.js): adds the search text to the sessionStorage and the searchOption to the localStorage 2025-01-13 14:45:41 +01:00
SimonGschnell 16097edfca refactor(CalendarDate.js): sets the locale for every new instance of CalendarDate that gets created in the CalendarDate.js class 2025-01-13 09:41:58 +01:00
SimonGschnell 05cbe495fe fix(Calendar Weeks View): updates the number of weeks in the weeks View when going to the next or previous year 2025-01-13 09:29:54 +01:00
Alexei Karpenko 6b169d4183 sancho mail: configuration of header/footer and sender is possible 2025-01-11 15:43:30 +01:00
SimonGschnell 14d4e103a3 update(Calendar Tages Ansicht): doesn't how the hour indicator if there are no events that day 2025-01-10 13:50:47 +01:00
SimonGschnell 478588aef0 fix(Calendar Date Issues):fixes a variety of user_locale calendar bugs 2025-01-10 13:46:24 +01:00
ma0068 03ad3116f7 temp formular 2025-01-10 07:16:56 +01:00
SimonGschnell d9375e2c8b comment(CalendarDate.js): adds comments to the functions: firstDayOfCalendarMonth, lastDayOfCalendarMonth, firstDayOfWeek, lastDayOfWeek 2025-01-09 15:04:56 +01:00
Johann Hoffmann 848d50ec93 Graph has reactive state over several types; WIP seperating data UI from graph component 2025-01-09 14:35:17 +01:00
Johann Hoffmann 036aeb5215 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2025-01-08 16:13:50 +01:00
Johann Hoffmann 2fdca1f09f WIP stats Tab in anw extension & FhcChart component in fhcore; 2025-01-08 16:12:30 +01:00
SimonGschnell b20965fcff refactor(CalendarDate.js): adds comments and restructures some conditionals 2025-01-08 13:31:38 +01:00
SimonGschnell 50f55eed1a Merge remote-tracking branch 'origin/bhdev' into feature-25999/C4_cleanup 2025-01-08 11:20:33 +01:00
SimonGschnell a67cc8cc4e Merge branch 'master' into feature-25999/C4_cleanup 2025-01-08 11:17:29 +01:00
SimonGschnell 26348bed80 update(FHC_JS_DATA_STORAGE_OBJECT/Sprachen.js): adds server_languages and their locale to FHC_JS_DATA_STORAGE_OBJECT and updates Sprachen.js accordingly 2025-01-08 11:15:55 +01:00
Harald Bamberger e432501a1f possible fix for kw 1 issue 2025-01-07 17:09:07 +01:00
SimonGschnell 6361d40356 update(WeekCalendarHeader):uses the last day of the week instead of the first day of the week for the calendar title 2025-01-07 15:26:08 +01:00
Harald Bamberger 46914e8a65 bugfix wenn mehrere karenzen im abgefragten zeitraum vorhanden sind 2025-01-07 14:38:08 +01:00
SimonGschnell c7ee2934a7 fix(Stg 0 not found bug): displays the LV in the lvMenu differently if the stg_kurzbz is 0, which is the case for lv's that are organisational 2025-01-07 11:17:29 +01:00
SimonGschnell 5a45b29bcd comment(Profil Quick links): comments the quick links of the profil views away because there is no idea of implementation yet 2025-01-07 09:10:41 +01:00
cgfhtw b43df5aea0 NotenTab: Phrases 2024-12-27 14:44:53 +01:00
SimonGschnell 574301d9e2 fix(Calendar Language): also update the tooltips of the calendar by using the client lannguage 2024-12-20 15:03:05 +01:00
cgfhtw 469c01c9e6 Comments 2024-12-20 14:15:28 +01:00
cgfhtw e13e612ad9 Merge branch 'master' into feature-53938/StV_Tab_Noten_fertigstellen 2024-12-19 16:48:15 +01:00
cgfhtw 174816e652 Cleanup & existing phrases 2024-12-19 16:42:02 +01:00
cgfhtw d899bf3393 NotenTab: Document download/archive 2024-12-19 16:20:14 +01:00
cgfhtw 14eb27ae24 add PrimeVue TieredMenu 2024-12-19 16:19:46 +01:00
cgfhtw de9e3d079c Endpoints for document download/archive (content/pdfExport.php with "archivdokument" not set) 2024-12-19 16:18:51 +01:00
Johann Hoffmann 551fd3a860 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-12-19 16:08:25 +01:00
Johann Hoffmann 64ff94882b stats enabled config flag; using highcharts plugin in new Tab & Component for (anw)Statistics; currently able to show old pie charts from old landing page; wip building setup UI for configurable graphs depending datasets and chart types; 2024-12-19 16:07:56 +01:00
ma0068 c980dee96b edit select 2024-12-19 15:25:21 +01:00
SimonGschnell 114562909f update(Calendar.js): uses the user_language for the different day formattings in the calendar views 2024-12-19 12:12:13 +01:00
Johann Hoffmann e2af00e41d highcharts consolidation -> add plugin, import switch to footer and repository requirement in composer.json 2024-12-19 11:24:31 +01:00
ma0068 39a23693ba start Table Mobility 2024-12-18 16:31:39 +01:00
ma0068 ba62abc19b bug stv 2024-12-18 14:57:18 +01:00
ma0048 8bc1aec764 - info mail auch senden, wenn in niedriger Prio bereits student ist 2024-12-18 14:46:26 +01:00
SimonGschnell 1094219a58 helper(Json.js):adds new helper component to display JSON data in the template, that can be used globally inside a vuejs app 2024-12-18 14:26:45 +01:00
SimonGschnell 313a6a6030 fix(Profil Views): corrects the title of the web tab from Stundenplan to Profil 2024-12-18 13:47:52 +01:00
ma0068 faa705408d Merge master into feature-54564/FHC-4_Studierendenverwaltung_Abschlusspruefung 2024-12-18 13:12:57 +01:00
ma0068 9f5b3b6f32 Print Functionality and Phrases 2024-12-18 12:56:51 +01:00
cgfhtw e1327453f7 DocumentExportLib: CI version of dokument_export.class 2024-12-18 09:43:16 +01:00
cgfhtw 636a331ca6 add Vorlagestudiengang_model->getCurrent similar to vorlage.class->getAktuelleVorlage 2024-12-17 14:29:37 +01:00
SimonGschnell e3f91003b3 phrasen(Profil.js): adds dynamic phrasen for the various Profil Views 2024-12-17 11:29:05 +01:00
SimonGschnell d247150fd6 phrasen(StudiengangInformationen.js): adds Phrasen to the StudiengangInformationen Component and all its subcomponents 2024-12-17 10:55:13 +01:00
cgfhtw b78382f1ba Add extra fields/joins to getZeugnisnoten 2024-12-17 09:27:18 +01:00
Andreas Österreicher a802e67faf Merge branch 'pep_deploy' 2024-12-16 13:57:15 +01:00
Andreas Österreicher 2c91756a36 Added missing APP PEP to checksystem 2024-12-16 13:29:55 +01:00
Johann Hoffmann 25dbee7266 removed app instance hacks, content component watches route.param.content_id and reloads accordingly; changed template to <router-view/> for cms pages; 2024-12-16 11:46:38 +01:00
Johann Hoffmann 0509137ad8 Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_CMS_content_router
# Conflicts:
#	public/js/apps/Cis/Cms.js
#	public/js/components/Cis/Cms/Content.js
2024-12-16 10:38:22 +01:00
SimonGschnell b4cd5055d2 delete(Contentl.js/Debugging prints) 2024-12-13 14:48:48 +01:00
SimonGschnell cb6fca9a2e update(Cms.js/News.js/PhrasenPlugin): removes the reload option, because the content can be newly fetched based on the currently active language 2024-12-13 14:41:07 +01:00
SimonGschnell 701f44c767 update(Cis4-Menu/Sprache): changes language of the Menu when switching language of the application 2024-12-13 14:40:01 +01:00
Harald Bamberger 0d2882d8aa Merge branch 'feature-25999/SearchbarStudent' 2024-12-13 12:11:12 +01:00
Harald Bamberger f62108f1d4 change concatenation of verband, use contact email in Stv search result, use dummy image when viewing anothers profile and foto is null or foto_sperre is not false 2024-12-13 12:09:16 +01:00
Johann Hoffmann 986b6934d6 Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_CMS_content_router
# Conflicts:
#	public/js/components/Cis/Cms/News.js
2024-12-13 12:04:38 +01:00
Johann Hoffmann 499e3077e2 Merge branch 'master' into feature-25999/C4_CMS_content_router 2024-12-13 12:00:50 +01:00
Johann Hoffmann 98d4a08836 navigating to another content_id link from cms app reloads the content instead of entire page; WIP implementing abstract reload functionality for all content types; 2024-12-13 11:52:34 +01:00
ma0048 746f8ab35a Merge branch 'feature-54822/filtercomponent_custom_headerfilter' into pep_deploy 2024-12-13 11:51:11 +01:00
ma0048 70b44c2202 Merge branch 'feature-40717/pep_faktor' into pep_deploy
# Conflicts:
#	public/js/components/filter/Filter.js
#	system/dbupdate_3.4.php
#	system/phrasesupdate.php
2024-12-13 11:50:53 +01:00
ma0048 c0d2474ad2 -dbupdate gegencheck eingebaut
- delete restrict auf cascade geändert
2024-12-13 11:42:00 +01:00
Harald Bamberger 5a174e554a use studentStv in Studentenverwaltung config, add aktiv to student and studentStv result, use studentStv in searchbar component, add searchbar_inaktiv css class, use aktiv to render inactive studentStv results with css class searchbar_inaktiv 2024-12-13 11:25:02 +01:00
ma0048 3451741327 - ON DELETE RESTRICT auf ON DELETE CASCADE bei bei den notizen
- sql angepast
2024-12-13 11:03:46 +01:00
SimonGschnell a3840d4c77 update(Searchbar/Student):shows dummy image if the student has foto_spere true 2024-12-13 10:47:34 +01:00
SimonGschnell 9a1777d1aa fix(_student searchfunction):fixes the sql logic for non active students 2024-12-12 15:35:56 +01:00
Harald Bamberger 4a86a48969 Merge branch 'master' into feature-25999/SearchbarStudent 2024-12-12 15:27:08 +01:00
Andreas Österreicher 1f01c55d71 LVPlan Feedback Link auf Startseite entfernt 2024-12-12 15:06:02 +01:00
Harald Bamberger 80222b7186 Merge branch 'master' into feature-25999/SearchbarStudent 2024-12-12 14:55:41 +01:00
Harald Bamberger d0266e7ef0 add vuejs3_dev to composer.json and ci javascript config file to switch between vuejs dev and prod version, alter FHC-Footer to use new config 2024-12-12 14:49:15 +01:00
SimonGschnell 8f07bd6b4d update(Sprachen.js): shows the sprachen in the component always using their bezeichnung 2024-12-12 14:46:32 +01:00
Harald Bamberger 3039fd2a1e Merge branch 'master' into feature-25999/SearchbarStudent 2024-12-12 13:57:03 +01:00
SimonGschnell 7bd9129056 fix(LvMenu/Lv.js): removes the list-item styling from the spinner when the data for the lvMenu is not yet ready and aligns the spinner in the center of the card 2024-12-12 13:47:15 +01:00
SimonGschnell 24ff474cad update(MyLv/Lv.js):the user can only click on the grade of an lv if the lv had multiple pruefungen otherwise the grade is not clickable 2024-12-12 13:31:06 +01:00
ma0048 5b3ffcfc9a - faktor berechtigung angepasst 2024-12-12 12:37:24 +01:00
SimonGschnell 4321a2325b update(StudiengangInformation.js): adds the general moodle link for the Studiengang informations to the component using a static link 2024-12-12 11:35:16 +01:00
Andreas Österreicher 03d8205722 Merge branch 'feature-46905/LV_plan_feedback_Link_aendern' 2024-12-12 11:30:00 +01:00
SimonGschnell 1d5f13c5ce Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-12-12 09:52:27 +01:00
SimonGschnell df8d4de50b fix(SearchbarLib/_student): the cis search does not include students that are not aktiv and has a seperate search function for the student search for the Cis and the studentverwaltung 2024-12-12 09:42:38 +01:00
Harald Bamberger 9af3f1ec0f Merge branch 'feature-25999/LvMenuFix' 2024-12-11 17:50:03 +01:00
Johann Hoffmann 82e7783259 stundenplan day layout fixed for scroll behaviour; max-height for stundenplan events to avoid escalating the grid width; 2024-12-11 16:59:35 +01:00
SimonGschnell 85d59f18be refactor(searchbar/Student): studiengang/verband/email are queried for the display in the searchbar component 2024-12-11 15:30:41 +01:00
ma0048 6a1e518da1 - defaultheaderfilter function in eigenes file verschoben 2024-12-11 13:44:19 +01:00
ma0048 8127091e2e - tags werden im fas nicht angezeigt
- class für tags hinzugefuegt
- prop confirmLimit hinzugefuegt
2024-12-11 13:25:38 +01:00
SimonGschnell e215e9e948 refactor(News-Paginator@Bottom):also adds the pagination at the bottom of the news, so that the user doesn't have to scroll up if he reaches the end 2024-12-11 12:44:06 +01:00
SimonGschnell a357001648 feature(Searchbar/StudentenSuche): adds student to the searchbar options and adds shadow to the searchbar 2024-12-11 12:34:58 +01:00
Harald Bamberger bfc6e86f05 Merge branch 'master' into feature-54920/DB_Model_encrypted_columns_spaltenname_enthaelt_anderen_spaltennamen 2024-12-11 11:54:23 +01:00
Harald Bamberger 3c8bb37a36 Merge branch 'master' into feature-54920/DB_Model_encrypted_columns_spaltenname_enthaelt_anderen_spaltennamen 2024-12-11 11:52:50 +01:00
SimonGschnell 2567db7725 fix(LvMenu.js): fixes layout of MenuPunkt if multiple moodle links are available 2024-12-11 11:28:40 +01:00
Johann Hoffmann fcbb9e43a4 Merge branch 'master' into feature-25999/C4_cleanup 2024-12-11 11:08:49 +01:00
Andreas Österreicher 034e1397e8 Merge branch 'feature-52814/infocenter_infocentermitarbeiter_spalte_beim_loeschen_des_dokuments' 2024-12-11 08:36:27 +01:00
Andreas Österreicher 35ded7950f Merge branch 'feature-46974/neuer_filter_ueber_ueberfaellige_buchungen' 2024-12-11 08:00:54 +01:00
Andreas Österreicher a6a74cd1e0 Merge branch 'feature-40413/testtool_sperren_bei_namen_mit_hochkomma' 2024-12-11 07:52:27 +01:00
Andreas Österreicher bae48fa175 Merge branch 'master' into feature-40413/testtool_sperren_bei_namen_mit_hochkomma 2024-12-11 07:13:20 +01:00
Andreas Österreicher 94f4761163 Merge branch 'bug-54917/Gruppenmanagement_Berechtigung' 2024-12-11 07:07:44 +01:00
Alexei Karpenko cc99d2b378 Gruppenmanagement: added checks so only Gruppenmanager can edit groups 2024-12-10 12:03:58 +01:00
Johann Hoffmann 53de29f3d2 stundeplan_model byLva() query when providing lv_id irrespective of student, group, lector etc just fetch all & show them 2024-12-09 17:13:23 +01:00
Johann Hoffmann e9d02c41ff merge fix; 2024-12-09 15:42:08 +01:00
Johann Hoffmann 04583d0cf2 Merge branch 'feature-25999/C4_anwesenheiten_widget' into feature-25999/C4_cleanup
# Conflicts:
#	public/js/components/Cis/Cms/News.js
#	public/js/components/DashboardWidget/News.js
#	public/js/plugin/FhcApi.js
2024-12-09 15:37:20 +01:00
Johann Hoffmann cbdd6bc954 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-12-09 14:32:35 +01:00
Johann Hoffmann a1045586fe use carousel instance .to(index) & computed classes to retrieve order; 2024-12-09 14:30:33 +01:00
SimonGschnell e9d2234353 feature(Studiengang Widget):creates a component for the Studiengang Widget that reuses the StudiengangInformation component 2024-12-09 13:36:18 +01:00
Alexei Karpenko ce2d69fc82 Vertragsbestandteil Model: check if sap sync table present before executing select for sap organisationseinheit 2024-12-06 13:05:35 +01:00
Johann Hoffmann 9fd0f43d3b news widget prev/next button hover styles; mobile responsive menu & gutter layout fix; 2024-12-06 13:04:28 +01:00
Andreas Österreicher 07ee3e1f4e Import der Leistungsstipendien angepasst. Neue Spaltenreihenfolge, Keine
automatische Gegenbuchung, Import der Bankdaten
2024-12-06 12:50:58 +01:00
SimonGschnell 39ffd6bdb9 fix(news Widget api): readds the removed api call from the news widget because it differs from the getNews api call that is used in the News View 2024-12-06 09:59:58 +01:00
SimonGschnell 0a5c335602 refactor(News-StudiengangInformationen): component clean up and refactors vertretungen into own component 2024-12-05 16:22:21 +01:00
cgfhtw 6fdad1b664 Noten Tab: delete 2024-12-05 16:19:51 +01:00
cgfhtw 3969ebfa01 Filter Component: better btn width/height css 2024-12-05 15:26:38 +01:00
SimonGschnell 797e52aad7 refactor(News-StudiengangInformationen): adds the Studiengangs informationen next to the news View 2024-12-05 15:22:53 +01:00
cgfhtw 5fd14949fa Tabulator Default Layout: fitDataStretchFrozen 2024-12-05 15:13:58 +01:00
cgfhtw 482f6b9a19 FhcAlert Color Bugfix 2024-12-05 15:08:31 +01:00
Johann Hoffmann 7f6884b67d primevue imports cis/dashboard; Anw widget implementation; WIP showing single anw entries on click on a quota progress bar in widget; 2024-12-05 15:03:46 +01:00
Johann Hoffmann f0e97c915b rename bindKeys() to addEndpoints(); removed Vue.reactive on $fhcApi; check if Api has been instantiated in install, only addEndpoints if that is the case; 2024-12-05 13:53:08 +01:00
SimonGschnell ecbb65c2a4 feature(News-StudiengangsInformationen): adds the Studiengangsinformationen next to the news view 2024-12-04 15:04:05 +01:00
Johann Hoffmann f7bc01e63f actually provide root to bindKeys() in FhcApiFactoryWrapper constructor 2024-12-04 13:53:59 +01:00
Johann Hoffmann 65c154054d actually provide root to bindKeys() in FhcApiFactoryWrapper constructor 2024-12-04 13:52:17 +01:00
Johann Hoffmann 27cd9dca6b Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_anwesenheiten_widget 2024-12-04 13:49:32 +01:00
Johann Hoffmann 00fba24936 fhcApi.factory.bindKeys to extend api later on from extensions 2024-12-04 13:48:28 +01:00
Harald Bamberger 57cba02559 Merge branch 'master' into feature-25999/C4_cleanup 2024-12-04 13:35:59 +01:00
Harald Bamberger 3cea79cb28 Merge branch 'feature-25999/C4_cleanup_rc' 2024-12-04 12:44:08 +01:00
Harald Bamberger e159dc44dc Merge branch 'master' into feature-25999/C4_cleanup_rc 2024-12-04 12:43:06 +01:00
Andreas Österreicher 055cea2002 Termin3 entfernt aus Default Checksystem 2024-12-04 11:25:49 +01:00
SimonGschnell a3dc5aec93 feature(StudiengangInformations componente): creates a Vue component for the StudiengangsInformationen that were displayed next to the news 2024-12-04 11:20:52 +01:00
Harald Bamberger f105bdb36a revert FhcApi.js to current master 2024-12-04 11:09:37 +01:00
Harald Bamberger af3334f227 Merge branch 'feature-25999/C4_cleanup_rc' into feature-25999/C4_cleanup 2024-12-04 09:29:29 +01:00
Harald Bamberger 1b445005af remove addMeta debug info 2024-12-04 09:28:59 +01:00
Harald Bamberger 16e7ee8aba Merge branch 'feature-25999/C4_cleanup_rc' into feature-25999/C4_cleanup 2024-12-04 09:17:57 +01:00
Harald Bamberger 2fee03ebcc remove sprachen menu from main nav 2024-12-04 09:17:15 +01:00
Harald Bamberger d30ba24d2f add config cis_send_profil_update_mails, use it in profil update controllers 2024-12-04 09:15:44 +01:00
ma0068 7cff70e88d update search Mitarbeiter, form 2024-12-04 08:34:36 +01:00
ma0048 631010821b - check bei projectstunden ob stunden eingetragen sind 2024-12-03 17:08:03 +01:00
ma0048 b34a7bfabc - custom filter tabulator 2024-12-03 16:13:48 +01:00
ma0048 6a1af1b2dd - fuer lehre tab planungsstatus hinzugefuegt
- config fuer planungsstatus
- tags ohne notiz setzen
2024-12-03 15:31:32 +01:00
Johann Hoffmann fe6f229d9f template fix; remove unused menu function; 2024-12-03 14:44:18 +01:00
Harald Bamberger 6f69046b71 use regex with word boundaries to be more specific when replacing 2024-12-03 13:44:24 +01:00
ma0048 19b56ff252 - tags
- phrases
- stundensatzbydatum
- filter nur count
2024-12-03 12:36:54 +01:00
cgfhtw 446a5732d2 NotenTab: Use Points 2024-12-03 09:27:38 +01:00
Harald Bamberger af2f3348b4 Merge branch 'master' into feature-25999/C4_cleanup 2024-12-03 07:37:22 +01:00
Johann Hoffmann 41ad440cd4 update newsWidget template & css, fixed carousel css transition; 2024-12-02 16:41:42 +01:00
ma0048 1a1ed49f8b - styling für neuen tag
- hover effekt
- tagicon statt plus
2024-12-02 13:09:38 +01:00
Cris 2ae9e4fffa Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2024-12-02 11:02:43 +01:00
Cris d67e240b06 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-12-02 11:01:45 +01:00
Johann Hoffmann bf5e8e9c0e Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_anwesenheiten_widget 2024-12-02 10:57:40 +01:00
Andreas Österreicher e63234e7bc Gegencheck und Anwesenheit App eingefügt 2024-12-02 10:09:09 +01:00
ma0068 00d64f2c97 bugfix index Favorites 2024-12-02 08:54:35 +01:00
ma0068 ae58cef816 Merge master 2024-12-02 08:43:13 +01:00
Johann Hoffmann 1ca0f35d29 news widget template carousel with menu update; 2024-11-29 15:24:33 +01:00
SimonGschnell 1336860ecd feature(Dashboard Transitions): uses Vue's built-in Transition component to add transitions to the widget config elements 2024-11-29 13:23:51 +01:00
Harald Bamberger 278e5d8abd Merge branch 'master' into feature-25999/C4_cleanup 2024-11-29 13:04:08 +01:00
Harald Bamberger 90ae50ac59 Merge branch 'master' into feature-47784/FHC-4/CleanupTasks 2024-11-29 12:48:38 +01:00
SimonGschnell 95e59007cc refactor(Settings/NavUser Collapsibles): closes the collapsibles if the user clicks outside of the elements 2024-11-29 12:29:59 +01:00
SimonGschnell 857d4d7282 refactor(Calendar indicator):adds Vue transition to the Calendar indicator through Vue's built-in component 2024-11-29 11:50:27 +01:00
Harald Bamberger 7a7c91b67b readd lines of code that were lost during merging 2024-11-29 11:19:57 +01:00
SimonGschnell 9cf6036926 refactor(Paginatino.js): makes the pagionation component responsive on mobile displays 2024-11-29 10:57:14 +01:00
cgfhtw cf6cc97475 Noten Tab: header/inline edit 2024-11-29 08:42:36 +01:00
ma0068 bf6b6e4563 actions insert, update, delete, link Pruefungsprotokoll 2024-11-28 16:29:13 +01:00
Andreas Österreicher 11eae29dab Merge branch 'feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp' 2024-11-28 14:04:50 +01:00
Andreas Österreicher 0f476b4e46 Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp 2024-11-28 14:02:41 +01:00
Andreas Österreicher 677d6e97d6 Config zur Steuerung für welche Studiengaenge die Digit. Anwesenheiten
sichtbar sein sollen (Testbetrieb)
2024-11-28 13:38:25 +01:00
SimonGschnell 021a140dd3 refactor(LvInfo.js): also adds a Profil View link to the lektor name 2024-11-28 13:09:41 +01:00
SimonGschnell 4f8ca679fb fix(Calendar/Week/Day/Page.js): removes the calendar indicator when moving the mouse outside of the calendar 2024-11-28 12:52:24 +01:00
SimonGschnell 9dfa8d13a6 feature(Mylv/Info.js): adds Profil view links to the Lektoren in MyLv Info and fixes the dupplicate lektoren names 2024-11-28 12:46:23 +01:00
SimonGschnell 71c39edd66 fix(Cis/Sprachen.js): fixes classes of the Sprachen component inside of the Nav Menu when toggled 2024-11-28 10:53:00 +01:00
Johann Hoffmann 1346466f79 Merge branch 'master' into feature-25999/C4_anwesenheiten_widget 2024-11-28 10:43:57 +01:00
Johann Hoffmann beb40cfcc9 Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_anwesenheiten_widget 2024-11-28 10:22:57 +01:00
Andreas Österreicher 0a4d8bb1f6 Falsch verschachtelte Phrase korrigiert 2024-11-28 08:43:25 +01:00
ma0068 9024b43f62 Merge master into feature-47784/Cleanup Tasks FHC4 2024-11-28 07:26:59 +01:00
ma0068 e8ded1f59f prepare branch before merge phrases 2024-11-28 07:14:15 +01:00
Cris b549622f50 Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite
# Conflicts:
#	application/models/organisation/Studiensemester_model.php
#	system/phrasesupdate.php
2024-11-27 17:44:45 +01:00
Cris b2477bb603 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-11-27 17:32:27 +01:00
Cris 3ec748e6fb Added new phrases for Softwarebereitstellung 2024-11-27 17:31:48 +01:00
Cris c94a2d2d0c Added param lehrveranstaltung_id to getTemplateLvTree method in Lehrveranstaltung_model.php and enhanced order
Now ordering extra templates to appear first and directly after the assigned lvs
2024-11-27 17:31:02 +01:00
Cris 1159b0dad5 Refactored getLvs method in Lehrveranstaltung_model.php 2024-11-27 17:28:54 +01:00
Johann Hoffmann 39f1f825a5 fhcApi extendable & reactive; provide reactive viewdata from dashboard to widgets by inject/provide reworked news xslt in db; css change since overflow-auto is in xslt now; WIP anw widget; 2024-11-27 16:30:54 +01:00
ma0068 f398a5699f merge into feature-54564 2024-11-27 15:14:48 +01:00
SimonGschnell 6e1943928a feature(Cms/Content_types/Raum_contentmittitel.js): wraps the h1 title of the content with a link to the Reservierungen of that room 2024-11-27 15:04:56 +01:00
ma0068 ffe28ea8fb undo phrases changes to avoid merging conflict 2024-11-27 14:58:00 +01:00
Andreas Österreicher 490a658e6d Merge branch 'feature-8482/Pruefungsprotokoll_zur_Einsicht_exportieren' 2024-11-27 13:45:30 +01:00
Andreas Österreicher fd91a4cb85 Merge branch 'master' into feature-8482/Pruefungsprotokoll_zur_Einsicht_exportieren 2024-11-27 13:44:24 +01:00
SimonGschnell 800d7ba005 refactor(Cis.css fhc-entry styles): switches the background-colors of the fhc-entry class between selected and not selected 2024-11-27 13:04:52 +01:00
ma0068 3318147ba0 Start tab Abschlusspruefung, Table and Form with Dropdowns and default data 2024-11-27 12:52:03 +01:00
SimonGschnell 89539d59fd refactor(components/Cis/Sprachen.js): refactors the Sprachen component with different styles and stores the user_langauge in the global properties of the Vue application by managing a reactive state in the phrasen plugin 2024-11-27 11:50:19 +01:00
Johann Hoffmann 1ba857b524 only show digi anw in cis_menu_lv when corresponding lva is from BIF/257 for testphase 2024-11-26 17:12:11 +01:00
SimonGschnell 0ebc6e820c refactor(Calendar/Page/Event style): change the margins of an event, so that the border of the event is visible 2024-11-26 16:27:48 +01:00
SimonGschnell 24740d055e feature(Sprache/Phrasen aendern): creates a Cis Sprachen component that lists all available Sprachen from the database and lets the user change the currently active language and persist it in the database 2024-11-26 16:26:29 +01:00
Johann Hoffmann c02c1e9955 hinweis "testphase -> keine benotung" phrase 2024-11-26 15:59:42 +01:00
cgfhtw 3457309d63 Switching grades to single edit 2024-11-26 15:06:13 +01:00
Andreas Österreicher c32f65bc1e Reihungstestangetreten Check aus BIS-Bewerbermeldung entfernt 2024-11-26 12:49:21 +01:00
SimonGschnell 82f1a70de5 fix(Calender/Day/Page.js): ausgewaehlte Event wird resetet wenn man den darauffolgenden oder vorherigen Tag auswaehlt 2024-11-26 09:25:24 +01:00
SimonGschnell 8983af4aef refactor(Stundenplan_model/getStundenplanQuery):removes wrong comments 2024-11-25 19:59:39 +01:00
Harald Bamberger 290da9f2c0 Merge branch 'master' into feature-25999/C4_cleanup 2024-11-25 17:09:53 +01:00
Harald Bamberger 7fe3a7c8f5 Merge branch 'feature-25999/C4_cleanup_rc' 2024-11-25 16:33:27 +01:00
Harald Bamberger 766bec887a check if constant CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN is defined 2024-11-25 16:29:41 +01:00
cgfhtw 5f61ae43f9 Hide Noten Tab from non-Students 2024-11-25 16:23:43 +01:00
SimonGschnell 90bdb68175 fix(Stundenplan_model/getStundenplanQuery):changes how the OR sql statments are added to the query 2024-11-25 15:24:36 +01:00
Harald Bamberger 0bec551174 lowercase search in searchfunction fhcapifactory path 2024-11-25 14:24:04 +01:00
Harald Bamberger f90f5154a0 remove searchdummy function and dummyapi 2024-11-25 13:57:25 +01:00
Harald Bamberger 2ed24ca60f remove unneeded controllers, views and vuejs apps 2024-11-25 13:48:33 +01:00
SimonGschnell 699595e891 refactor(DashboardWidget/Stundenplan.js):adds the template for the MonthPage when the Month of the calendar is visible 2024-11-25 13:34:36 +01:00
SimonGschnell 43fbd1d8f1 refactor(Calendar/Day/Page.js): moves the content to the parent, so that different views can display different content 2024-11-25 13:28:55 +01:00
cgfhtw 9c32e6f968 Zeugnis title 2024-11-25 13:06:13 +01:00
SimonGschnell 36c129fcaf reafactor(Calendar/Day/Page.js-Calendar/Week/Page.js): refactors styles of elements for easier readability 2024-11-25 11:41:22 +01:00
Harald Bamberger df0ed6715c add renderif to default room action if no content id is defined 2024-11-25 11:31:13 +01:00
cgfhtw 28e4454409 Move Semester Filter to top component 2024-11-25 11:20:44 +01:00
cgfhtw 334fc870d0 Repeater Grades 2024-11-25 10:45:45 +01:00
Harald Bamberger 6f1e61fa00 move contentid of cis4 menu root to ci config, remove unused controller components CisVue, modify CISVUE-Header to use config for cis4 menu root content id 2024-11-22 15:16:27 +01:00
SimonGschnell 1297a8a23a reafactor(Calendar/Day/Page.js): refactors styles of elements for easier readability 2024-11-22 15:02:42 +01:00
Harald Bamberger 8e51071997 readd v-bind item removing it breaks dashboard customize view instead of plus signs a ghost widget is shown 2024-11-22 14:50:16 +01:00
Johann Hoffmann ecab3ea4d9 remove hardcoded h1 tag, keep the title h1 tag; more cleanup; 2024-11-22 11:43:05 +01:00
Andreas Österreicher 14169fafd0 Wording korrigiert 2024-11-22 11:42:24 +01:00
ma0068 9c503ae66f Validierung Modal askAusbildungssemester 2024-11-22 10:51:47 +01:00
Johann Hoffmann e2b42de6b3 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-11-22 10:27:12 +01:00
Johann Hoffmann f4d16af68e change eye watering cms css from green background & white font to white background and black font - as it should be 2024-11-22 10:26:47 +01:00
SimonGschnell ab15a8675c Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-11-22 10:25:22 +01:00
SimonGschnell 20abd6aa05 fix(LvMenu): makes non available menu punkte disabled and non interactable 2024-11-22 10:25:02 +01:00
Johann Hoffmann 4bd4301873 more template cleanup profil 2024-11-22 10:15:31 +01:00
Andreas Österreicher fa3d36e99e Added check if Constant CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN is
available at all
2024-11-22 08:46:42 +01:00
ma0068 bb724bef6e Bug filter Semester 2024-11-22 08:08:35 +01:00
Johann Hoffmann 16cfb0a3eb template cleanup profil 2024-11-21 17:32:34 +01:00
Johann Hoffmann 1a6b30588d MyLvApp & Components template & property definition cleanup 2024-11-21 16:11:02 +01:00
ma0068 b0fb045b50 Cleanup tasks: add factory, validations in form, phrases ID 2024-11-21 16:07:10 +01:00
Harald Bamberger fc5ea9f4db remove unused xmlns:fo add xsl:output method html 2024-11-21 15:59:42 +01:00
ma0068 f2b5c12e6d add abort controller to autocomplete fields 2024-11-21 15:53:58 +01:00
Johann Hoffmann 61728f3044 dashboard & widgets: template cleanup; property definiton cleanup; delete unwrapInjectedRef -> resolved since vue3.3; 2024-11-21 15:43:35 +01:00
Johann Hoffmann a349a179d0 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-11-21 15:22:09 +01:00
Johann Hoffmann d400f34e0f missing phrasen 2024-11-21 15:21:33 +01:00
Harald Bamberger cdc9e08cd0 cleanup C4 dbupdates 2024-11-21 15:14:13 +01:00
ma0068 94255709c7 mark mandatory fields 2024-11-21 14:31:57 +01:00
Harald Bamberger 8eb7d18ff9 remove C4 Menu from checksystem 2024-11-21 14:04:35 +01:00
Johann Hoffmann 920bd845f8 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-11-21 13:28:10 +01:00
Johann Hoffmann 933ca20e65 tabulator in cms content -> sanitize table header contructs breaking tabulator; 2024-11-21 13:27:39 +01:00
SimonGschnell 763d038b4c fix(api/v1/Stundenplan/getStundenplan): fetches groups and studentlehrverbaende based on the date interval of the current and previous semesters 2024-11-21 12:19:22 +01:00
Harald Bamberger 6946028d76 Merge branch 'master' into feature-25999/C4_cleanup 2024-11-21 11:39:50 +01:00
ma0068 7a0690227c Merge branch 'feature-47784/FHC-4/CleanupTasks' of github.com:FH-Complete/FHC-Core into feature-47784/FHC-4/CleanupTasks 2024-11-20 16:23:16 +01:00
ma0068 d17c776905 bug address.js, phrase Notiz 2024-11-20 16:22:39 +01:00
kindlm 222f31c464 Merge remote-tracking branch 'origin/master' 2024-11-20 16:01:07 +01:00
kindlm 155e8da35a Ampel Übersicht tablesorter with filter + date-sort bugfix 2024-11-20 16:00:57 +01:00
Cris e94e9ceff2 Added phrases 'zuordnungExistiertBereits' and 'swFuerLvAendern' 2024-11-20 14:07:43 +01:00
Cris 8a22eab0c8 Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2024-11-20 13:59:35 +01:00
Cris 95ebc442a4 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-11-20 13:58:27 +01:00
Cris ae94daa4a6 Added getStudienjahrByStudiensemester method to Studiensemester Model 2024-11-20 13:57:30 +01:00
Cris 933af94344 Added checkIsTemplate method to Lehrveranstaltung Model
Checks if given LV is a template (Quellkurs)
2024-11-20 13:55:11 +01:00
Cris 8614e4301f Added getStudienjahrByStudiensemester method to Studiensemester API Controller 2024-11-20 13:54:05 +01:00
cgfhtw e0e123f264 Teacher Component 2024-11-20 13:19:43 +01:00
cgfhtw ad01c8bdeb Bugfix: reinitialize initialData in Prestudent Tab after saving 2024-11-20 12:45:14 +01:00
cgfhtw 8593fda5cd Bugfix: scrolling in Notiz Tab 2024-11-20 12:44:45 +01:00
cgfhtw e76d8fb85d Phrases & TODO cleanup 2024-11-20 11:15:18 +01:00
Johann Hoffmann a5dd639404 stundenplan header offset class conditionally depending on fhc-calendar widget property 2024-11-20 11:14:55 +01:00
cgfhtw fe7ca2bf69 Teacher Proposal 2024-11-20 11:06:28 +01:00
cgfhtw 5369c95e77 Scroll Bug Notizen Tab 2024-11-20 11:05:05 +01:00
ma0068 b189ac8cd0 adapt Notes: Tinymce, textarea, delete bsModal 2024-11-20 10:41:12 +01:00
SimonGschnell 7466e414f8 Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-11-20 10:36:04 +01:00
SimonGschnell 3896aa73ea fix(Raum_information Calendar): passt die RaumInformations Seite auf die Aenderungen des Calenders an 2024-11-20 10:35:51 +01:00
Harald Bamberger f6319aa845 add new searchoptions to display search results correct again 2024-11-20 09:29:43 +01:00
Harald Bamberger 9420e22b2a optimise scrolling behavior of search results and responsive layout of search results 2024-11-19 18:13:15 +01:00
Johann Hoffmann 778149880f Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-11-19 17:46:32 +01:00
Johann Hoffmann 2c98438096 add cis4link to widget setup; show link icon in dashboard item header; remove links from widget contents; 2024-11-19 17:46:11 +01:00
Harald Bamberger a2bdca5551 fix typo 2024-11-19 17:44:44 +01:00
Harald Bamberger 05c52e41eb search only for active orgunits and rooms, also search room description 2024-11-19 17:33:57 +01:00
Johann Hoffmann 00406c50a5 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-11-19 17:09:58 +01:00
Johann Hoffmann 5e9e08d65e calendar scrollbar css fix; 2024-11-19 17:08:39 +01:00
Johann Hoffmann d8af18673c always show card header of widgets as in editMode but enable certain tools only when actually in editMode. editMode is active for dashboard not for section; less paddings overall in dashboard; deleted Section headers and put cog besides personal greeting; reformatted name var for greeting into generic viewData property; 2024-11-19 17:07:05 +01:00
Harald Bamberger c32046002d add buffer to height calculation 2024-11-19 16:24:36 +01:00
Harald Bamberger df054a7088 Merge branch 'feature-25999/C4_cleanup_rc' into feature-25999/C4_cleanup 2024-11-19 16:18:45 +01:00
Harald Bamberger 4e4e8a0a5c improve responsive layout of search results 2024-11-19 16:16:46 +01:00
Johann Hoffmann ad7b43f8a8 Merge remote-tracking branch 'origin/feature-25999/C4_cleanup' into feature-25999/C4_cleanup 2024-11-19 13:35:30 +01:00
Johann Hoffmann f82c669475 provide/inject editModeIsActive from section.js -> currently used in bookmark widget to move redundant config modal into actual widget when said mode is on; 2024-11-19 13:35:06 +01:00
SimonGschnell d2466b032a Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-11-19 12:51:50 +01:00
SimonGschnell 8d01995722 refactor(Studenplan Query):queries all studiensemester from start_date to end_date and matches the gruppen and studentlehrverbaende to the associated studiensemester in the query 2024-11-19 12:51:12 +01:00
Johann Hoffmann 3cb9e5b4f8 stpl widget title & show no LVA found on empty days; limit news widget content img max-width by css class; 2024-11-19 12:38:32 +01:00
SimonGschnell 5d5b2e5bc4 fix(FHCAPI_Controller): adjusts the php doc types of parameters 2024-11-19 11:35:20 +01:00
Johann Hoffmann 4cb3521361 Merge branch 'feature-53416/stundenplan_eine_lva' into feature-25999/C4_cleanup 2024-11-19 10:36:34 +01:00
Johann Hoffmann 46ef02b54d deactivate drag mode when widget config modal is opened 2024-11-19 10:33:39 +01:00
Harald Bamberger 9c6509b32a Merge branch 'feature-25999/C4_cleanup_tablewidget' into feature-25999/C4_cleanup 2024-11-19 10:18:26 +01:00
Harald Bamberger d6bdad27b2 move room specific stuff to searchconfig, add renderif method to be able to render actions conditionally via config, remove additional prop selectedtypes 2024-11-19 10:17:10 +01:00
SimonGschnell 4aed321b5e refactor(Calendar Tagesansicht): changes how the logic for opening a modal or showing the lvMenu next to the calendar is handled 2024-11-19 10:11:49 +01:00
Harald Bamberger 06dab52461 Merge branch 'feature-25999/C4_cleanup_tablewidget' into feature-25999/C4_cleanup 2024-11-19 08:48:06 +01:00
Harald Bamberger 6fc7fd7788 Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_cleanup_tablewidget 2024-11-19 08:44:24 +01:00
Harald Bamberger 13e77c8154 Merge branch 'master' into feature-25999/C4_cleanup 2024-11-19 08:43:05 +01:00
Johann Hoffmann b6a5e9b845 load stsemArray from Prestudentstati for select options; 2024-11-18 16:09:16 +01:00
Harald Bamberger ad31e73212 reset Tabulator fontsize, combine page headings 2024-11-18 11:59:40 +01:00
Harald Bamberger 5596c12af9 use deleteRow instead of getRow and delete to avoid console log error 2024-11-18 11:53:17 +01:00
Harald Bamberger e044641600 use deleteRow instead of getRow and delete to avoid console log error 2024-11-18 11:50:51 +01:00
Harald Bamberger 65c9d5a84c adminZeitverfuegbarkeiten reset tabulator fontsize 2024-11-18 10:47:08 +01:00
Harald Bamberger 545a9c31e4 tablewidget footer buttons add missing btn css class 2024-11-18 10:29:28 +01:00
Harald Bamberger 2b98a35f59 bs5 accordion-button class added 2024-11-18 10:20:13 +01:00
cgfhtw d650587418 use fhcApi for grades tab 2024-11-18 09:58:59 +01:00
SimonGschnell 96ec9aa8aa fix(Calender Style): changes the hover style for fhc-entries to have a brighter color than the selectedEvent itself 2024-11-18 09:32:49 +01:00
Harald Bamberger 1b8980a0e2 add css classe with bs3 legacy colors for bg-success and bg-warning and use them in acceptLehrauftrag cis page 2024-11-15 15:58:26 +01:00
Harald Bamberger 1e5d7e01af reset font-size for tabulator on vilesci page 2024-11-15 15:57:00 +01:00
Harald Bamberger 78f216f9ad fix syntax error 2024-11-15 15:55:42 +01:00
Harald Bamberger 16cba022e2 add css class to be able to reset tabulator fontsize to 14px for vilesci pages, set active and focus class for filter buttons to new combined button, add css rules to make tooltips on cells in unselectable rows work again 2024-11-15 15:21:46 +01:00
Harald Bamberger 488847984e change property downloadTitle to titleDownload for Tabulator 5, call tabulator redraw at the end of tableInit callback to ensure renderStart callbacks are run 2024-11-15 15:19:09 +01:00
Harald Bamberger daf432fe8d port changes made for BS3 => BS5 to version of current master to get rid of many whitespace and code formating changes and only have functional changes 2024-11-15 15:14:15 +01:00
Johann Hoffmann 3146f0795f Merge branch 'feature-53416/stundenplan_eine_lva' into feature-25999/C4_cleanup 2024-11-15 14:12:00 +01:00
Johann Hoffmann 87657a18f1 apply max width only to sanitized p blocks, not column default 2024-11-15 14:10:47 +01:00
Johann Hoffmann 6e8aea7feb Merge branch 'feature-53416/stundenplan_eine_lva' into feature-25999/C4_cleanup 2024-11-15 14:04:53 +01:00
Johann Hoffmann d9f33a279d apply html sanitization on legacy cms tables intended to be rendered with tabulator 5; clears nested tables, reformats rext nodes and unordered lists to fit into tabulator cells; 2024-11-15 14:02:05 +01:00
SimonGschnell fdcef8bdab feature(Calendar): keeps track of the selected Event in a shared state and highlights the selected Event over different calendar views 2024-11-15 12:52:24 +01:00
SimonGschnell 65d0e89f06 refactor(Stundenplan events css): moves the class definitions of the events to the slot templates and adds little animations 2024-11-15 11:48:55 +01:00
SimonGschnell 45fca04029 feature(Calendar Tagesansicht):based on the window with decides wether to display the lvMenu in a Modal or next to the calendar 2024-11-15 11:18:15 +01:00
ma0068 eccd827c71 adaptions and additions cleanup tasks according to task 54312 2024-11-15 11:14:58 +01:00
cgfhtw da465fffb1 Points to Grade conversion 2024-11-15 09:56:58 +01:00
cgfhtw 5705cd2d66 Note einblenden 2024-11-15 09:56:22 +01:00
SimonGschnell ef21936975 fix(Calendar scroll):ensures the calendar scroll watcher always triggers by also passing the current focusDate of the Calendar 2024-11-15 09:52:40 +01:00
Harald Bamberger 6b828179b0 revert lehrveranstaltung.class.php lehreinheit.class.php to current master since additional functions were ported to codeigniter models and are no longer used 2024-11-14 16:13:11 +01:00
SimonGschnell ebedb30c29 refactor(Stundenplan Tagesansicht):dynamically loads the lvMenu of the first Lv of the day and hightlights the selected LV of the day 2024-11-14 14:40:18 +01:00
Johann Hoffmann 8da27a5c77 stpl widget shows selected day + next 7 days 2024-11-14 13:12:56 +01:00
SimonGschnell 681fb18222 fix(Stundenplan): readds the loadEvents and deletes the template error 2024-11-14 11:15:02 +01:00
SimonGschnell f159d6e2a7 fix(Grid CSS): remove unused css rules and css classes 2024-11-14 11:07:58 +01:00
Johann Hoffmann 3fff0c5325 Merge branch 'feature-53416/stundenplan_eine_lva' into feature-25999/C4_cleanup 2024-11-13 18:59:33 +01:00
Johann Hoffmann 160294bea4 removed grey section background and added fading thing seperator line for every section after the first 2024-11-13 18:39:19 +01:00
Johann Hoffmann a682d6e5ae overflow-y scroll changed to overflow-y auto -> avoid unnecessary scrollbars 2024-11-13 18:14:58 +01:00
Johann Hoffmann 9042f9b83b change fh logo visibility breakpoint class md -> sm; editable flag in profile based on looking at own profile or being an admin; scrollbar calc in profil app; 2024-11-13 17:27:50 +01:00
Johann Hoffmann cad2756613 Merge branch 'feature-53416/stundenplan_eine_lva' into feature-25999/C4_cleanup 2024-11-13 15:21:33 +01:00
Johann Hoffmann 2fd39a9d18 defined active color variable for lvl 2 buttons and use in css class fhc-active for language Buttons. It is yet another shade of grey. 2024-11-13 15:19:42 +01:00
SimonGschnell 329a418be3 Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-11-13 14:53:49 +01:00
SimonGschnell e3cbbfa365 feature(Calendar Tagesansicht): LvInfo und LvMenu wird neben der Tagesansicht angezeigt wenn man eine Lv auswaehlt 2024-11-13 14:52:46 +01:00
Johann Hoffmann c85790b637 Merge branch 'feature-53416/stundenplan_eine_lva' into feature-25999/C4_cleanup 2024-11-13 14:14:34 +01:00
Johann Hoffmann 5d524c5fda fix dashboard alert css by adding primevue3 in $includeArray in Dashboard view file 2024-11-13 14:14:11 +01:00
Johann Hoffmann 6613b0ea40 remove console.log 2024-11-13 14:08:58 +01:00
Johann Hoffmann a94d8d8fa5 calendar minimized only using slot; showing whole week in stundeplan widget tagesansicht grouped by day; everything in past has 0.5 opacity 2024-11-13 13:57:37 +01:00
Andreas Österreicher 3c966e00ba Merge branch 'feature-47976/KU_Linz_Statistik_Austria_Export_BPK' 2024-11-13 12:11:35 +01:00
Johann Hoffmann e43a890aff Merge branch 'feature-25999/C4_cleanup' into feature-53416/stundenplan_eine_lva
# Conflicts:
#	public/js/apps/Cis/Stundenplan.js
#	public/js/components/DashboardWidget/Stundenplan.js
2024-11-13 11:17:43 +01:00
SimonGschnell 59f8f91af9 feature(Calendar Tagesansicht): Calender wird ausgegraut wenn keine LVs an diesen Tag vorhanden sind 2024-11-13 11:00:08 +01:00
Johann Hoffmann b0cd599999 WIP stundenplan widget tagesansicht 2024-11-13 10:41:50 +01:00
cgfhtw 1cdf1e7896 Anzahl anzeigen 2024-11-13 10:08:36 +01:00
SimonGschnell c244b3ad1b fix(Stundenplan): template error 2024-11-12 12:55:14 +01:00
ma0048 6b04dff4a3 - start tab tags hinzugefuegt 2024-11-12 11:47:16 +01:00
Harald Bamberger f265e20dce Merge branch 'feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp' into feature-25999/C4_cleanup 2024-11-12 11:21:16 +01:00
Harald Bamberger c691d155c9 remove dependecy to legacy phrases from LvMenu controller, add legacy phrases needed in LvMenu controller 2024-11-12 11:05:13 +01:00
SimonGschnell 3046c29ae2 fix(Calendar): does not display events on the calendar when sliding the carusel to avoid showing overlapping events 2024-11-12 09:57:10 +01:00
SimonGschnell 6cf7a8e35e fix(Calendar scroll): extends the id of the scroll anchor to include hour/day/week and changes the logic to search for the anchor depend on the week or day view 2024-11-12 09:48:03 +01:00
SimonGschnell 35691b39c4 fix(Calendar scroll): fixes the scroll feature for the Calendar 2024-11-11 16:15:14 +01:00
Johann Hoffmann 85bec1e0e3 section spacing; dashboard widgets section backgrounds; set scrollbar width css variable via new helper in FhcApp (Dashboard); WIP stundenplan alle Termine einer LV -> c4 link in bfi addon adapted; 2024-11-11 15:49:03 +01:00
SimonGschnell 094a3ed56a feature(Calendar): scrolls to the first event of the day if the prop scrollTime is passed to Calendar component 2024-11-11 15:46:09 +01:00
SimonGschnell bd1ce9fa63 refactor(Calendar Header): refactors view buttons in the calendar header 2024-11-11 14:57:34 +01:00
SimonGschnell bd54399cfd fix(Calendar Header): adds responsiveness to the calendar header and the view button group next to the header 2024-11-11 14:57:28 +01:00
SimonGschnell b7e89ab557 fix(Stundenplan hour lines): fixes the hour lines from disapearing on smaller viewports by using a box-shadow instead 2024-11-11 11:27:23 +01:00
SimonGschnell 0e49dfaba0 refactor(Calendar day view): changes the classes for fhc-calendar-day-page so that the width is divided in calendar and content 2024-11-11 10:40:58 +01:00
Johann Hoffmann 96335a7979 moved email template to fhtw addon; einheiten column visibility default false since pausen are not represented; backend code cleanup; phrase fix; 2024-11-11 09:56:43 +01:00
ma0048 355652cdb1 - added sql for tags 2024-11-11 07:51:52 +01:00
ma0048 45bc65d32a - Tags testversion
- header tooltips
- lehre spalte markieren wenn altes semester
- legende-tab hinzugefuegt
2024-11-11 07:33:49 +01:00
SimonGschnell ca7ded38d2 refactor(Stundenplan indicator): uses a 5 minute interval for the Stundenplan indicator 2024-11-08 16:08:08 +01:00
SimonGschnell f304e79ee0 feature(Stundenplan): adds Tagesansicht for the Stundenplan 2024-11-08 15:18:10 +01:00
SimonGschnell 68042c1c77 Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-11-08 14:14:54 +01:00
SimonGschnell b9690988e5 refactor(Stundenplan): uses named slots for week-view template 2024-11-08 10:53:02 +01:00
Harald Bamberger 1691c75a84 replace dependencies on legacy code with ci model functions 2024-11-07 19:18:08 +01:00
SimonGschnell f4176b86ee refactor(js helpers): moves ObjectUtils from composables to the js helpers folder and changes its import statements 2024-11-07 15:00:25 +01:00
SimonGschnell da70c77a2b feature(DateHelpers.js): creates a js helper file to create, handle and manipulate js dates 2024-11-07 15:00:18 +01:00
SimonGschnell 6732063e6a Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-11-07 13:15:08 +01:00
SimonGschnell b65d17e7ae refactor(LvModal): uses the right format for the date and adds padding to date numbers which are single digits 2024-11-07 13:14:40 +01:00
Andreas Österreicher f68d18f0a8 Stundenplan Bugfix to also load Entries of Semester and Verband 2024-11-07 10:25:42 +01:00
SimonGschnell 4f2992fbe2 fix(Cis profil menu): fixes the layout of the collapsible in the mobile view 2024-11-07 10:21:39 +01:00
Harald Bamberger 2b516d40c9 remove controllers, views and libraries for CisHtml since not used 2024-11-05 17:46:42 +01:00
Harald Bamberger 39cedfe6a0 remove controllers, views and libraries for CisHmvc since not used 2024-11-05 16:48:30 +01:00
SimonGschnell 8316290b31 fix(Cis Navbar Collapsibles): closes other colapsibles when opening another 2024-11-05 15:54:26 +01:00
SimonGschnell 7653bc3e29 fix(Menu User Dropdown): rearranges html elements to make dropdown scroll 2024-11-05 12:03:44 +01:00
SimonGschnell 37dffbba19 fix(Dashboard widget Url): adds validation method for both input fields and fixes confirm delete dialog 2024-11-05 11:32:02 +01:00
Harald Bamberger a9fe52d3c6 Merge branch 'feature-25999/C4_cleanup_merge_anrechnungen_bs5' into feature-25999/C4_cleanup 2024-11-05 07:59:21 +01:00
Harald Bamberger 20e0e2e910 Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_cleanup_merge_anrechnungen_bs5 2024-11-04 15:59:14 +01:00
Andreas Österreicher 835adca419 Debugging option entfernt 2024-11-04 15:42:47 +01:00
Harald Bamberger 50880c696b use getAuthUID function instead of get_uid, use new permission basis/cis and switch to Auth_Controller where possible 2024-11-04 15:41:02 +01:00
Harald Bamberger a65e94bc8a fix phrases variable name because of switch from mixin to plugin 2024-11-04 15:38:04 +01:00
Harald Bamberger 20715d6ef5 add permission basis/cis 2024-11-04 15:36:46 +01:00
Harald Bamberger c31cef349c add phrases from legacy code for news extra aside content 2024-11-04 15:35:35 +01:00
SimonGschnell 50a67a8e88 feature(Dashboard Bookmark): checks whether the link is a valid URL, displays fhcAlert otherwise 2024-11-04 14:37:09 +01:00
SimonGschnell eafbdcfffe refactor(Cis Menu): changes method name and checks if the CIS4_MENU_ENTRY constant is defined 2024-11-04 13:39:13 +01:00
ma0048 9c637b8575 - added model 2024-11-04 12:20:52 +01:00
SimonGschnell 86ee48888a fix(Cis Menu): adds Zahlungen to Mein Studium 2024-11-04 12:09:26 +01:00
SimonGschnell 9e45394deb fix(Cis MyLv): uses the moodle course bezeichnung for multiple moodle links 2024-11-04 12:09:12 +01:00
SimonGschnell ad068ffe5f different property name for the different moodle courses names 2024-11-04 09:07:35 +01:00
Harald Bamberger 93ac45308f Merge branch 'feature-36185/requestAnrechnung_bootstrap3_zu_bootstrap5' into feature-25999/C4_cleanup 2024-10-31 16:00:12 +01:00
SimonGschnell 34c6c63c74 Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-10-31 14:24:19 +01:00
SimonGschnell f820a0148a adapts the LV view to incorporate a dropdown if a lehrveranstaltung has multiple moodle links 2024-10-31 14:22:46 +01:00
Harald Bamberger e78c2e1bf7 Merge branch 'master' into feature-25999/C4_cleanup 2024-10-30 17:19:01 +01:00
Harald Bamberger d4f3fbfc79 Merge branch 'master' into feature-36185/requestAnrechnung_bootstrap3_zu_bootstrap5 2024-10-30 16:45:07 +01:00
SimonGschnell c5b81c22f9 adds the target for the lv menu in the studenplan modal and also replaces the tablesorter tables with tabulator5 in other content views 2024-10-30 11:31:39 +01:00
SimonGschnell 837cc191bf adds another link regex for the link string '../cms/content?content_id=...' and adds the library content to the CIS4 Menu content 2024-10-30 10:49:27 +01:00
Alexei Karpenko 9b4fb2ac2c bpk job: enabled getting vBPKs with new API version 0.8 2024-10-29 16:28:17 +01:00
SimonGschnell 6b991c514e refactors the room actions in the searchbar 2024-10-29 15:49:56 +01:00
SimonGschnell bdfea1763d adds gaps to the LvMenu 2024-10-29 15:38:10 +01:00
SimonGschnell 587a193a6b refactors the LvMenu Modal 2024-10-29 15:18:53 +01:00
Johann Hoffmann ec9e73180d primevue custom tooltip directive zIndex config retrieval fix; studentByLva tabulator height calc abort if no dataTable rendered; phrases fix; 2024-10-29 15:13:00 +01:00
SimonGschnell ff367339ea makes MyLv more responsive 2024-10-29 14:31:20 +01:00
Harald Bamberger ae80c3415d betraege im Gehaltsbestandteil als string mit . als komma konvertieren, um zu verhindern, dass locale spezifische Betraege in der verschluesselten DB Spalte gespeichert werden 2024-10-29 10:37:00 +01:00
Harald Bamberger 1e55b13546 force use of insertamum column from antrag table 2024-10-28 15:58:20 +01:00
SimonGschnell b9ccafe9db uses the cis.php file for the anrechnungen url 2024-10-28 15:57:33 +01:00
SimonGschnell 5f078a76c6 renders the right header (cis or fhtw) conditionally based on the CIS4 constant 2024-10-28 14:54:26 +01:00
SimonGschnell 3eb2100b3d Merge branch 'feature-25999/C4_cleanup' of github.com:FH-Complete/FHC-Core into feature-25999/C4_cleanup 2024-10-28 14:16:07 +01:00
SimonGschnell fbf0417269 only adds the Events file from addons which are actually active and refactors the Lv Information into its own component 2024-10-28 14:15:45 +01:00
SimonGschnell b801401d2b only shows the Week modus of the calendar if it is not a widget and opens the MyLV links as new tabs instead of showing them in the modal 2024-10-28 13:25:41 +01:00
Johann Hoffmann 46c4a30408 css fix & header file import remove 2024-10-28 11:36:49 +01:00
Johann Hoffmann 6fc5714fdf removed language flags; anw phrasen added; added names to apps for easier devtools debugging; 2024-10-25 16:34:57 +02:00
Johann Hoffmann 74cf0ad173 use vue header & tooltip translations 2024-10-25 15:58:37 +02:00
Johann Hoffmann e387671e09 added set language feature; phrasen plugin with optional reload if non responsive phrasen are used; stundenplan header mode & buttons reworked 2024-10-24 17:46:42 +02:00
Johann Hoffmann 32137479e9 activate email to assistenz on upload; redraw table in case of tabulator scroll bug; navigation.php $root var for Cis4 preperation 2024-10-24 15:07:08 +02:00
Harald Bamberger 2398ca1962 Merge branch 'feature-52916/Unterbrecher_in_serie' 2024-10-24 11:15:36 +02:00
cgfhtw 9eb91574c3 semester 2024-10-24 11:08:22 +02:00
cgfhtw 2edfd1febc Unterbrecher in serie problematik 2024-10-24 11:03:28 +02:00
Harald Bamberger 4789bfab42 add columns gehaltsbestandteil_von and gehaltsbestandteil_bis to hr.tbl_gehaltshistorie 2024-10-24 07:57:54 +02:00
ma0068 0779bc5204 bugfix add and update Adresse 2024-10-23 16:33:02 +02:00
ma0068 e283997293 cleanUp Tasks Tab Details 2024-10-23 14:26:33 +02:00
ma0048 e89beb610d - infocentermitarbeiter spalte deleted by user wird ignoriert 2024-10-23 13:33:50 +02:00
Johann Hoffmann 805ed20a18 Merge branch 'feature-52360/C4_fh_logo_remove_and_extend_searchbar_mobile' into feature-52734/C4_moodle_link_stpl_widget_stpl_mylva 2024-10-22 17:52:57 +02:00
Harald Bamberger f59bdf812a add phrase mark_person_as_unruly 2024-10-22 17:18:02 +02:00
Harald Bamberger 384de674c0 Merge branch 'feature-40896/kennzeichnung_unruly_person' 2024-10-22 16:50:53 +02:00
Harald Bamberger fa0fe2a952 hide unruly option in AbmeldungStg for the moment 2024-10-22 16:49:56 +02:00
ma0068 8787558fef cleanUp Tasks Tab PrestudentIn 2024-10-22 15:58:02 +02:00
Harald Bamberger 8ba2a6852b Merge branch 'master' into feature-40896/kennzeichnung_unruly_person 2024-10-22 11:04:07 +02:00
Harald Bamberger c763e332d8 Merge branch 'feature-52735/C4_stundenplan_query_fix' into feature-25999/C4_cleanup 2024-10-21 17:16:21 +02:00
Johann Hoffmann f3851da10d add bootstrap class to only show fh logo in header on medium and greater displays; adjusted nav-user-btn css under mobile breakpoint to just take space of contained img and let searchbar flex growth apply to leftover width; 2024-10-21 16:02:54 +02:00
Cris dcb24415fc Added phrases 'errorConfigFehlt' and 'errorUnbekannteUrl' 2024-10-21 14:02:25 +02:00
Johann Hoffmann 2e3bc855aa Merge branch 'feature-25999/C4_cleanup' into feature-52735/C4_stundenplan_query_fix 2024-10-21 13:51:21 +02:00
Johann Hoffmann 728e2f9b3a fix getStundenplanQuery query building if benutzer gruppen are empty; 2024-10-21 13:48:32 +02:00
Harald Bamberger 690080035a fix umlauts in variable name 2024-10-21 13:05:47 +02:00
Johann Hoffmann d8c4c6506a Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp 2024-10-21 10:21:42 +02:00
Harald Bamberger 9cd59a1250 add header version switch depending on CIS4 defined 2024-10-18 17:16:12 +02:00
Harald Bamberger 289c99a5a1 fix another 2 file permissions erroneously commited as a21a292da6 2024-10-18 17:03:40 +02:00
Harald Bamberger cf77a60b35 remove application/controllers/components/Antrag/* since not present in master any more 2024-10-18 16:57:03 +02:00
Harald Bamberger 0775fae67d remove unnecessary comment 2024-10-18 16:49:52 +02:00
Harald Bamberger 071b0c72dc Merge branch 'master' into feature-25999/C4_cleanup 2024-10-18 15:45:42 +02:00
Harald Bamberger 44b81d9dff Merge branch 'feature-25999/C4' into feature-25999/C4_cleanup 2024-10-18 15:44:39 +02:00
Johann Hoffmann 7ce426abc2 tooltip css fix; added missing phrase; 2024-10-18 15:14:13 +02:00
Andreas Österreicher 501784aba1 Zusätzliche Reihungsteststufen hinzugefügt 2024-10-18 14:24:16 +02:00
ma0048 5cee80ed12 - rtliste automatisierte messages 2024-10-18 13:24:39 +02:00
SimonGschnell 8ba370d3a7 makes the active menu punkt bold instead of underlined 2024-10-18 11:58:14 +02:00
SimonGschnell 59df85b05e adds Zeugnisse und Documents unter dem Mein Studium Menu Punkt 2024-10-18 11:55:20 +02:00
SimonGschnell 909b9f5f5a Merge branch 'feature-25999/C4' of github.com:FH-Complete/FHC-Core into feature-25999/C4 2024-10-18 11:19:18 +02:00
SimonGschnell 236c4bbdfc adds placeholders to the empty dashboard fields, that can be used to add new widgets to the dashboard 2024-10-18 11:18:36 +02:00
Harald Bamberger 755e8dd222 add provide to vuejs plugins FhcAlert, FhcApi and Phrasen so they are also useable with inject in composition api 2024-10-17 16:37:27 +02:00
Harald Bamberger c80e943b3b readd erroneously deleted folder addons/template commited as 56080f6681 2024-10-17 15:55:05 +02:00
Harald Bamberger d4494836b1 fix file permissions erroneously commited as a21a292da6 2024-10-17 15:34:00 +02:00
Johann Hoffmann a04b2725f9 csv download lektor table as is; cis_menu_lv link hidden behind berechtigungen check; every tabulator now calculates remaining height by accessing window.visibleViewport.height and tabulator dataset element in order to get virtual DOM behaviour for faster rendering and better UX; filter component now emits uuid on created() lifecycle; 2024-10-17 15:04:03 +02:00
Harald Bamberger 0ab1ec1fc8 Merge branch 'master' into feature-25999/C4 2024-10-17 14:49:43 +02:00
SimonGschnell e475fe568e adds the dashboard menu punkt and adds greeting to the dashboard view 2024-10-17 09:58:28 +02:00
Cris 2f448ca2bc Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite
# Conflicts:
#	system/phrasesupdate.php
2024-10-16 09:44:50 +02:00
Cris 38bf664b02 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-10-16 09:41:12 +02:00
Harald Bamberger 24ce443e95 nur die letzte komm oder zusaetzlichen komm Pruefung einer LV beruecksichtigen 2024-10-15 17:40:11 +02:00
Harald Bamberger 439ae5113d fix unterbrechung erstellen nicht möglich wenn ein abgelehnter unterbrechungsantrag existiert 2024-10-15 13:59:11 +02:00
Cris d913bf40d8 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-10-15 12:07:08 +02:00
Harald Bamberger 14aa98c223 Merge branch 'master' into feature-25999/C4 2024-10-15 10:46:17 +02:00
Harald Bamberger e2cee7ffa3 Merge branch 'master' into feature-25999/C4 2024-10-15 10:44:56 +02:00
Andreas Österreicher 5774cb78c9 Merge branch 'feature-40816/Plausicheck_Anpassungen' 2024-10-15 10:28:38 +02:00
Harald Bamberger 27e3f1d1bc take status rejected into account when calculating available semster slots for unterbrechung 2024-10-14 15:40:25 +02:00
Alexei Karpenko 301466f944 Merge branch 'master' into feature-40816/Plausicheck_Anpassungen 2024-10-14 15:20:16 +02:00
SimonGschnell 9ed08fb40c default value for hasConfig is false and the emit update for the URL dashboard widget and only loads the config component if the dashboard widget actually has a config 2024-10-14 13:36:31 +02:00
Alexei Karpenko 2893f2ec5a bugfix lvplan feedback link stpl_detail: correct html 2024-10-14 13:21:19 +02:00
SimonGschnell b0e96fbab1 replaces the emits to injections to avoid repassing the emits between intermediate parent elements 2024-10-14 11:42:30 +02:00
SimonGschnell 0528f3b262 checks the size of the arrays before using the current method and does not allow mitarbeiter to access the student stundenplan 2024-10-14 11:32:23 +02:00
SimonGschnell 462857080b makes the parent menu point active if the child menu points gets closed 2024-10-14 11:06:48 +02:00
Johann Hoffmann c67e78d135 phrasen rewording; formatter change; fix save changed anwesenheiten StudentByLvaComponent.js; 2024-10-14 10:42:49 +02:00
SimonGschnell 4f9591fc3b fix the z-index of the week stundenplan header 2024-10-14 10:36:46 +02:00
SimonGschnell c444e27d0d adds more styling and fixes little bug in the currentHour Stundenplan indicator 2024-10-14 10:34:01 +02:00
SimonGschnell ed1d4b1a50 regex replaces old content links with new CIS4 controller links and adopts the Menu Entry links to not refresh the page when closing the Menu point 2024-10-14 10:17:20 +02:00
SimonGschnell 9fd02460ce doesnt refresh the page when the menu entry gets closed, does redirect if the menu entry gets opened 2024-10-14 09:48:54 +02:00
Alexei Karpenko 1c61217891 lvplan: changed feedback phrase and Link 2024-10-13 13:34:07 +02:00
SimonGschnell f9e72832c9 adds time inidication on stundenplan on mouse position 2024-10-11 12:33:06 +02:00
SimonGschnell 5359539a09 makes Stundenplan query BLAZINGLY fast 2024-10-10 20:59:55 +02:00
SimonGschnell d2ed82cb37 calculates the total amout of hours with an array filter instead of statically inserting all hours 2024-10-10 13:27:26 +02:00
SimonGschnell f3fa2fa2dd adds the hour gutter for the stundenplan with absolute positioned divs instead of a linear gradient 2024-10-10 13:12:01 +02:00
cgfhtw 469867e98c Studstatus: status "EmailVersandt" is not an active status 2024-10-10 12:37:57 +02:00
SimonGschnell bf8085f642 starts the stundenplan from hour 7 instead of hour 0 2024-10-10 11:24:26 +02:00
Johann Hoffmann 9be5dc3f73 phrasen; tooltips; 2024-10-10 09:47:40 +02:00
Andreas Österreicher 9ca59f7928 Paragraph Verweis korrigiert für Master Plagiatsprüfung 2024-10-09 15:22:41 +02:00
Harald Bamberger b3258e017c add column path_kurzbz to view vw_oe_path 2024-10-09 13:14:54 +02:00
Harald Bamberger 1da045f58e Merge branch 'feature-40953/LV-Template_Uebersichtsseite' 2024-10-08 16:38:50 +02:00
Harald Bamberger 3c4b4b6a58 recht lehre/lehrveranstaltung auch am api endpunkt 2024-10-08 16:38:16 +02:00
Harald Bamberger 455d154b63 recht lehre/lehrveranstaltung statt basis/vilesci, schriftgröße verkleinern, menuepunkt in vilesci, headerfilter angepasst 2024-10-08 16:19:57 +02:00
SimonGschnell 4d50d4380b little bug fix 2024-10-08 13:54:58 +02:00
SimonGschnell 45ff067379 makes the url match to the Menu entries better 2024-10-08 13:47:48 +02:00
SimonGschnell ebebf8af6d changes calendar mode to button-group instead of select 2024-10-08 13:29:43 +02:00
SimonGschnell 79c8edc6cf makes the calendar week mode header align and highlights the week or day in the Month view depenedent if there is a week view available 2024-10-08 13:20:06 +02:00
Harald Bamberger a2f70be7e4 Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2024-10-08 09:28:56 +02:00
Cris 7096bba958 Added phrases for Softwarebereitstellung 2024-10-07 16:37:45 +02:00
Cris b08e01f72f Added columns to and moved where-clauses from _getQryLvsByStudienplan to calling methods in Lehrveranstaltung_model.php
.added cols lehrtyp_kurzbz and lehrveranstaltung_template_id
2024-10-07 16:37:07 +02:00
Cris 8744a00ce7 Added filter lehrtyp_kurzbz and $oe_column to getLvsByStudienplan in Lehrveranstaltung_model.php
.lehrtyp_kurzbz filters by Lehrtyp 'lv' or 'modul' (default no filter)
.oe_column is used when filtering $oes: Filter by lv.oe_kurzbz or stg.oe_kurzbz (the stg joined to lv)
2024-10-07 16:34:41 +02:00
Cris 11b0e770a2 Added filter lehrtyp_kurzbz to getAutocompleteSuggestions in Lehrveranstaltung_model.php 2024-10-07 16:29:53 +02:00
Johann Hoffmann 008bbedd98 phrase 2024-10-07 16:22:27 +02:00
SimonGschnell e75872adaa lets the user change the view of the calendar in the header with a select and highlights the date fields to change the view of the current calendar 2024-10-07 14:49:02 +02:00
kindlm 41a10320f8 Bugfix LV-Teile Vorrückung, wenn Von-Semester leer
Umbenennung Lehreinheit in LV-Teil
2024-10-04 13:51:48 +02:00
SimonGschnell 25a64cbcae fixes cis4 Menu for longest matching urls 2024-10-04 12:04:54 +02:00
Johann Hoffmann 772fe616ff remove unused unruly code nr2; 2024-10-03 13:27:05 +02:00
Johann Hoffmann a9d0f177da remove unused unruly code; 2024-10-03 13:25:02 +02:00
Johann Hoffmann ef0e3f3a66 Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp 2024-10-03 11:24:48 +02:00
Andreas Österreicher 35043ad0ec Merge branch 'bug-48771/messages_list_limit' 2024-10-03 11:19:47 +02:00
ma0048 9dbb5291f4 - added limit 2024-10-03 11:17:09 +02:00
Johann Hoffmann dbf5935897 check correct grund phrase to trigger unruly api request; 2024-10-03 11:14:52 +02:00
Andreas Österreicher c754291c6d Merge branch 'feature-20228/erfassung_internationalisierungsmassnahmen_beurteilung' 2024-10-03 10:42:00 +02:00
Johann Hoffmann ed6eb18c4d fetch termine from vw_stundenplan, not tbl_stundenplan; LE_ID DD chagned to refs (WIP MA_UID DD & Termin DD); removed console.logs(); fhcAlert fix; now find closest termin with absolute value of timeDiff; 2024-10-02 18:04:30 +02:00
SimonGschnell 8042f3ae0b makes the menu point active with the url matches 2024-10-02 14:22:34 +02:00
ma0048 317796c919 - legende und phrasen hinzugefuegt 2024-10-02 14:13:44 +02:00
SimonGschnell e8f38bfcf6 sets the events to null before fetching the new events to reactivate the loading spinner 2024-10-02 13:28:18 +02:00
SimonGschnell 7f9352b820 prototyp fuer die Stundenplan query fuer Studierende 2024-10-02 13:25:39 +02:00
SimonGschnell c461480d1d stundenplanQuery optimization 2024-10-02 10:35:58 +02:00
ma0068 b9911e69c5 renaming id: Tab Contact 2024-10-02 08:58:24 +02:00
ma0068 00cf7b8112 tabs Status and Gesamthistorie: use factories 2024-10-01 15:27:36 +02:00
SimonGschnell 567dd816be better descriptions for the cis4_root_menu sql queries 2024-10-01 13:54:53 +02:00
SimonGschnell 76facc40b9 changes the layout for the LvMenu to a flex instead of a grid 2024-10-01 12:14:34 +02:00
Johann Hoffmann ce058df3a5 Student Component Performance Fix (dont subquery person and anwesenheiten_user table on every anw_user row, just do the entschuldigung offen/abgelehnt logic in client before rendering); entschuldigung tab route; pagination on student entschuldigung page aswell; added config for einheiten länge to calculate/show; mitarbeiter selection in case of admin & lektor in same account behaving as expected; added index creation to initial sql scripts; 2024-09-30 17:25:51 +02:00
SimonGschnell 23b7d18906 gives the content_childs of the CIS4_ROOT the correct ordering 2024-09-30 14:24:48 +02:00
SimonGschnell fa8aec2c2e adds the MyLv and the Stundenplan Menupunkt to the sql inserts and changes the content for the Dokumente redirect 2024-09-30 14:13:00 +02:00
SimonGschnell 6f0f3890f9 doesnt show the footer in the editProfil modal when opening a ProfilUpdate 2024-09-30 13:43:26 +02:00
SimonGschnell 8f617c6222 fixes littel bug with the edit-profil modal in the StudentProfil 2024-09-30 13:20:14 +02:00
SimonGschnell f38b0cf78f changes all the Headers from the CISHTML-Header to the CISVUE-Header 2024-09-30 11:58:20 +02:00
SimonGschnell 964f6c689c removes debugging prints 2024-09-30 11:44:31 +02:00
SimonGschnell 4a5a019841 loads the menu for the CISVUE-Header in the server side and not in the client side 2024-09-30 11:33:55 +02:00
SimonGschnell 24a2b4ba2f fixes the bug where the Menu is still selected in the LvModal after clicking on the back button 2024-09-30 11:20:20 +02:00
SimonGschnell 8c6f9d1bc4 loads the menu for the CISVUE-Header in the server side instead of the client side 2024-09-30 11:14:34 +02:00
SimonGschnell 0e385e8628 makes the menu of the CISVUE-Header also sticky now 2024-09-30 10:30:11 +02:00
SimonGschnell bbed90c814 moves the searchbar from the mobile view to the top of the header 2024-09-30 10:26:23 +02:00
SimonGschnell c0596c08c5 changes the header for the Dashboard to the CISVUE-Header and passes the selectedTypes props to fix the CISVUE Header search 2024-09-30 09:43:26 +02:00
SimonGschnell d1070656ac CIS4 MENU sql update COMPLETE 2024-09-27 13:38:29 +02:00
SimonGschnell 23badc3404 CIS4 MENU sql update WIP 2024-09-27 12:20:37 +02:00
ma0048 0f708f4934 - added app pep
- phrases
- added error
- added model
2024-09-27 11:23:54 +02:00
ma0068 0127982f50 use factories in Address.js, Bankaccount.js, Contact.js 2024-09-27 10:54:54 +02:00
SimonGschnell 73a2bf59f3 resolves buggs with the checkActiveUrl method 2024-09-27 10:44:09 +02:00
Harald Bamberger be412abebc Merge branch 'master' into feature-40896/kennzeichnung_unruly_person 2024-09-26 16:16:24 +02:00
SimonGschnell bc6bc930fe moves the news titel to the component and adds css classes for darker dropdown buttons for the different menu levels 2024-09-26 12:05:44 +02:00
ma0068 9d5a0585b0 Phrases alerts, templates, tabulator 2024-09-26 07:56:15 +02:00
SimonGschnell b174818ed2 updates the active state of the menu based on the changed url 2024-09-25 15:02:35 +02:00
SimonGschnell b0a78658cf also makes the menu points active which redirect to an url hash 2024-09-25 13:35:41 +02:00
SimonGschnell a1fade0489 fixes the recursive function to find a child content_id 2024-09-25 12:25:19 +02:00
Harald Bamberger 2fc0827d49 revert erroneously merged pull request 2024-09-25 11:22:59 +02:00
SimonGschnell 951d5bb2c7 all the parents of an active child are also active 2024-09-25 10:46:09 +02:00
SimonGschnell 3c050438b3 makes the dropdown button of the menu points darker to make them more visible 2024-09-25 09:26:08 +02:00
Christian Paminger 90931232d9 Merge pull request #49 from FortySeeds/master
Enable HTTP-Basic Auth for Demo and Testing
2024-09-25 05:57:13 +02:00
Christian Paminger 427a301d1a Merge branch 'FH-Complete:master' into master 2024-09-25 05:51:11 +02:00
Christian Paminger f66c3466ed Extend HTTP-Basic-Auth for Demo-Mode and easier testing 2024-09-25 05:40:04 +02:00
ma0068 1df91303f0 update Permissions, update validations, insert Termin1 with Termin2, finish phrases 2024-09-24 15:10:31 +02:00
SimonGschnell 7ed7ce1bb9 active Menu Entry logic for CISVUE 2024-09-24 14:57:41 +02:00
Andreas Österreicher b184cee975 Offset für das Laden von Geschaeftsjahren hinzugefügt 2024-09-24 12:40:12 +02:00
ma0048 419f608322 - benotung international skills hinzugefügt
- phrase
2024-09-24 12:05:09 +02:00
Andreas Österreicher 5d70f72cc2 Merge branch 'feature-40348/UHSTAT_1_Unbekannte_Eltern' 2024-09-24 11:22:34 +02:00
KarpAlex 5057b2d761 bugfix unbekannte Eltern: unknown can always be chosen, and it is valid. Only if Land des Abschlusses in austria, austrian max Bildung options can be chosen 2024-09-23 18:27:19 +02:00
SimonGschnell 470192aabd fixes some bugs in the View/Entry.php for the Menu 2024-09-23 15:14:31 +02:00
SimonGschnell 45d350a76e changes the header for the news and puts the LV title in the card header / removes the lines of the lehrveranstaltungs optionenen 2024-09-23 13:24:58 +02:00
Alexei Karpenko 3b20f5e45c Plausichecks: removed check BewerberNichtZumRtAngetreten 2024-09-20 16:12:14 +02:00
Alexei Karpenko 2d3643d1f0 Bismeldestichtag: added method for getting next Meldestichtag, loading data only after tabulator is ready 2024-09-20 16:04:27 +02:00
Johann Hoffmann effad6f62d only fetch person_id, vorname, nachname & unruly from tbl_person on checkUnruly() 2024-09-20 15:16:20 +02:00
ma0068 4579c133a8 Validierung Eintragung Note after ExamDate, Hinweis KommPruefung, Phrases 2024-09-20 14:21:45 +02:00
SimonGschnell 98c85f1241 little changes to the view for the content 2024-09-20 14:20:44 +02:00
Johann Hoffmann 958c897467 changed unruly html from a tags to p tags since they messed with styles somehow 2024-09-20 13:54:32 +02:00
Johann Hoffmann a2e4704223 developing new components in lektor ui for ux improvements; anw function now explicitely in extension schema 2024-09-20 13:12:50 +02:00
ma0068 a7f51205b1 Show Kürzel Ma in Dropdown, Filter current semester, adapt Berechtigungen, reload semester 2024-09-20 11:41:44 +02:00
SimonGschnell 9343d1ee0c refactor Content_types template 2024-09-20 11:26:08 +02:00
SimonGschnell ca4865011d adds missing parameters to the getContent function 2024-09-20 11:21:59 +02:00
SimonGschnell 693313a23b renames/reuses lv-modal and fixes bugs associated with the modal 2024-09-19 09:35:36 +02:00
ma0068 f874ca43c0 Standard validations, show Hint KommPrfg, disable noten not active 2024-09-18 16:03:35 +02:00
SimonGschnell b9fd95741d moves the CalendarModal into the Stundenplan component instead of the Calendar component and changes the start_time and end_time computed properties 2024-09-18 14:40:58 +02:00
SimonGschnell 5877411db8 also loads the stundenplan data when the component is created 2024-09-18 13:52:49 +02:00
SimonGschnell f7b3af4939 makes the studiengang_semester reactive using computed when providing the value 2024-09-18 13:17:14 +02:00
SimonGschnell 164fc4b132 converts the dropdown of the lehrveranstaltungs optionen into a list inside the lv card 2024-09-18 12:52:55 +02:00
Andreas Österreicher e6eea06900 Merge branch 'feature-40348/UHSTAT1_unbekannte_Eltern' 2024-09-18 12:41:05 +02:00
Andreas Österreicher f499110bbf Merge branch 'feature-41046/wartende_anschreiben_onetimemessages_abgewiesene_werden_nicht_ausgefiltert' 2024-09-18 12:28:50 +02:00
Andreas Österreicher d0281bb3b4 Merge branch 'feature-47888/projektarbeit_endabgabe' 2024-09-18 12:24:37 +02:00
SimonGschnell 910a467fcc changes the stundenplan widget to use the new api endpoints that query the stundenplan events 2024-09-18 11:44:47 +02:00
ma0048 91174ca974 - schickt message, nur wenn wartender der letzte status ist 2024-09-17 15:35:00 +02:00
ma0068 4d5ea1f519 adapt addNewPruefung, pruefungModal, function getLvsByStudent 2024-09-17 15:28:18 +02:00
Johann Hoffmann 79ea8c4521 renamed unrulyPerson api to checkPerson; built in logic into infoCenterDetails to trigger a number of checks about any changed data in the info center (in this case unruly) and update the page accordingly; Also fixed a bug when saving stammdaten without kontakt entries; 2024-09-17 14:09:49 +02:00
SimonGschnell 6edc411a95 adds the LvMenu as dropdown options to the MyLV 2024-09-17 12:34:47 +02:00
SimonGschnell 5ca639101c fixes Month display of LVs 2024-09-17 11:39:39 +02:00
ma0048 7c85e981f9 - absteigende sortierung endabgabe 2024-09-17 11:17:44 +02:00
SimonGschnell d931aad11c solves reactive data problem in CalendarModal 2024-09-17 09:41:17 +02:00
SimonGschnell 61e6ad063a solves Telefon displaying as null for some benutzer 2024-09-17 09:28:11 +02:00
Cris d6d6d0ac48 Added phrases for softwarebereitstellung app 2024-09-16 18:22:28 +02:00
Cris 585cec31e2 Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2024-09-16 16:20:51 +02:00
Cris 2f0514092a Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-09-16 16:20:12 +02:00
SimonGschnell e1c395146b refactors the LvMenu into its own component and removes debugging prints 2024-09-16 14:55:26 +02:00
Harald Bamberger 363a014298 Merge branch 'feature-39161/PV21_Valorisierung' 2024-09-16 09:17:51 +02:00
SimonGschnell 4836ed8de0 adds LvMenu to the CalendarModel WIP 2024-09-13 13:44:53 +02:00
SimonGschnell b30156a65f catches errors better in Profil 2024-09-13 12:42:57 +02:00
Harald Bamberger d6966b24fe Merge branch 'master' into feature-39161/PV21_Valorisierung 2024-09-13 12:39:05 +02:00
SimonGschnell 88c38c9228 fixes ProfilUpdate bugs 2024-09-13 12:37:13 +02:00
SimonGschnell cf1cb44afa refactors old ProfilUpdate controller functions 2024-09-13 12:27:07 +02:00
SimonGschnell 2b9406b172 resolves zustellnungs value bug and removes debugging prints 2024-09-13 11:15:46 +02:00
Johann Hoffmann 27c312d7d3 filterPerson unrulyPerson api & person model 2024-09-12 15:42:21 +02:00
SimonGschnell 29fac520f3 component was setting the topic false when trying to delete a kontakt or an adresse 2024-09-12 12:04:42 +02:00
SimonGschnell 1208c6829c when an error happenes to editProfil Modal will also be closed then 2024-09-12 11:53:13 +02:00
SimonGschnell 1de8c00990 fixes an error where the payload i treated like an object but is an associative array in the controller 2024-09-12 11:45:54 +02:00
SimonGschnell e247621f95 fixes the profilBearbeiten phrase and does update the topic correctly when adding a new kontakt/addresse in the profil 2024-09-12 10:47:31 +02:00
SimonGschnell cfea7e10f2 adds the reservierungen overview action for the search result with a room object and removes debugging prints 2024-09-11 14:51:52 +02:00
SimonGschnell 6cf3896d49 fixes Calendar.js 2024-09-11 14:38:00 +02:00
Andreas Österreicher b2dbe65739 Berechtigungen korrigiert beim Setzen von Unruly People 2024-09-11 14:32:47 +02:00
SimonGschnell cf4105dcb3 Merge branch 'feature-25999/C4_copy' into feature-25999/C4 2024-09-11 14:07:25 +02:00
SimonGschnell b79a3bd5e9 Merge branch 'master' into feature-25999/C4 2024-09-11 14:06:49 +02:00
SimonGschnell 04aaefd5d8 refetches the Stundenplan events also for the Stundenplan and not only for the roomplan 2024-09-11 14:00:53 +02:00
SimonGschnell aef267186f removes typo and debugging print from Calendar.js 2024-09-11 13:56:39 +02:00
SimonGschnell d80761d952 Merge branch 'feature-39912/Room_planning_calendar' into feature-25999/C4_copy 2024-09-11 13:54:45 +02:00
SimonGschnell 8860d9a598 adds quick fix for the query builder error that comes up when fetching content 2024-09-11 11:26:04 +02:00
SimonGschnell f2a57f85a8 fixes the errors with the stundenplan/reservierungen data query 2024-09-11 10:19:46 +02:00
SimonGschnell ac35ba3e27 puts the logic that adds the object informtion to the json reponse in the controllers instead of the models 2024-09-11 09:50:04 +02:00
SimonGschnell 1de658ace6 fixes the query for the reservierungen in the stundenplan and in the raum informations 2024-09-11 09:32:28 +02:00
SimonGschnell 715b8075b8 reworks the query for the reservierungen stundenplan/room 2024-09-10 12:30:40 +02:00
Andreas Österreicher 555e74b8cd Projektexport ist jetzt auch möglich wenn aktuell keine Projekte
zugeordnet sind
2024-09-10 11:48:43 +02:00
Johann Hoffmann 79d23a4557 Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp
# Conflicts:
#	public/js/components/Form/Upload/Dms.js
2024-09-10 11:25:19 +02:00
Johann Hoffmann 6bc58c00b7 unruly controller benutzerrechte; studstatus unruly api fix; 2024-09-10 10:50:02 +02:00
Johann Hoffmann d9f5646ad1 Merge branch 'master' into feature-40896/kennzeichnung_unruly_person
# Conflicts:
#	application/models/crm/Prestudentstatus_model.php
#	public/js/api/fhcapifactory.js
#	system/dbupdate_3.4.php
#	system/phrasesupdate.php
2024-09-10 10:17:55 +02:00
Johann Hoffmann 888e3878bd studstatus unruly als grund 2024-09-09 17:16:05 +02:00
SimonGschnell 7b110aaf50 adds the needed phrase to the api/frontend/v1/Cms Controller 2024-09-09 14:16:37 +02:00
SimonGschnell 7a63301f08 puts profil settings ul outside of the sticky container 2024-09-09 13:49:38 +02:00
Harald Bamberger 5f50d9f0ec Merge branch 'feature-40311/Stundenplan_widget' into feature-25999/C4 2024-09-09 13:26:03 +02:00
SimonGschnell 26a0521379 fixes fhcapi 2024-09-09 13:12:11 +02:00
Harald Bamberger 996a49105b Merge branch 'feature-40309/Cis_News_widget' into feature-25999/C4 2024-09-09 13:03:47 +02:00
Harald Bamberger ff51d3964f Merge branch 'feature-40842/DashboardAmpeln' into feature-25999/C4 2024-09-09 12:56:55 +02:00
Harald Bamberger c2c30b86a1 Merge branch 'feature-40841/SearchBarChanges' into feature-25999/C4 2024-09-09 12:02:09 +02:00
Harald Bamberger 97b34d98fb Merge branch 'feature-41133/side_menu_sticky' into feature-25999/C4 2024-09-09 11:51:34 +02:00
Harald Bamberger 1f4628720a Merge branch 'feature-39911/Suche_um_raeume_erweitern' into feature-25999/C4 2024-09-09 11:50:27 +02:00
Harald Bamberger a8141e5dac Merge branch 'master' into feature-25999/C4 2024-09-09 11:45:10 +02:00
Johann Hoffmann 33122a0708 WIP performance testing & UI upgrades 2024-09-09 10:49:21 +02:00
Cris 92abfb8b58 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-09-09 10:26:07 +02:00
SimonGschnell ec8b3ccb6f adds the organisations bezeichnung through a subquery to the lehrveranstaltungs events 2024-09-06 13:11:22 +02:00
SimonGschnell 122673d291 gets rid of the stunden dependency and uses the beginn and ende property of the queried events 2024-09-06 11:20:20 +02:00
SimonGschnell 8376e8b92d bundles the room_events and the reservierungen api calls together with Promise.allSettled 2024-09-06 11:02:14 +02:00
Harald Bamberger 493405951d zusaetzlicher Filter bei Handyverwaltung nach beendeten DVs 2024-09-05 16:31:56 +02:00
SimonGschnell f9b69fe08c changes how the reservierungen are fetched from the database to have the same information as the room events 2024-09-05 14:57:57 +02:00
SimonGschnell e33162d20e changes the structure of the JSON data from the stundenplan 2024-09-04 14:59:56 +02:00
Cris 0e39cfd4e3 Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite 2024-09-04 11:01:01 +02:00
Cris f74ccb0513 Removed column Lehreinheitgruppen 2024-09-04 10:59:46 +02:00
Cris 6076d59c4b Removed Group by Organisationseinheit
Instead added Organisationseinheit as column for filtering reasons.
Column is invisible by default.
2024-09-04 10:59:25 +02:00
SimonGschnell 87f82b7f5d also adds the stundenplan information as object in the response of the endpoint 2024-09-03 12:07:13 +02:00
SimonGschnell f19c1b4eaf adds the lector and the gruppe as objects to the endpoint result instead of just strings 2024-09-02 14:47:40 +02:00
SimonGschnell 8c5ca521ac adopts the side menu for the desktop and mobile view 2024-09-02 10:42:01 +02:00
ma0048 7dc7816123 - fas neuer filter ueberfaellige buchungen 2024-08-30 08:21:35 +02:00
ma0068 de0fbdb72c Form, Table and Queries for new Tab Pruefung 2024-08-29 09:53:34 +02:00
Johann Hoffmann d03678e3dc WIP 2024-08-27 15:30:17 +02:00
ma0068 d254b9c10b Start Tab Pruefung, Abfrage Pruefungen 2024-08-23 11:58:08 +02:00
Cris f2be396e7a Adapted to use new fhcApi.getUri method 2024-08-21 13:53:49 +02:00
Cris 0c4d1afded Merge branch 'master' into feature-40953/LV-Template_Uebersichtsseite
# Conflicts:
#	system/phrasesupdate.php
2024-08-21 13:46:41 +02:00
Cris 7fb7263424 Added phrases for LV Templates Overview 2024-08-21 13:34:11 +02:00
Cris e5e4bb2ea1 Added Component LvTemplateUebersicht.js 2024-08-21 13:32:37 +02:00
Cris fc8c748bc4 Added View LvTemplateUebersicht.php 2024-08-21 13:32:14 +02:00
Cris eb308b78ef Added App LvTemplates.js 2024-08-21 13:28:56 +02:00
Cris 6168a6b806 Added Controller LvTemplateUebersicht.php 2024-08-21 13:26:20 +02:00
Cris d07f19d893 Added api Controller Studiensemester.php + methods getAll and getAktNext 2024-08-21 13:23:26 +02:00
Cris bff5d4ffbe Added api Controller Lehrveranstaltung.php + method getTemplateLvTree 2024-08-21 13:22:15 +02:00
Cris 4dc698a6be Added navigation menu item 'Lehrveranstaltungen' > 'LV Template Uebersicht' 2024-08-21 13:17:54 +02:00
Cris 3963358d95 Added getTemplateLvTree method to Lehrveranstaltung_model.php
This method gets all Templates and unions with all Lehrveranstaltungen of given Studiensemester and Oes, that are assigned to
a template. This data structure can be used for nested tabulator data tree.
2024-08-21 13:16:22 +02:00
KarpAlex 30396b3f0e Merge remote-tracking branch 'origin/feature-40728/Issues_logik_auslagern_in_eigene_library' into feature-39161/PV21_Valorisierung 2024-08-13 18:32:15 +02:00
Alexei Karpenko 8a9e040554 added Gehaltstyp model 2024-08-13 16:57:05 +02:00
SimonGschnell 3a466e8e0f puts nav-toggle and nav-menu-items in a sticky container 2024-08-13 15:27:51 +02:00
SimonGschnell 8bc8c67f8d better comments 2024-08-13 15:10:23 +02:00
SimonGschnell 36bd1795ed makes the cis4 side menu sticky 2024-08-13 15:04:44 +02:00
SimonGschnell cce58fdc31 removes debugging prints 2024-08-12 14:24:37 +02:00
Johann Hoffmann 8232224b21 LvMenu.php added codeigniter phrasen object to params; Using ci_phrases in Events.php for cis4 menu; 2024-08-12 14:20:42 +02:00
SimonGschnell 73dd89e5af adds phrasen library to LvMenu 2024-08-12 14:09:21 +02:00
KarpAlex 20ed9ffc41 UHSTAT Formular: added "unknown" options to every input 2024-08-11 21:59:13 +02:00
SimonGschnell d7abc41137 adds digitaleAnwesenheiten menu point 2024-08-09 13:32:00 +02:00
ma0048 6f0575304c - ent/sperren mit hochkomma bug fixed 2024-08-09 11:54:01 +02:00
SimonGschnell ba2c450bd2 uses the codeigniter querybuilder to construct the active ampeln query 2024-08-07 15:43:20 +02:00
SimonGschnell 3f86961bda adds parameter to ampeln deadline/overdue phrase 2024-08-07 15:21:22 +02:00
cgfhtw 05e0d219f4 Codequality 2024-08-07 14:32:44 +02:00
cgfhtw 8b590dc58a optimizing Ampel Widget 2024-08-07 14:23:35 +02:00
SimonGschnell a6bef31862 corrects filter styling problem 2024-08-07 12:00:24 +02:00
cgfhtw e7a29dc21a Identation 2024-08-07 11:56:00 +02:00
SimonGschnell ceb8eb9671 corrects the way how to active ampeln check whether an ampel was bestaetigt or not and adds the Ampel_Benutzer_Bestaetigt_model 2024-08-07 11:52:50 +02:00
SimonGschnell 47a4b63172 changes the zustellungs warning for the Profil Adressen/Kontakte 2024-08-07 09:53:37 +02:00
SimonGschnell 46a0706057 updates roomEvents on change:range / groups the results of a studenplan query 2024-08-06 14:29:24 +02:00
SimonGschnell f0db878623 changes the headers from the news template from h5 to h2 but adds the bootstrap h5 class 2024-08-05 11:48:57 +02:00
SimonGschnell e44c1bccb3 adds shorthands with getDataOrTerminateWithError and adds also form_validation 2024-08-05 09:17:04 +02:00
SimonGschnell b350c9da56 refactors the news controller 2024-08-02 14:46:22 +02:00
SimonGschnell c5f57a0689 adds the bestaetigt property of the ampel when fetching all the active ampeln 2024-08-02 12:52:21 +02:00
SimonGschnell 3bb87ef8d3 corrects the translation of the ampel queries 2024-08-02 11:44:58 +02:00
SimonGschnell 4811f223b9 corrects little typo 2024-08-02 11:01:32 +02:00
SimonGschnell e6ba291549 adds the translation of the beschreibung and the buttontext in the Ampel_model and not in the Ampel controller 2024-08-02 11:00:11 +02:00
SimonGschnell 9e1bd2b64d adds form_validation 2024-08-02 10:36:34 +02:00
chfhtw fb6bca0ffb Merge pull request #46 from FH-Complete/feature-41134/bookmark_dashboardWidget
Feature 41134/bookmark dashboard widget
2024-08-02 09:59:51 +02:00
SimonGschnell 2de307682c convert identation to tabs 2024-08-02 09:26:39 +02:00
SimonGschnell 1d4f03e3f1 adds single phrase 2024-08-02 08:24:57 +02:00
SimonGschnell d4e33eb1df refactor 2024-08-01 15:04:18 +02:00
SimonGschnell 4317d5ebe9 tab spaces/ catch alerts 2024-08-01 14:16:20 +02:00
SimonGschnell 6fcc8cf7e8 code review changes 2024-08-01 11:49:14 +02:00
SimonGschnell bd7e45547f adds Phrasen to the Stundenplan dashboard widget 2024-07-31 14:51:43 +02:00
Johann Hoffmann c9471c344d added unruly person boolean column to tbl_person; studStatus/leitung added a checkbox to mark persons as unruly unrelated to studstatus datastate; 2024-07-31 14:37:26 +02:00
SimonGschnell 3641047963 adds bookmark phrasen and makes the data shared between the dashboard widget and the configuration view of the widget 2024-07-31 13:51:34 +02:00
cgfhtw cf440ffb43 Shared Data in Widget Component and Widget Config Component 2024-07-31 13:13:16 +02:00
SimonGschnell c2be0a4790 adds content to Url.js 2024-07-31 12:41:03 +02:00
SimonGschnell 8c84a63757 corrects how both the ampel and the ui phrasen are loaded 2024-07-31 09:40:50 +02:00
SimonGschnell 39574c1b3a adds delete endpoint for the dashboard bookmark widget 2024-07-30 15:27:24 +02:00
SimonGschnell 198b866268 adds fhcalert when confirming an ampel 2024-07-30 12:37:05 +02:00
SimonGschnell 02cf36c17c adds Phrasen to the dashboard ampel-widget 2024-07-30 12:25:26 +02:00
SimonGschnell 284cf711fd adds the sql scripts to create dashboard.tbl_bookmark and dashboard.tbl_bookmark_sequence 2024-07-30 11:26:22 +02:00
SimonGschnell f4210e7671 fixes the Vue component layout for the ampeln dashboardwidget 2024-07-29 13:44:17 +02:00
SimonGschnell 2c45478877 fixes the fetched ampeln in the ampelWidget 2024-07-29 13:17:29 +02:00
Alexei Karpenko 88b5fbc4c9 PlausicheckResolverLib: resolving of issues without explicit resolver can also be used in extensions 2024-07-28 19:40:10 +02:00
Alexei Karpenko f1d1c3cbfd issueresolver: improved yet another comment 2024-07-28 19:34:58 +02:00
Alexei Karpenko 6680e9b882 issueresolver: improved another comment 2024-07-28 19:15:27 +02:00
Alexei Karpenko 31a21954d9 issueresolver: improved comment 2024-07-28 19:12:40 +02:00
SimonGschnell 65b71191a0 adds +1 to month in getMonth() function because the month index of a javascript date starts with 0, additional cleanup in Ampel.js Widgett 2024-07-26 15:41:21 +02:00
SimonGschnell fb30a8e009 translates the ampel queries in separate private function 2024-07-26 14:07:56 +02:00
SimonGschnell ca6e3a8463 adds endpoint to query all user ampeln that were assigned after the start_working_date with the appropriate beschreibungs translations 2024-07-25 15:16:01 +02:00
Alexei Karpenko abc74b09b3 Merge branch 'master' into feature-40728/Issues_logik_auslagern_in_eigene_library 2024-07-24 21:15:40 +02:00
SimonGschnell 0849e795a0 also adds the horizontal line under the heading 2024-07-24 14:59:02 +02:00
SimonGschnell 012cbe9a25 pulls the header out of the content div which makes the headings smaller in the content view with a specific css 2024-07-24 14:57:11 +02:00
SimonGschnell e9d45b6532 removes the old way a modal was shown in the news widget of the dashboard 2024-07-24 14:51:04 +02:00
SimonGschnell 94df440f88 adds a heading to the Content and the News View again 2024-07-24 14:49:58 +02:00
SimonGschnell 4e929f4cce Merge branch 'feature-25999/C4' into feature-40309/Cis_News_widget 2024-07-24 14:40:15 +02:00
SimonGschnell 563f5e5f9e merging C4 2024-07-24 14:37:16 +02:00
SimonGschnell 1e3146d33f dashboardAmpeln 2024-07-24 13:31:00 +02:00
SimonGschnell 4b0878b248 Merge branch 'master' into feature-39911/Suche_um_raeume_erweitern 2024-07-24 13:00:52 +02:00
SimonGschnell 1211d63ccf adds placeholders for the ampeln and adds new endpoints that fetch activeAmpeln and confirmedActiveAmpeln of the user 2024-07-23 13:59:04 +02:00
SimonGschnell 7e983292ea adds the endpoint that fetches all ampeln of a user that are not confirmed by the user yet and also removes some unnecessary comments from other enpoints 2024-07-23 11:26:52 +02:00
SimonGschnell 2083e95f8c adds vertical layout for the documents view when the viewport is less than lg 2024-07-23 09:14:38 +02:00
SimonGschnell f207419859 removes the import for userdata and profilUpdate from the old fhcapi which should be replaced by the new fhcapi 2024-07-23 08:58:52 +02:00
SimonGschnell e613ac3255 computes the childactions for the room in the search result independently 2024-07-22 14:33:19 +02:00
SimonGschnell 9170653260 adds a childaction for the rooms when searching for a room to see the eventoverview of the room 2024-07-22 14:07:00 +02:00
SimonGschnell f4bf3eec86 merging feature-39911/Suche_um_raeume_erweitern 2024-07-22 12:55:01 +02:00
SimonGschnell 82417a7f6f removes old api files and removes the use(fhcApi) because it is already imported in the Phrasen plugin 2024-07-22 11:36:12 +02:00
SimonGschnell a0871657ca adds insertFile to the new ProfilUpdate FhcAPIController and starts a transaction when deleting the foreign key from the profil update and deleting the old file 2024-07-22 11:24:47 +02:00
SimonGschnell 0cc6222175 adds deleteProfilRequest to the new ProfilUpdate FhcAPIController 2024-07-19 14:57:42 +02:00
SimonGschnell 8700abd0fa adds updateProfilRequest to the new ProfilUpdate FhcAPIController 2024-07-19 14:50:00 +02:00
SimonGschnell 12626511e9 adds insertProfilRequest to the new ProfilUpdate FhcAPIController 2024-07-19 14:00:40 +02:00
SimonGschnell a06f9b581f adds selectProfilRequest to the new ProfilUpdate FhcAPIController 2024-07-19 13:11:58 +02:00
SimonGschnell be66150631 adds acceptProfilRequest and denyProfilRequest to the new ProfilUpdate FhcAPIController 2024-07-19 11:38:15 +02:00
SimonGschnell 9eb61649eb adds getProfilRequestFiles to the new ProfilUpdate FhcAPIController 2024-07-19 09:06:49 +02:00
SimonGschnell ddd4d5bafe parses the links in the moodle addon dynamically, so that other addons can easily override the phrase used for the links 2024-07-18 14:03:15 +02:00
SimonGschnell 2711113a69 solves column title race condition 2024-07-18 11:43:08 +02:00
SimonGschnell 328a46f16d adds getTopic to the new ProfilUpdate FhcAPIController 2024-07-18 10:40:30 +02:00
SimonGschnell 885315c22b adds getStatus to the new ProfilUpdate FhcAPIController 2024-07-18 09:52:08 +02:00
SimonGschnell 29aa7f5056 adds isMitarbeiter to the new Profil FhcAPIController 2024-07-18 09:36:30 +02:00
SimonGschnell fdd3026212 adds getAllNationen to the new Profil FhcAPIController 2024-07-18 08:53:45 +02:00
SimonGschnell da8bb697df change url of Gesamtnote Menu Punkt 2024-07-16 15:42:42 +02:00
SimonGschnell 3417dcd41d centers the text, displays default message and makes # links not clickable and removes the link styling from them 2024-07-16 15:18:23 +02:00
Johann Hoffmann 630d2659b3 extension/anwesenheit_assistenz -> extension/anw_ent_admin; removed hardocoded status; check for overlapping excuse timespans; and a lot more ;) 2024-07-15 17:38:13 +02:00
SimonGschnell 14df81cbfb adds c4_linkList and additional styling to the LvUebersicht Menu 2024-07-12 16:14:20 +02:00
SimonGschnell 1614771150 loads content of the menu punkte in iframe inside a full-screen modal 2024-07-12 13:17:44 +02:00
ma0048 c94f185308 - faktor für lvs hinzugefuegt 2024-07-10 15:13:46 +02:00
SimonGschnell a83e07350e makes the pinboard link redirect to all news 2024-07-10 11:35:36 +02:00
SimonGschnell d364630d92 instead of modifying the original menu keys, it adds new keys for the cis4 version of the menu 2024-07-10 10:48:24 +02:00
SimonGschnell bc9f247323 replaces wrong quatations in the menu items if the link_onclick array key is defined 2024-07-10 09:10:35 +02:00
SimonGschnell 56080f6681 changes the LVUebersicht and the endpoint 2024-07-09 15:28:28 +02:00
SimonGschnell 8a44a9e1af passes the menu as a reference to the on Events instead of using a callback function 2024-07-09 10:37:43 +02:00
SimonGschnell 84029fc729 updates editAdressen in the Profil 2024-07-08 15:15:08 +02:00
Johann Hoffmann 66b151dce0 Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp
# Conflicts:
#	system/dbupdate_3.4.php
#	system/phrasesupdate.php
2024-07-08 14:42:01 +02:00
SimonGschnell 0347f8bf02 filters the menu to remove all elements that don't have the position property 2024-07-08 11:43:48 +02:00
SimonGschnell e98f59e984 adds all menu punkte from fh-core to the LvMenu endpoint function 2024-07-08 10:54:39 +02:00
SimonGschnell 578afaeb08 adds fh-core menu logic WIP 2024-07-05 15:21:14 +02:00
SimonGschnell 08555a77be makes contentModal bigger for the room content and uses the raum_info component to insert the tabulator in the content 2024-07-05 10:00:54 +02:00
SimonGschnell 79ffc1c077 creating lvMenu with Event hooks WIP 2024-07-04 15:37:50 +02:00
SimonGschnell 92afdf71cd changing fhcapi for the client side for the profil WIP 2024-07-03 15:53:01 +02:00
SimonGschnell 2a7735bca5 outsources internal queryies to the appropriate classes, to assign the values to the needed variables to fill the menu array of the menu_lv.inc.php 2024-07-03 11:56:18 +02:00
Johann Hoffmann affbe7821a email vorlagen sql insert; trim entschuldigungs begründung to max size; WIP routing; WIP fancy loader overlay; WIP Api Testing; lektor ui finetuning; 2024-07-02 16:51:42 +02:00
SimonGschnell 19753a9ef7 test api endpoint to include the lvinfo menu link 2024-07-02 14:50:54 +02:00
SimonGschnell 57d3d3af13 removes the shared storage for the searchbar and saves the data local in the searchbar again 2024-07-02 10:28:35 +02:00
SimonGschnell 3d2ea2821e fixes little typo, that fails to render the widget 2024-07-02 09:26:19 +02:00
SimonGschnell ff0f2320e1 changes the layout of the searchbar to be the same in the mobile view and in the desktop view 2024-07-01 14:43:43 +02:00
SimonGschnell f4f08c0710 stores the local information of the searchbar inside a collected storage in case more than one searchbar is used 2024-07-01 13:53:55 +02:00
SimonGschnell 3e3f005525 changes the layout/buttons of the searchbarsettings, adds responsive searchbar in the header for mobile views 2024-06-28 14:34:41 +02:00
SimonGschnell d0f457d8ed changes the data format from the studierendenEmail api call and displays the mailto on the modal 2024-06-28 11:06:44 +02:00
SimonGschnell c34144a4e8 creates sql query in the lehreinheit_model to query the studierenden Mail inside a lehrveranstaltung and creates the matching fhcapi methods / frontend/v1 api controllers 2024-06-27 15:09:09 +02:00
SimonGschnell ffc1241188 news widget 'alle News' redirects to the news URI 2024-06-27 11:53:22 +02:00
Alexei Karpenko 32e1e487a9 issues: enabled resolving without explicitely creating a resolver (by using producer method), old resolvers are still working. Created example for "self-resolving" issue: AbbrecherAktiv 2024-06-26 22:46:36 +02:00
SimonGschnell 5070353bf0 passes the active_addons constant to the LvUebersicht Modal 2024-06-26 16:37:54 +02:00
SimonGschnell a540ac3f7e adds a General view for the content_types that dont need any special extra computation 2024-06-26 15:58:50 +02:00
Johann Hoffmann 1305633511 removed 99% of console.logs; fixed entschuldigung update notiz only; added kontrolleDeleteMaxReach Constant from config; updateAnwesenheiten notiz fix; Entschuldigungs studiengang fetch fix; 2024-06-26 15:38:22 +02:00
SimonGschnell 93b7f6e57c fixes little typo 2024-06-26 15:20:19 +02:00
SimonGschnell 4640db5aff adds a view components for the news if the content that gets loaded has the template_kurzbz news 2024-06-26 14:17:44 +02:00
SimonGschnell 478adb740e changes the db query and adopts the layout of the Vue component to show the correct betreff and content of the news 2024-06-26 13:21:32 +02:00
SimonGschnell f546554f87 changes the layout of the news widget in the dashboard 2024-06-25 16:48:05 +02:00
SimonGschnell f4176ebcda adds the content of the news to the dashboard items and makes them scrollable through css classes 2024-06-25 14:18:11 +02:00
Johann Hoffmann dd044b9146 entschuldigungen reload fix; student anw group header toggle fix; scan error msg fix; delete modal with kontrolle selection; scan code route renamed to profile/scan from student/scan; fixed sum formatting; 2024-06-24 16:35:48 +02:00
SimonGschnell 27287bd07a creating the api endpoint that fetches the content of the news instead of text metdata 2024-06-24 16:05:51 +02:00
SimonGschnell 7267d526bb rendering content pages 2024-06-24 14:23:34 +02:00
SimonGschnell f8c431e0bc updating comment of the content function 2024-06-24 14:23:34 +02:00
SimonGschnell 629ea3716e changes how the content and the news are displayed and also modifies the modals for the roominformation which now get their data from props instead of passing them directly via refs 2024-06-24 14:23:34 +02:00
SimonGschnell 6230aa47ae now also displays the room information inside a modal and does not redirect to the content site 2024-06-24 14:23:34 +02:00
SimonGschnell b3dfcdc295 the calendar modal is correctly opened when the correct event is called 2024-06-24 14:23:34 +02:00
SimonGschnell bb9d4bda04 adds a general modal for the lehrveranstaltungs Uebersicht with all the links connected to the lehrveranstaltung 2024-06-24 14:23:34 +02:00
SimonGschnell d92ad0a6c6 links the ort_kurzbz from the Stundenplan in the Dashboard to the Ort Information Content 2024-06-24 14:23:34 +02:00
SimonGschnell 63f089dc27 changes the layout of the Stundenplan Events 2024-06-24 13:50:13 +02:00
SimonGschnell 77cd3bb02d removes the z-index from the calendar header so that it doesn't show over the menu when used in mobil view 2024-06-24 13:11:55 +02:00
SimonGschnell 008847e490 adds a sql query for the grouping algorithm 2024-06-24 13:08:44 +02:00
Johann Hoffmann 570798b5f7 landing page is now container for tabs or single component directly; WIP reworking lektor UI; 2024-06-24 10:51:23 +02:00
Alexei Karpenko 155d2f9651 Merge remote-tracking branch 'origin/feature-30679/Plausichecks_Behebung_parameter_zur_Identifizierung_eines_Issues_einbeziehen' into feature-40728/Issues_logik_auslagern_in_eigene_library 2024-06-21 15:03:23 +02:00
Alexei Karpenko 453f93aba6 outsourcing Issue logic: removed var dumps 2024-06-21 14:58:26 +02:00
Alexei Karpenko d2611ac0a5 put issue logik in own library (so GUIs should not have to reimplement it) 2024-06-21 14:34:31 +02:00
Johann Hoffmann b4b44d9a89 added entschuldigung & anw_user notizen; entschukldigung notizen working; WIP anw notizen; api fixes entschuldigung; LE for LVA fetch now disregarding stundenplan; Paths renamed to new controller names; 2024-06-18 14:15:35 +02:00
Johann Hoffmann 473815639b added entschuldigung max reach constant; rewrote SQL queries from string insert to param escaping; removed Stundenplan Lookup from LE for LVA fetch; load LE Stundenplan termine and serve as option when starting new kontrolle. 2024-06-17 17:39:56 +02:00
SimonGschnell a0472c6573 little changes 2024-06-14 14:44:29 +02:00
SimonGschnell f83cd3b87a checks whether the user wants to fetch content or the news 2024-06-14 11:18:29 +02:00
SimonGschnell dd7c8480f3 removes unwanted methods and properties from CalendarModal 2024-06-13 12:29:36 +02:00
SimonGschnell de4accab83 cleans up the Stundenplan grouping algorithm 2024-06-13 12:27:09 +02:00
SimonGschnell d1afd9f09d groups the uids of the reservierungen in the raum uebersicht and renders different template if the calender entry is a reservierung or a stundenplan event 2024-06-12 14:42:30 +02:00
SimonGschnell 9c51f25c9e modifies how the slot template from the Calendar Page is passed to the CalendarApp and prints the reservierungen differently (but the reservierungen are not grouped yet) 2024-06-11 15:03:09 +02:00
Johann Hoffmann e7e5d76531 fhcapi use factory merge 2024-06-10 17:23:37 +02:00
Johann Hoffmann 52a55a018c merge fix 2024-06-10 15:13:30 +02:00
Johann Hoffmann aa1d70f8f0 fix 2024-06-10 13:35:06 +02:00
Johann Hoffmann 9350e9230f API refactor 2024-06-10 13:30:44 +02:00
SimonGschnell 022ad26dd2 reservierungen query also joins the studiengangs and mitarbeiter information 2024-06-10 13:01:55 +02:00
SimonGschnell 392d8f38d2 adding the reservierungen to the room plannung 2024-06-10 11:39:16 +02:00
SimonGschnell 8442690bc7 splits the multiple stg into different rows if there are more than one stg in one lv 2024-06-10 10:56:12 +02:00
SimonGschnell 70b0b3fae7 MVP algorithm for stundenplan gruppierung (testing) 2024-06-07 15:06:28 +02:00
Johann Hoffmann 068aa03b4f Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp 2024-06-06 11:02:56 +02:00
SimonGschnell 25d284389a gruppieren algorithm erweitern 2024-06-06 09:25:46 +02:00
SimonGschnell 1a5d270936 calendarDate preparation 2024-06-04 15:00:41 +02:00
SimonGschnell 3df1aaf371 uses the new fhcApi factory to make the roomInformation get request from the frontent/v1/stundenplan api and uses the CalendarDate class to get the first day of the week and the last day of the week to make the request for the room information over the whole week 2024-06-04 08:24:58 +02:00
Harald Bamberger 7491b9c1b0 try to fix mobile dashboard view 2024-06-03 11:35:11 +02:00
Harald Bamberger 204de30459 make news modal more responsive 2024-06-03 10:46:26 +02:00
Harald Bamberger 92319b9b29 quick fix for overlapping dashboard elements on mobile phones 2024-06-03 10:27:03 +02:00
SimonGschnell 39321dcde3 adds the roomInformation Calendar to the menu and uses different template for the calendar page slot 2024-05-31 12:28:06 +02:00
SimonGschnell b9bd8e1d4d Merge branch 'feature-25999/C4' into feature-39912/Room_planning_calendar 2024-05-31 08:53:40 +02:00
SimonGschnell 5021c47c9f calendar style changes 2024-05-27 12:20:58 +02:00
SimonGschnell 87681351b9 Merge branch 'feature-25999/C4' into feature-39912/Room_planning_calendar 2024-05-27 10:55:44 +02:00
SimonGschnell 16f90604b6 stundenplan modal for LVs and making calendar header sticky 2024-05-24 11:17:06 +02:00
SimonGschnell 234ec03db9 adds the phrase noGrade 2024-05-24 09:37:07 +02:00
Johann Hoffmann 0536ff0044 load person_id & uid for students to navigate them with admin view; WIP studentDropdown selection; WIP changing studentComponent to work with different permissions; 2024-05-23 16:49:53 +02:00
SimonGschnell 729509a45d WIP 2024-05-23 15:40:23 +02:00
SimonGschnell 12b2f3ab07 adding more information to the cis40 stundenplan 2024-05-23 15:39:31 +02:00
Alexei Karpenko 854d836e30 Abschlussprüfungsprotokolle: added link in FAS to read-only form 2024-05-23 13:56:18 +02:00
SimonGschnell 25deb0a440 takes the value of the node not just the node 2024-05-23 13:01:18 +02:00
SimonGschnell cef41f3710 fixes html, one closing div to much 2024-05-23 12:44:12 +02:00
Johann Hoffmann 59a1e84fb2 Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp
# Conflicts:
#	public/js/components/filter/Filter.js
#	public/js/plugin/FhcApi.js
#	system/dbupdate_3.4.php
2024-05-22 15:42:19 +02:00
SimonGschnell 186e9e6f08 WIP room planning in calendar 2024-05-21 15:56:18 +02:00
SimonGschnell c566d07847 fixes little xml layout issue 2024-05-21 13:34:58 +02:00
SimonGschnell 48bb2ef7e1 adds the insert query for the new raum template and the update statement to update the template for every room content 2024-05-21 11:05:22 +02:00
SimonGschnell 393475e62c adds the content update script for the room content to the checksystem 2024-05-21 10:49:27 +02:00
SimonGschnell d07c568d5e adds dbupdate queryies for the new raum template 2024-05-21 10:37:53 +02:00
Johann Hoffmann 7530a74ff3 demo stand gf; 2024-05-16 16:39:54 +02:00
SimonGschnell c7e01bd3f2 creates the sql query with the needed room information to be displayed in the search 2024-05-15 14:37:18 +02:00
SimonGschnell 56e6efe416 WIP sql query for the raum search 2024-05-14 15:57:48 +02:00
SimonGschnell 841e3b0390 raum query 2024-05-14 14:21:52 +02:00
Harald Bamberger b3c6127cfe Merge branch 'feature-25999/C4_TEST' into feature-25999/C4 2024-05-14 14:01:24 +02:00
Johann Hoffmann 3b762c8065 getStudentsForLvaInSemester data query; getLektorIsTeachingLE veryfication query; getLektorenForLvaInSemester selection query; moved setup from app to landing page, landing page thus unskippable; now checking qr code age in check in; charts smaller size now; more phrasen; lektor tabulator height fix; ma uid selection of lektors for admin and assistenz; tested and implemented QRDelete Cronjob; 2024-05-13 16:01:26 +02:00
ma0048 a0284c313a - funktion fuer das alle markierten akzeptieren getrennt
- fehlende phrasen hinzugefuegt
2024-05-13 09:16:29 +02:00
SimonGschnell fd8e49c11f hotfix in Modal.js 2024-05-08 14:35:41 +02:00
SimonGschnell 6fa5ff81d6 Merge branch 'feature-25999/task-39464' into feature-25999/C4_TEST 2024-05-08 12:01:53 +02:00
SimonGschnell 0942480428 adds the missing model for the function 2024-05-08 11:58:35 +02:00
SimonGschnell 2fd2746a74 Merge branch 'feature-25999/task-39464' of github.com:FH-Complete/FHC-Core into feature-25999/task-39464 2024-05-08 11:56:50 +02:00
SimonGschnell 8e2129902c Merge branch 'feature-25999/task-39464' into feature-25999/C4_TEST 2024-05-08 11:29:39 +02:00
SimonGschnell d0509abb8b also adds the new controller functions to the CisVue/Cms and CisHmvc/Cms 2024-05-08 11:28:16 +02:00
SimonGschnell c2a782e164 updates news fetching and DB_Model pagination methods 2024-05-08 11:28:16 +02:00
SimonGschnell 5ac0b249ec makes component Pagination page_size prop a required prop 2024-05-08 11:28:16 +02:00
SimonGschnell 5142f5656b passes the page_size down from the parent component to the child component 2024-05-08 11:28:16 +02:00
SimonGschnell 7bd70a6436 makes it possible to send the page_size from the frontend to the backend to adopt how many rows to query 2024-05-08 11:28:16 +02:00
SimonGschnell c017014171 changes how the pagination is done in the DB_Model 2024-05-08 11:28:16 +02:00
SimonGschnell 36c8862b99 implementing frontend pagination for components 2024-05-08 11:28:16 +02:00
SimonGschnell 29f7e34e10 adds pagination logic to C4 news 2024-05-08 11:28:16 +02:00
SimonGschnell 730db74743 Merge branch 'feature-25999/C4_ma0594_profilePage' into feature-25999/C4_TEST 2024-05-08 11:14:41 +02:00
SimonGschnell d1207ced02 Merge branch 'master' into feature-25999/C4_TEST 2024-05-08 11:06:34 +02:00
SimonGschnell fb6bb96fbd making Filter-core-cmp emit the tableBuilt event 2024-05-08 10:58:38 +02:00
SimonGschnell 9db09a040a Merge branch 'master' into feature-25999/C4_ma0594_profilePage 2024-05-08 09:58:18 +02:00
SimonGschnell a563f053ef adds the width and the height properties to the dashboard item, they were missing and caused a bug where the news widget was not displaying correctly 2024-05-06 14:19:04 +02:00
Johann Hoffmann 3846f38a6f added PK to tbl_anwesenheit_check; chenged anwesenheiten sum function to account for timespans of the checks; added extension/anwesenheit_admin berechtigung; fotos are now being sent as links to bild.php; studentByLva table now with von & bis times of the check; now updating attendance check times when starting further checks on the same date; checking if time the code is being sent is in the timespan of the kontrolle; added method to delete QR codes older than certain ms to be called from QRDelete Cronjob; 2024-05-06 11:21:01 +02:00
SimonGschnell efcebb567f responsive adjustments 2024-05-03 10:46:20 +02:00
SimonGschnell e6ad3b3168 adjust responsiveness of createAnrechnung.php 2024-05-03 10:35:46 +02:00
SimonGschnell f9058b954e adjusting the responsive layout for approveAnrechnungDetail view 2024-05-03 10:31:53 +02:00
SimonGschnell 4aa8807830 adds responsiveness for the view approveAnrechnungUebersicht 2024-05-03 09:48:18 +02:00
SimonGschnell 9975f767b8 adds responsiveness to reviewAnrechnungDetail.php 2024-05-02 12:15:57 +02:00
SimonGschnell 0b58d4fd6f also adds the programmatically unselectable logic to the reject button 2024-05-02 11:43:19 +02:00
SimonGschnell bcafb6cea6 removes unnecessary function call from reviewAnrechnungUebersicht.js 2024-05-02 11:30:38 +02:00
SimonGschnell 6ea802717b adds pointer-events none to all rows with the class .tabulator-unselectable except for the links inside those rows, because it was not possible to programmatically retrigger the selectableCheck 2024-05-02 11:14:12 +02:00
Johann Hoffmann 2c08a482e3 finished phrasen in backend; setup component is no a modal in landing page and only for lektors with multiple LE assigned in an lva; assistenz skips landing page; tabulator formatting fixes; getAllAnwesenheitenByLektor now fetches students and their anwesenheiten entries seperately which is significantly faster; 2024-05-02 09:29:50 +02:00
SimonGschnell 10bfb6c9e8 also fixes the isSelectable bug when rejecting a anrechnung in the approveAnrechnungenUebersicht view 2024-04-30 15:03:30 +02:00
SimonGschnell 86d3042cc6 makes the rows that were recently selected unselectable and adds the correct styling in the approveAnrechnungUebersicht view 2024-04-30 14:18:22 +02:00
SimonGschnell ac0103751d adds a border to the tableWidget and also adds a function that finds the tableunqiueid using the tableInstance 2024-04-30 09:48:08 +02:00
SimonGschnell 20a2e369c5 adds new button to show all new and changed lehrauftraege in the orderLehrauftrag view, so that the user can set the initial filter himself 2024-04-29 15:53:56 +02:00
SimonGschnell 555db0d5af fixes the selection of the tableUniqueID 2024-04-29 11:45:08 +02:00
SimonGschnell b0d31361c1 updates fontawesome version 2024-04-29 11:38:03 +02:00
SimonGschnell 8cf63f3b76 replaces the icons images with actual icons from the fontawesome6 library 2024-04-29 11:34:18 +02:00
SimonGschnell ffe4fcb0b3 removes the cis styles from the admin views 2024-04-26 14:43:56 +02:00
SimonGschnell dec6b160a6 fixes the acceptLehrauftrag view with bootstrap5 and tabulator5 2024-04-26 14:07:24 +02:00
SimonGschnell e4f1da751d migrating the acceptLehrauftrags view to bootstrap 5 2024-04-25 15:19:24 +02:00
SimonGschnell 88fd26d192 Merge branch 'master' into feature-36185/requestAnrechnung_bootstrap3_zu_bootstrap5 2024-04-25 14:35:50 +02:00
SimonGschnell 580b6239c2 remove the body tag from all views that use the FHC-Header view 2024-04-25 14:35:06 +02:00
SimonGschnell b7ffe00c69 sets the height of the adminZeitverfuegbarkeit to 50% of the screen ehight 2024-04-25 14:16:28 +02:00
SimonGschnell d01b05fd73 edit anrechnungszeitfenster does actually edit and not insert a new anrechnungszeitfenster 2024-04-25 13:30:32 +02:00
SimonGschnell deb0197452 fixes the adminAnrechnungen page 2024-04-25 13:13:24 +02:00
SimonGschnell fed30daad0 bug fix, only appending the event to the accept and deny action button if they were actually created 2024-04-25 09:41:32 +02:00
SimonGschnell a2e943ac40 adjusts the actions of the ProfilUpdateView table with accept and deny buttons 2024-04-25 09:29:47 +02:00
Johann Hoffmann f5d534a409 added require branch update file in dbupdate_3.4.php; added phrasen everywhere in frontend, WIP translating backend messages; 2024-04-24 15:52:53 +02:00
SimonGschnell cea06994de fixes the bug with the columnDefault tooltips that was inside the TableWidget.js file 2024-04-24 14:59:46 +02:00
ma0048 b1e85fe92b - international skills auf vuejs
- note uebernehmen hinzugefuegt
2024-04-24 14:18:55 +02:00
SimonGschnell 5a62dbc740 refactors the adminAnrechnung page because it is used in an bootstrap3 environment 2024-04-24 11:35:02 +02:00
SimonGschnell 7dfe2f1932 tabulator5 function changes 2024-04-24 10:00:12 +02:00
Johann Hoffmann 633b9eeafe loading STG permissions for assistenz into frontend and only fetching entschuldigungsdata for those; new data fetch api methods for lektor to visualize graphs: getAllByLva & getAllByStudiengang. old one renamed to getAllByLvaAssigned; automatic email to responsible adress on entschuldigung upload of a student; focused on pie charts for reusable landing page design; fixed entschuldigungen date filter validation; WIP extension specific phrases; 2024-04-23 17:00:32 +02:00
SimonGschnell 96b79c8740 corrects reviewAnrechnungDetail style typo, and adds the height function to the adminAnrechnung table again 2024-04-23 13:43:00 +02:00
SimonGschnell bebec98285 adds a little space with a br between the tablewidget header and the table itself 2024-04-23 13:16:04 +02:00
SimonGschnell 8d68faf922 replaces the pull-right class with a conditional if bootstrapVersion was set to 5 2024-04-23 13:06:02 +02:00
SimonGschnell 9ae36b54e1 remove the 50% height from the table and add fitColumns to the table so that the columns take the whole available space 2024-04-23 12:55:44 +02:00
SimonGschnell 11c9622186 replaces the anrechnungen.css with styles in the zeitverfuegbarkeit view 2024-04-23 12:50:29 +02:00
SimonGschnell 3a1ac15740 adds the button width and margin classes from the Tabulator.css (used in Tabulator4) to the anrechnungen.css file 2024-04-23 12:47:17 +02:00
SimonGschnell 51ee16926c adds a tabulator redraw when adding the details column to the tableWidget 2024-04-23 09:49:41 +02:00
SimonGschnell e1fac8e871 adds the bootstrapVersion flag to all the TableWidgetData files 2024-04-22 17:11:02 +02:00
SimonGschnell 977c2d4432 Merge branch 'master' into feature-36185/requestAnrechnung_bootstrap3_zu_bootstrap5 2024-04-22 15:18:19 +02:00
SimonGschnell 258c5f7777 Merge branch 'master' into feature-36185/requestAnrechnung_bootstrap3_zu_bootstrap5 2024-04-22 14:56:07 +02:00
SimonGschnell e2e7966f83 adds accept and deny actions in the actions column of the ProfilUpdateView component 2024-04-22 14:55:37 +02:00
SimonGschnell 349865b8fb fixes the phrasen for the column titles of the ProfilUpdateView 2024-04-22 13:52:38 +02:00
SimonGschnell 27428b15bb changes the escaping string for the xslt_xhtml_c4 2024-04-22 11:49:19 +02:00
Harald Bamberger 93ae5577f8 try with here documents 2024-04-22 11:25:24 +02:00
SimonGschnell 1447a930d3 adds more phrasen to the profil and the profilUpdate views, headers of tables phrasen 2024-04-19 14:24:32 +02:00
SimonGschnell 4bb9c61168 also fixes the phrasen for the student/Mitarbeiter View Ansicht 2024-04-18 15:06:38 +02:00
SimonGschnell bc0d581402 fixes phrasen in the studentProfil 2024-04-18 15:00:28 +02:00
SimonGschnell 4e5379c5d9 adds an edit button over every section in the profil page to edit that section 2024-04-18 14:53:51 +02:00
SimonGschnell cc0ea44de3 also adds the new controller functions to the CisVue/Cms and CisHmvc/Cms 2024-04-18 11:56:55 +02:00
SimonGschnell 3993d614d4 updates news fetching and DB_Model pagination methods 2024-04-18 11:52:58 +02:00
SimonGschnell 71f63095c2 makes component Pagination page_size prop a required prop 2024-04-17 15:15:51 +02:00
SimonGschnell 92f2c6e0a2 passes the page_size down from the parent component to the child component 2024-04-17 15:12:55 +02:00
SimonGschnell 284ae0637e makes it possible to send the page_size from the frontend to the backend to adopt how many rows to query 2024-04-17 14:54:22 +02:00
SimonGschnell 6c642f1242 changes how the pagination is done in the DB_Model 2024-04-17 14:23:09 +02:00
SimonGschnell d77499b73b implementing frontend pagination for components 2024-04-15 13:35:33 +02:00
Johann Hoffmann 563e7bebc0 setupComponent currently uses globalProperties as model for le selection; lektorComponent uses globalProperties for le_id; le_selection now has sophisticated info String detailing every group associated with le for lektor; WIP assistenz filter setup; WIP checking in router guard for missing le_id when they have not loaded yet; 2024-04-12 15:01:37 +02:00
SimonGschnell ad956bef8e adds pagination logic to C4 news 2024-04-12 14:38:01 +02:00
SimonGschnell ea9bd93e73 phrasen fix and bug where profilUpdates were only sorted when accepting the request and not denying 2024-04-12 09:39:28 +02:00
SimonGschnell 86504fd663 doesn't show the footer if the view inside the EditProfil Modal is set to Status 2024-04-11 11:39:29 +02:00
SimonGschnell 2b68831415 adds more filter options for the ProfilUpdateView 2024-04-11 11:20:32 +02:00
SimonGschnell 4fc4cd762d adopts logic to fetched profilUpdate status and topic from the database 2024-04-11 09:15:19 +02:00
SimonGschnell 21c2bafed6 adapt the logic of the profilUpdate feature to use constant status and topics from the database 2024-04-10 15:08:21 +02:00
SimonGschnell 5b2365a1e2 stores the status of profilUpdate with their language in the database and adapts the logic to it 2024-04-09 15:02:17 +02:00
SimonGschnell 78031bf1ad fixes buggs that were produced with the introduction of new phrasen 2024-04-09 09:08:47 +02:00
SimonGschnell 2df91bce5c adds phrasen to the ProfilUpdateView.js file 2024-04-08 15:49:28 +02:00
SimonGschnell 960341e25d adds more profil phrasen error messages 2024-04-08 15:08:20 +02:00
SimonGschnell 1b04d70839 adds phrasen for profil in php controller and adds error message phrasen 2024-04-08 15:03:08 +02:00
Johann Hoffmann cf0c7a2f8c put le_ids aswell as viewdata for le selection in globalProperties to share between components; using FhcApi Plugin for API calls; le selection in setup now with info (gruppe_kurzbz, lehrform_kurzbz, semester, verband, gruppe); fixed setting foto in viewData after refreshing sum eg after kontrolle; 2024-04-08 12:25:25 +02:00
SimonGschnell b77e56161d fixing some not working phrasen 2024-04-08 09:58:53 +02:00
SimonGschnell 0cd86e3e54 cannot use this keyword when assigning default values to props in componenets 2024-04-05 14:57:00 +02:00
SimonGschnell 150b4ec09d phrasen for acceptDenyUpdate.js and ProfilUpdateView.js 2024-04-05 10:33:23 +02:00
SimonGschnell c1cb2904e6 adding phrases for Profil and ProfilUpdate 2024-04-04 15:02:47 +02:00
SimonGschnell 6af2a01166 tabulator5 migration changes 2024-04-04 09:55:41 +02:00
SimonGschnell 2e5f53f59a changes tabulator cell alignment in tabulator5 2024-04-04 09:36:46 +02:00
SimonGschnell dd2f982e95 adding the uniqueID jquery identifier to acceptLehrvertrag.js 2024-04-03 14:33:35 +02:00
SimonGschnell a2d71d3a8d adjusts how the AcceptDenyModal is used and included in the ProfilUpdateView 2024-04-02 16:38:29 +02:00
SimonGschnell 51a65495aa corrects the insertion of the dms_kategorie profil_aenderung in the checksystem 2024-04-02 15:31:56 +02:00
SimonGschnell e33d863732 upgrades pruefungsprotokollUebersicht to tabulator 5 2024-04-02 13:03:52 +02:00
SimonGschnell 4e3ab802b6 removes unnecessary debugging log 2024-04-02 12:49:33 +02:00
SimonGschnell d8fb36543f migrates adminZeitverfuegbarkeit to tabulator5 2024-04-02 12:46:51 +02:00
SimonGschnell e29dfd99f3 migrate approveLehrauftrag/acceptLehrauftrag/orderLehrauftrag to tabulator 5 2024-04-02 12:34:51 +02:00
Johann Hoffmann 927ed934c0 new Controller & routes for Landing Page; Fixed querying students for n LE; Pictures in LektorOverview & Detailview; WIP SetupComponent to select missing parameters in case; added highcharts library as pure JS; WIP designing Charts based on role & parameter input or setup; Integration in old cis via Mein Cis/Meine LV aswell as Studium/Studiengänge currently as "Anwesenheiten NEU"; WIP Landing Page Design; WIP LE Selection from Stundenplan Entries with appropriate Classification; defined settings for QR Regeneration and showing time left on a progress bar; entry query parameters are being handled inside globalProperties, controller parameters are still inside permissions array; 2024-03-22 14:12:17 +01:00
SimonGschnell 7dec1178e4 changes the parameter list of the tooltip function in tabulator 5 for approveAnrechnungUebersicht and reviewAnrechungUebersicht 2024-03-21 14:51:04 +01:00
SimonGschnell 72b19987bd removes unnecessary debugging prints 2024-03-21 14:46:03 +01:00
SimonGschnell 1a76231df0 migrated orderLehrauftrag to tabulator5 2024-03-21 14:37:28 +01:00
SimonGschnell 57e5626fe4 reset the navbar to use bootstrap3 2024-03-21 13:52:56 +01:00
SimonGschnell a8c60c105d migrating approveLehrauftrag to tabulator5 2024-03-21 13:42:43 +01:00
SimonGschnell 47dfb66b8d replacing string concatenation with string literals for tableWidget Header and Footer 2024-03-21 09:27:44 +01:00
SimonGschnell 081a2d69f5 set version 3 as the default version of bootstrap for the tableWidget 2024-03-21 08:49:28 +01:00
SimonGschnell 59f25bd3a2 adding the bootstrapVersion flag to the /widget/table view to dynamically render css classes + little fixes 2024-03-20 13:26:23 +01:00
SimonGschnell 78a16982f8 updates the tableHelpsite to use bootstrap5 classes if the bootstrapVersion flag is set to 5 2024-03-20 13:25:32 +01:00
SimonGschnell de15d43bb7 adds bootstrapVersion flag to the tableWidget options to render bootstrap3 classes or bootstrap5 classes 2024-03-19 15:29:28 +01:00
SimonGschnell acac5dfc65 trying to independenly restyle the navigationWidget 2024-03-18 15:17:14 +01:00
SimonGschnell 92cb4dedef migrates adminAnrechnungData and adminAnrechnung.js to use tabulator5 2024-03-18 11:49:54 +01:00
SimonGschnell 3cdc051861 updates adminAnrechnung view to bootstrap5 2024-03-18 11:42:34 +01:00
SimonGschnell 961526925c updates reviewAnrechnungDetail.js to change the correct bootstrap5 classes in the javascript 2024-03-18 11:07:12 +01:00
SimonGschnell 571bf8ebad update reviewAnrechnungenDetail to Bootatrap5 and little styling fixes for other Detail views 2024-03-18 11:02:26 +01:00
Johann Hoffmann 44260ddb4d basic link to Anwesenheit Extension from cis_menu_lv.inc.php checking on CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN in global.config-default.inc.php 2024-03-18 10:58:14 +01:00
Johann Hoffmann b39b8559d9 Merge branch 'master' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp 2024-03-18 10:55:05 +01:00
SimonGschnell 72bf2525b7 updating reviewAnrechnungUebersicht to bootstrap5 and tabulator5 2024-03-18 10:14:05 +01:00
SimonGschnell 83ccc93305 little adjustments and migrations 2024-03-15 15:02:17 +01:00
SimonGschnell 5ecac3cb99 migrates createAnrechnung to bootstrap 5 and tabulator 5 2024-03-15 15:01:55 +01:00
SimonGschnell 183cb1ac17 little adjustments on requestAnrechnung 2024-03-15 12:52:21 +01:00
SimonGschnell cc461aab8b updates js file of approveAnrechnungDetail to be bootstrap5 conform 2024-03-15 12:52:00 +01:00
SimonGschnell f9c894307d buttons with attribute disabled and title fix 2024-03-15 11:58:31 +01:00
SimonGschnell 9360c8a470 migrates approveAnrechnungDetail to bootstrap5 and adds little adjustments to requestAnrechungImportant 2024-03-15 11:57:11 +01:00
SimonGschnell 868d10ffd6 adds bg-secondary-subtle to the color palette and fixes buttons that are disabled and have a title attribute 2024-03-15 11:56:16 +01:00
SimonGschnell 465ab736ee changed AnrechnungenInfo panel to bootstrap5 accordion 2024-03-15 11:18:31 +01:00
SimonGschnell 8556632f90 updating approveAnrechnungDetail to boostrap5 2024-03-14 11:36:42 +01:00
SimonGschnell 8a835cb7f8 reset searchbar.js fixing searchbar style 2024-03-13 14:44:56 +01:00
SimonGschnell 3c2190b280 fixes zustellAdressenCount for EditAdresse and formats code files 2024-03-13 14:01:29 +01:00
SimonGschnell c0e6552c08 fixes zustellKontakteCount in EditKontakt 2024-03-13 13:44:08 +01:00
SimonGschnell e7480eb9ff hotfix, editProfil modal in fetchProfilUpdates component 2024-03-13 12:23:45 +01:00
SimonGschnell 1816f3f5f6 fully upgrades the approveAnrechnungUebersicht to tabulator5 2024-03-13 10:22:10 +01:00
SimonGschnell 6722fde9c9 adapts approveAnrechnungUebersicht for the new tabultor5 functions 2024-03-12 15:33:24 +01:00
SimonGschnell 70418b8ff6 updates TableWidget.js functions that are no longer valid in tabulator5 2024-03-12 14:30:40 +01:00
SimonGschnell 1dc4f5b56a upgrading tableWidget to tabulator 5 with custom jquery_wrapper 2024-03-12 12:28:59 +01:00
Harald Bamberger 691bbaaf82 workaround for tabulator jquery_wrapper 2024-03-12 09:59:21 +01:00
SimonGschnell aa7982fea9 adds jquery adjustments 2024-03-08 12:34:26 +01:00
SimonGschnell 1b65f6f4e6 trying to add callbacks after the tabulator called the tableBuilt event with jquery 2024-03-07 14:48:11 +01:00
SimonGschnell 7eda02f366 adds include variable tabulator5JQuery to FHC-Common.php 2024-03-07 11:46:05 +01:00
SimonGschnell b1411549f3 better folder structure for Cis Profil 2024-03-07 11:14:58 +01:00
SimonGschnell 96e0bfa72c changes how the EditProfil Modal passes props to its children 2024-03-07 11:08:43 +01:00
SimonGschnell 464799d22b tabulator upgrade 2024-03-06 14:46:21 +01:00
SimonGschnell e41e24be04 adding the option to add css classes to the HTMLWidget 2024-03-05 15:38:51 +01:00
SimonGschnell 144a872c98 adds cutsom cis css style which lowers the overall font size 2024-03-05 09:36:16 +01:00
SimonGschnell b7a1236acc anrechnung.css update 2024-03-04 15:06:08 +01:00
SimonGschnell dd309e972b js alert messages update, need to update the phrasesupdate.php 2024-03-04 15:03:49 +01:00
SimonGschnell 84ba0dbb64 bootstrap 5 upgrade (tooltips,cards,margins,..) 2024-03-04 13:50:06 +01:00
SimonGschnell ccf01100bb adds new classes because alert-info/warning/... are not consistent in the new bootstrap versions 2024-03-01 15:36:10 +01:00
Johann Hoffmann 8ccc621a91 Finalized db schema changes for Anwesenheitskontrolle and Checkin; Multiple Lektor scenario not being managed yet; reworked frontend requests towards API Controller to not confuse vue router; WIP UX; 2024-02-27 11:42:42 +01:00
SimonGschnell 21f7099878 refactor 2024-02-23 14:32:06 +01:00
SimonGschnell f09692edd1 adds primevue autocomplete field for EditAdresse 2024-02-22 15:04:24 +01:00
SimonGschnell ee7a819094 Merge branch 'master' into feature-25999/C4_ma0594dev 2024-02-22 12:06:16 +01:00
SimonGschnell 989f1ecf02 finishes the documentation in Profil.php controller and refactors getView 2024-02-22 11:50:08 +01:00
Johann Hoffmann 63a06dfef2 WIP api controller backend; WIP adapting queries to new db schema; 2024-02-22 10:30:18 +01:00
SimonGschnell 0b84e1b608 finishes documentation on Profil.php controller 2024-02-22 09:00:53 +01:00
SimonGschnell 4edd242f09 adds documentation to the Profil.php controller not finished 2024-02-21 15:44:41 +01:00
SimonGschnell 2a393f0087 adds the fields gemeinde and nation to the EditAdresse Component and adds autocomplete for the gemeinde if the nation is A 2024-02-21 12:31:41 +01:00
SimonGschnell 1bed062a01 querying the right data for the EditAdresse Nation and Gemeinde Fields 2024-02-20 15:57:17 +01:00
SimonGschnell 6f7bca6eab adds loading modal to ProfilUpdateView 2024-02-20 14:32:28 +01:00
SimonGschnell 47abce4aad handles the loading modal in the root Profil app when inserting a new profil update that may takes some time because it has to send out emails 2024-02-20 10:50:35 +01:00
SimonGschnell 1afb9130c0 adds a loading animation when waiting for the emails to be sent out when inserting a new profil update request 2024-02-19 15:12:16 +01:00
SimonGschnell 2e9cc2b291 /ProfilUpdate/id/ was added to the ProfilUpdate controller to automatically open the necessary profil_update on startup of the page, this functionality is used when sending emails with the link to the profil_update 2024-02-19 14:36:45 +01:00
SimonGschnell 2d5aea2bb8 translates the english status into a german version for the email vorlage 2024-02-19 09:14:45 +01:00
SimonGschnell 318087c572 sends email to the user if a profil update was accepted or rejected 2024-02-16 15:37:20 +01:00
SimonGschnell 501224b9b7 sends emails on insertion of an profil update to the studiengänge in case of students and to hr in case of a mitarbeiter 2024-02-16 14:33:49 +01:00
SimonGschnell 34b995ed6d adds dms_kategorie for profil updates as an insert into statement in the dbupdate file 2024-02-15 16:20:54 +01:00
SimonGschnell 04f6ee6156 Merge branch 'master' into feature-25999/C4_ma0594dev 2024-02-15 15:16:07 +01:00
SimonGschnell 6eeeb8b4b7 send email 2024-02-15 15:09:41 +01:00
SimonGschnell 279fbe51c3 sendMail function now gets all the studiengang emails of an active student or sends the mail to personalverwaltung if it is a mitarbeiter 2024-02-15 14:24:07 +01:00
Johann Hoffmann afa00caa4c Merge remote-tracking branch 'origin/feature-34543/UX_Template' into feature-33683/digitale_anwesenheitsliste_und_entschuldigungsmanagement_fuer_studierende_prototyp
# Conflicts:
#	system/filtersupdate.php
2024-02-15 14:16:33 +01:00
SimonGschnell fd260a6307 changes the check if a user has permissions to accept or deny a profil update 2024-02-15 09:59:27 +01:00
SimonGschnell 028be08ec3 fixes little bug with profil update checking 2024-02-14 14:38:21 +01:00
SimonGschnell 5758d7cf4f overrides old zustelladressen/kontakte when changing or adding a new zustelladresse/kontakt 2024-02-14 14:18:31 +01:00
SimonGschnell b655c4021a instead of calculating how many zustelladressen or zustellkontakte a user has in the backend, it is calculated in the client side to prevent an extra api call 2024-02-14 11:42:20 +01:00
SimonGschnell 65a9b8c80f little fix 2024-02-14 09:01:40 +01:00
SimonGschnell bfba05753e also shows the zustellungs warning when there is more than one kontakt marked as zustellung 2024-02-14 08:56:25 +01:00
SimonGschnell 5ee241d914 now editAdressen shows a warning message if a new adresse is marked as zustelladresse 2024-02-13 15:30:23 +01:00
SimonGschnell 409221434a removes the checkbox for heimatadresse because it should not be changed by the user 2024-02-13 14:25:07 +01:00
SimonGschnell 66b843be1b hides the profil updates list if no profil update is present 2024-02-13 14:20:01 +01:00
SimonGschnell 1be8c27cb5 checks the permissions of a user when accepting or denying a profil update 2024-02-13 13:37:10 +01:00
SimonGschnell 92f2f5108c refactor of Profil.php to reuse function functionalities 2024-02-13 11:39:57 +01:00
SimonGschnell 24b467cd90 show different options for address types if the user is a mitarbeiter or a student 2024-02-12 16:29:19 +01:00
SimonGschnell 9ac523c087 deletes column name from public.tbl_profil_update 2024-02-12 16:00:17 +01:00
SimonGschnell 4b898bd976 queries full name of user that created profil_update using join in Profil_update_model 2024-02-12 15:58:52 +01:00
SimonGschnell 78bffb1348 little bugfix 2024-02-12 14:08:26 +01:00
SimonGschnell 6aa0bbb037 fixed little bug with fileOutput 2024-02-12 12:27:15 +01:00
SimonGschnell a09a350338 berechtigungen für die Ansicht von Profil Update Dokumente 2024-02-12 11:30:49 +01:00
SimonGschnell b21d3448cb fixes some data handling errors in controller functions 2024-02-12 09:07:51 +01:00
SimonGschnell 90012856dc EditAdresse layout change 2024-02-09 15:21:53 +01:00
SimonGschnell bbf6616cd9 corrects the display of links to attachments of a profil update request 2024-02-09 14:41:29 +01:00
SimonGschnell 43492add0b changes how files are attached/replaced to a profil update 2024-02-09 13:55:08 +01:00
SimonGschnell cda13ac705 makes the send button in the profil update popup disabled instead of not showing it 2024-02-08 13:47:03 +01:00
SimonGschnell 89bc5a5d9d Assistenten koennen nur Profil Aenderungen von Studenten ansehen deren Organisationseinheit in den Berechtigung des Assistenten vorhanden sind (und kleiner sessionStorage fix der einen String zu Boolean converted) 2024-02-08 11:48:14 +01:00
SimonGschnell fa1871a059 adopting profil controllers/models/views to db table change 2024-02-07 16:34:00 +01:00
SimonGschnell 3739581a29 db tabellen anpassung 2024-02-07 16:25:39 +01:00
SimonGschnell 9362aea0cf when user does not have permissions to accept/deny a profil update request it is notified via alert modal 2024-02-07 14:21:25 +01:00
SimonGschnell 286c7be83d only displays profil update requests the uid has permissions for (mitarbeiter/stammdaten or student/stammdaten), also fixes bug and adds JSON.parse to get the value in the sessionStorage 2024-02-07 13:25:50 +01:00
SimonGschnell 1e260a178c trying to restructure where editData is created 2024-02-06 16:24:43 +01:00
SimonGschnell 3d2c7e4026 sorts the data of the profil updates before displaying them in a table and tooltips have been added to the hr profil update requests table 2024-02-06 11:26:45 +01:00
SimonGschnell f47650f5e9 shows a menu when right clicking a profil update request in the hr view 2024-02-05 15:33:51 +01:00
Johann Hoffmann c6d4c34cad define AnwesenheitenByLektor in system/filtersupdate.php 2024-02-05 15:32:03 +01:00
SimonGschnell ff88581ecd stores the value of the selection to show all or only the pending Profil update requests in the sessionStorage 2024-02-05 14:26:38 +01:00
SimonGschnell 4faaa78ee1 also shows the zustelladresse checkbox when viewing an Adresse component in the hr View for Profil Updates 2024-02-05 13:16:51 +01:00
SimonGschnell a2d0f9e39a funciton that queries the ProfilUpdates now takes a associative array instead of multiple separate parameters 2024-02-05 11:17:07 +01:00
SimonGschnell 6e55382d15 adds zustelladresse as a field to EditKontakte component 2024-02-05 09:52:27 +01:00
SimonGschnell c88da53c03 only allows to user to send profil updates when the input doesn't correspond the original values 2024-02-02 09:49:07 +01:00
SimonGschnell e5182a20ac adds a select to the profilUpdateRequests to change display between only pending and all requests 2024-02-01 15:27:24 +01:00
SimonGschnell d813f55a9b makes it possible to display documents when reviewing profil update requests 2024-02-01 14:08:55 +01:00
SimonGschnell 1460e6ed80 modifing uploaded files int the fetchProfilUpdates component works correctly 2024-01-31 15:22:03 +01:00
SimonGschnell 0e69e432da fixes a lot of bugs and adds the inseramum/insertvon/updateamum/updatevon fields to the cis_profil_update db table 2024-01-31 14:26:54 +01:00
SimonGschnell 6f081e4136 removes logs 2024-01-31 09:15:48 +01:00
SimonGschnell df1fe01abe makes watcher eager and aligns files vertically 2024-01-31 09:05:23 +01:00
SimonGschnell 3362eb8e31 changing the text_input component to accept documents for the name or the title of a PersonUpdateRequest 2024-01-30 15:59:56 +01:00
SimonGschnell a21a292da6 dokument upload 2024-01-29 16:48:41 +01:00
SimonGschnell 76f2501fec little layout fix 2024-01-29 11:14:51 +01:00
SimonGschnell 9ebb04a01b StudentView also uses the layout components 2024-01-29 09:49:50 +01:00
SimonGschnell 783a2fb2b0 removes print in MitarbeiterView Controller and MitarbeiterView uses the components to render the information 2024-01-29 09:22:20 +01:00
SimonGschnell bdf59f3230 layout fixes and adding profilUpdateRequests component to Student view 2024-01-26 17:51:08 +01:00
SimonGschnell bece495ac8 fixes edge cases realted to creating new profil update requests 2024-01-26 16:37:39 +01:00
SimonGschnell 15cd9155f1 updates kontakt_id / adresse_id in profilUpdateRequest after inserting new kontakt/adresse in db 2024-01-25 16:43:47 +01:00
SimonGschnell 20672cd311 add/delete/update von Adressen funktioniert 2024-01-24 17:03:06 +01:00
SimonGschnell a390eefd75 add/delete/update kontakt is possible 2024-01-24 16:06:22 +01:00
SimonGschnell 20d6a34506 little style changes and adds name field to the public.tbl_cis_profil_update table 2024-01-24 12:18:21 +01:00
SimonGschnell 5f55834ccf controller functionality to apply profil update requests to the user 2024-01-23 18:03:38 +01:00
SimonGschnell 13f2bb4e85 fixes little bug where status timestamp was converted from null to the current date, with create_date in php 2024-01-23 11:40:02 +01:00
SimonGschnell df74bade9b fixes bug when getting all the profil update requests and makes it possible to add a message when dening or accepting a profil update 2024-01-23 11:00:43 +01:00
SimonGschnell 7abe04a69f fixes little bug for View Profil and changes layout of the profil update fetch component 2024-01-22 16:02:52 +01:00
SimonGschnell fb9b65b138 changes how to display the hr table with all the user update requests and the update request table in the profil view, also adds some new columns to the cis_profil_update table to store the status, status date and status message 2024-01-22 14:45:32 +01:00
SimonGschnell 0d5e8e89a6 splits the ProfilComponents.js file into multiple components in the ProfilComponents Folder and StudentProfil uses the components 2024-01-19 15:07:57 +01:00
SimonGschnell 84b23a148e modulerizing the profil page in multiple reusable components 2024-01-18 15:32:52 +01:00
SimonGschnell 5e7e2b63dd disables the kontakt input field in the EditKontakt component if no Kontakttyp was selected 2024-01-18 11:31:28 +01:00
SimonGschnell c5f6ce861b when adding a new kontakt or address, it is possible to modify it afterwards 2024-01-18 09:20:01 +01:00
SimonGschnell 8bda0f2f96 first template for the functionality to add a new kontakt/address 2024-01-17 15:34:53 +01:00
SimonGschnell 49fda27e56 profilUpdates need to have unique adresse_id or kontakt_id 2024-01-17 13:53:32 +01:00
SimonGschnell a5c77543b1 adds functionality to delete a Kontakt or an Adress 2024-01-17 12:07:06 +01:00
SimonGschnell b53dec6a31 adds breadcrumb to modal and adjusts controller functions and api calls 2024-01-16 15:44:04 +01:00
SimonGschnell 73792d1e78 the user is now able to delete an existing change request that he made 2024-01-15 15:40:55 +01:00
SimonGschnell e881abe904 allows user to make profil changes requests and to oversee his requested changes 2024-01-15 15:15:16 +01:00
SimonGschnell d3a3ebacfc first templates for the components Select and Breadcrumbs 2024-01-10 15:02:11 +01:00
SimonGschnell 75ce2a0aa8 Shows Select option names without _ 2024-01-10 09:11:24 +01:00
SimonGschnell b1d8a2f5a4 adds topic field to the cis_profil_update table and changes the layout of the editProfil Modul 2024-01-09 15:51:50 +01:00
SimonGschnell 5b597dbc31 changing the editProfil Modal from an Accordion to a select 2024-01-08 15:19:18 +01:00
SimonGschnell e479a7aa49 stores the old and the new value in the profil update request, to track which information has to be updated in the database 2024-01-05 10:40:47 +01:00
Simon Gschnell ee8051915e formats the update timestamps in php, differently tracks which properties and informations where changed by the user 2024-01-04 16:06:47 +01:00
Simon Gschnell d412c1d00e first template for the hr view to accept or deny profil update requests 2024-01-03 14:38:40 +01:00
Simon Gschnell ddab42123b refactores the modal out of the view into its own modal component 2024-01-02 12:50:04 +01:00
Simon Gschnell bb0656c480 http response returns the timestamp of the change 2023-12-29 12:01:25 +01:00
Simon Gschnell a27b80c394 show the date of the last edit profil information request if there is any 2023-12-29 10:17:33 +01:00
Simon Gschnell 59b848c576 fetches profil update request if an entry with uid in table public.tbl_cis_profil_update exists 2023-12-28 11:51:58 +01:00
Simon Gschnell 414541b6cf checks if table entry for uid exists and performs update or insert on result 2023-12-28 10:43:21 +01:00
Simon Gschnell 981e782c57 checks whether the editProfilData was changed by the user and is not in the original state 2023-12-28 10:15:24 +01:00
Simon Gschnell 87f640d66a little layout fix for MitarbeiterViewProfil.js 2023-12-27 11:20:54 +01:00
Simon Gschnell d8cd52f7a0 accordion styling 2023-12-27 11:16:18 +01:00
Simon Gschnell f3e23b888d fixing the accordion with editData 2023-12-27 10:42:33 +01:00
Simon Gschnell 620528fa50 moves the collapseFunction to the parent component Profil and also manages the collapse state from the parent 2023-12-27 09:27:18 +01:00
Simon Gschnell 733275a162 first profil info edit template 2023-12-22 14:18:49 +01:00
Simon Gschnell d6ef9c4ec4 adds custom floating label css construct to the rest of the profil views 2023-12-21 11:46:42 +01:00
Simon Gschnell fed4f7f929 replaced form-control with custom css construct 2023-12-21 08:53:56 +01:00
Simon Gschnell 6f8bd9527c changes the styling when hovering over form-control fields in the profil view, so that it does not also change the behavior of other elements that use form-control on the web page 2023-12-19 16:00:43 +01:00
Simon Gschnell 9c69d8cc46 trims the student information so that the value is falsy in javascript 2023-12-19 15:49:57 +01:00
Simon Gschnell 8666dbe3a6 wrong uid was used to get the emails of the student profil view 2023-12-19 15:36:11 +01:00
Simon Gschnell c08171536c changes the tel and mailto links of all profil views 2023-12-19 15:34:28 +01:00
Simon Gschnell 030be5b83f queryies the telefon number of the mitarbeiter with standort and adds tel links to all phone numbers 2023-12-19 11:02:44 +01:00
Simon Gschnell a3e70afdc1 adds font-size 1rem to the .tabulator class of the FilterComponent 2023-12-19 11:01:51 +01:00
Simon Gschnell 8b06ef030a adds icons and some layout changes 2023-12-18 15:27:45 +01:00
Simon Gschnell f0a3b8db95 Merge remote-tracking branch 'origin/feature-25999/C4' into feature-25999/C4_ma0594dev
merges menu width
2023-12-18 12:26:01 +01:00
cgfhtw eb05922043 menu width 2023-12-18 12:25:16 +01:00
Simon Gschnell 5fbe374ea3 removes the p-4 for all screensizes from the cis-main and adds different padding for mobile view Cis-main in Cis.css 2023-12-18 12:21:17 +01:00
Simon Gschnell 64326136d5 Merge remote-tracking branch 'origin/feature-25999/C4' into feature-25999/C4_ma0594dev 2023-12-18 12:14:07 +01:00
Simon Gschnell fa3d9e1e05 layout changes 2023-12-18 12:13:03 +01:00
cgfhtw 9c2f062d34 Css update 2023-12-18 09:56:59 +01:00
cgfhtw 2e1f38cc91 Merge remote-tracking branch 'origin/feature-25999/C4' into feature-25999/C4 2023-12-18 09:54:15 +01:00
cgfhtw ae0c311be3 Css korrektur 2023-12-18 09:53:52 +01:00
KarpAlex b6adf1ad53 Merge branch 'master' into feature-30679/Plausichecks_Behebung_parameter_zur_Identifizierung_eines_Issues_einbeziehen 2023-12-17 19:12:05 +01:00
Simon Gschnell 1d75a26230 responsive layout 2023-12-15 14:40:56 +01:00
Simon Gschnell 98006b3d2b puts hidden quick links in card 2023-12-14 09:19:07 +01:00
Simon Gschnell 91781d3a38 adds cards to the main information of the mitarbeiter profil view 2023-12-13 15:56:24 +01:00
Simon Gschnell d87670edb8 adds Mailverteiler in card 2023-12-13 15:49:51 +01:00
Simon Gschnell 5671bb340b resposive profil information column change and remove default table sideMenu prop 2023-12-13 14:47:40 +01:00
Simon Gschnell bff4fa5544 Merge branch 'master' into feature-25999/C4_ma0594dev 2023-12-13 14:34:37 +01:00
Simon Gschnell b6dbe1513e adds the collapsing funktions to all the different profil view that use a table with more than one column 2023-12-13 13:59:23 +01:00
Simon Gschnell 8fe19d40bc little fix for the collapsing columns function 2023-12-13 13:26:44 +01:00
Simon Gschnell ba17974371 adds the collapsing function to the column itself 2023-12-13 12:58:34 +01:00
Simon Gschnell b400ea758c fixing the hide/show all collapsed table columns function by calling the click event instead of changing the classes and styles manually 2023-12-13 12:54:44 +01:00
Simon Gschnell 058863ba8d fix for show/hide all collapsed columns icon function, weird bug where collapsed columns icons don't work on first click 2023-12-13 11:22:47 +01:00
Simon Gschnell 4715ce3b95 icon to show or hide all collapsed columns 2023-12-13 10:58:05 +01:00
Simon Gschnell a72b8a153e layout changes 2023-12-12 15:34:28 +01:00
Simon Gschnell 633cd6be0f adds wrap word to every view and deltes the old profil view 2023-12-12 14:48:26 +01:00
Simon Gschnell 5b03abb50c restyling for the hidden dropdown quick links 2023-12-12 14:42:15 +01:00
Simon Gschnell 036365e148 shows all columns, removes the hidding of a column 2023-12-12 14:00:01 +01:00
Simon Gschnell 4b45914d4f adds the collapse formater function as a global Vue function that can be used by alle the different view components 2023-12-12 13:50:38 +01:00
Simon Gschnell b2c8bcb2bf adds a little shadow to the collapsed columns in the tables 2023-12-12 13:21:15 +01:00
Simon Gschnell 350911d474 adds responsive layout collapse to both tables 2023-12-12 12:15:27 +01:00
Simon Gschnell 3a191f4a11 adds responsive layout to the tables by collapsing the columns of a table 2023-12-12 12:09:03 +01:00
Simon Gschnell 38301572ae Mailverteiler nehmen ganze Spalte ein bei Viewport lg 2023-12-12 09:41:53 +01:00
Simon Gschnell aefe73b642 overflow-wrap: break-word style for better text wrapping 2023-12-12 09:28:49 +01:00
Simon Gschnell efc8e7c5fe css fix to wrap words when space gets little 2023-12-12 09:04:07 +01:00
Simon Gschnell 37f89010a4 adds Mitarbeiter und Studenten Profil Titel 2023-12-11 15:18:44 +01:00
Simon Gschnell 84706c957e changes dynamically the col width if a kontakt anmerkung is vorhanden or not 2023-12-11 14:35:17 +01:00
Simon Gschnell 9beb426531 adding word wrap to bootstrap columns 2023-12-11 13:47:56 +01:00
Simon Gschnell 832a3de8c5 centers the text of the link under the image 2023-12-11 13:38:44 +01:00
Simon Gschnell d378cd3002 center profil image in the middle 2023-12-11 13:05:25 +01:00
Simon Gschnell f45d692e66 used new layout for the different views 2023-12-11 12:55:54 +01:00
Simon Gschnell e8a89cf277 add comments to the layout to logically seperate the different columns and rows 2023-12-11 09:47:39 +01:00
Simon Gschnell 8f152cdf50 fixed layout bug, table now shows under profil information without disturbing the right panel 2023-12-11 08:51:51 +01:00
Harald Bamberger 3f84fa7f2d use smaller base font-size 2023-12-07 17:17:48 +01:00
Simon Gschnell a48cbaabb9 layout template 2023-12-07 15:59:01 +01:00
Simon Gschnell 02e7ef12de Profil information layout 2023-12-06 13:47:35 +01:00
Simon Gschnell 617c126aa8 store getAuthUID and getAuthPersonID inside Profil controller to avoid extra calls 2023-12-06 09:52:46 +01:00
Simon Gschnell 28b7a41b80 cleaning up the code not needed in the Profil controler 2023-12-05 13:55:51 +01:00
Simon Gschnell 0d3c55b019 dynamic component inside the profil app now controlls the view and the data 2023-12-05 13:52:31 +01:00
Simon Gschnell 087bf229af restructuring controller 2023-12-05 10:39:39 +01:00
Simon Gschnell 71fda916a3 added Menu link and Profile pop up link 2023-12-04 09:25:08 +01:00
Simon Gschnell 75547ea5e3 adding link to search to view profile 2023-12-01 13:35:29 +01:00
Simon Gschnell 48f4afae73 adds Ort_kurzbz for the View_Mitarbeiter 2023-12-01 11:41:17 +01:00
Simon Gschnell 38f76f68f1 conditional rendering for different Profile Views 2023-12-01 11:07:25 +01:00
Simon Gschnell f26801b7de adds a prop to the FilterTable component to conditionally render the filter columns, this was added because there is no need for a filter column when the table only has 1 column 2023-11-28 14:58:16 +01:00
Simon Gschnell c68856b740 completes the index view for both student and mitarbeiter 2023-11-28 14:56:42 +01:00
Simon Gschnell e3ec0fc36c upadtes api calls 2023-11-28 14:55:42 +01:00
Simon Gschnell 2df956ef20 layout for index Mitarbeiter 2023-11-27 12:04:57 +01:00
Simon Gschnell 1817757745 adds the @ to the emails and changes the layout of the information displayed on the profile page 2023-11-27 12:01:04 +01:00
Simon Gschnell dee3b35a5d solved table bug 2023-11-23 14:48:05 +01:00
Simon Gschnell d08b904530 mailverteiler und deren mailto href 2023-11-23 10:02:22 +01:00
Simon Gschnell 0e813f78fb updates the foto_sperre_function to automatically update the data of the vue component 2023-11-22 09:51:49 +01:00
Simon Gschnell 16b61d0560 Daten fuer die Betriebsmittel und zutrittskarten_ausgegebenam gesammelt 2023-11-20 17:30:58 +01:00
Simon Gschnell 4fead18c06 adds the model calls for the benutzerfunktionen information for the cis profile 2023-11-17 15:27:41 +01:00
Simon Gschnell 6b27c00d30 new data collection 2023-11-17 13:09:32 +01:00
Simon Gschnell 40a58ad9d0 Merge branch 'feature-25999/C4' of github.com:FH-Complete/FHC-Core into feature-25999/C4 2023-11-17 13:05:48 +01:00
Simon Gschnell dee0bdaa17 querying new data for the cis profile page 2023-11-15 15:09:59 +01:00
Simon Gschnell 7c229bbcee importing the api calls in the component and creating api endpoints for the cis profile page 2023-11-15 13:49:06 +01:00
SimonGschnell 9227cc12f0 retrieving user data from mitarbeiter and benutzer models 2023-11-14 14:36:47 +01:00
SimonGschnell 5b385d376e creating the controller/view/api base 2023-11-14 11:52:45 +01:00
cgfhtw c0fbc74862 Bug: search url not dynamic 2023-11-13 15:04:41 +01:00
cgfhtw 8e3939a885 bug: path seperator 2023-11-06 11:20:00 +01:00
cgfhtw 7dee77a6af Code Quality 2023-07-27 11:42:03 +02:00
cgfhtw ace3bd6736 Verbesserungen 2023-07-27 10:57:53 +02:00
cgfhtw cfe7c5b0da Merge branch 'feature-27351/Digitalisierung_Formulare_Neu' into feature-25999/C4 2023-07-25 14:07:17 +02:00
cgfhtw 764628d5fb Merge branch 'feature-27351/Digitalisierung_Formulare_Neu' into feature-25999/C4 2023-07-25 10:40:38 +02:00
cgfhtw 2046b6c2a8 Menu Entry: Studierendenantrag 2023-07-25 10:38:48 +02:00
cgfhtw 8901791911 Merge branch 'feature-27351/Digitalisierung_Formulare_Neu' into feature-25999/C4 2023-07-19 14:37:59 +02:00
cgfhtw ffd12e8ddf Access Rights 2023-07-19 11:17:17 +02:00
cgfhtw 044695183f Merge branch 'feature-24647/Konfigurierbare_Dashboards' into feature-25999/C4 2023-07-19 11:15:40 +02:00
cgfhtw 0beabe0f4a spaces to tabs 2023-07-19 11:11:52 +02:00
cgfhtw 0fd53dc3ac spaces to tabs 2023-07-19 11:10:01 +02:00
cgfhtw 72169b26c3 separate class attribute and property for easier readability 2023-07-19 11:06:01 +02:00
cgfhtw 7b96f99929 Access Rights Api Controller 2023-07-19 10:59:39 +02:00
cgfhtw 72d0517701 Merge branch 'master' into feature-25999/C4 2023-07-19 10:55:35 +02:00
cgfhtw dc21662fc9 Add missing SQL Rights for web 2023-07-14 13:01:01 +02:00
cgfhtw b0c9231d14 Hmvc: Safer Code 2023-07-14 09:02:25 +02:00
cgfhtw c5db083a84 Correct paths 2023-07-12 15:32:52 +02:00
cgfhtw 5f3e393ed1 Default menu: correct paths 2023-07-12 09:12:03 +02:00
KarpAlex 1416e91af7 Issues: Behebung parameter are included in identification of an issue 2023-07-11 15:58:48 +02:00
cgfhtw 3e4703408b directories from variables 2023-07-10 08:42:48 +02:00
cgfhtw d54868070f 29006: Dashboard verbesserungen 2023-05-08 12:39:25 +02:00
cgfhtw 2780ec5636 Dashboard Admin Demo 2023-05-05 14:27:33 +02:00
cgfhtw 4f43b79ed5 default controller 2023-04-14 12:50:07 +02:00
cgfhtw 95458c193c CIS4 Entry & View titles 2023-03-31 14:50:56 +02:00
cgfhtw 2a59fad2fc CMS loading speedup 2023-03-31 09:21:52 +02:00
cgfhtw e2cf663f88 Default Menu 2023-03-31 09:21:09 +02:00
cgfhtw 7e518c3978 Documents 2023-03-24 11:26:16 +01:00
Paolo 06179ee714 Code quality check fixes 2023-03-23 14:38:42 +01:00
cgfhtw 9e11dfb668 code quality 2023-03-14 11:00:36 +01:00
cgfhtw 6b6392deb4 Missing ; 2023-03-13 09:02:46 +01:00
cgfhtw 2238b872c6 Documents Self Service 2023-03-13 09:01:45 +01:00
cgfhtw 83c0413815 code quality 2023-03-10 10:29:54 +01:00
cgfhtw 91e43bbc07 Documents first draft 2023-03-10 09:28:57 +01:00
cgfhtw f9975eb530 Code Quality 2023-03-10 09:28:04 +01:00
cgfhtw 555b8f4e6b access rights 2023-02-24 11:59:27 +01:00
cgfhtw 280890a00d Stundenplan Widget 2023-02-24 11:57:54 +01:00
cgfhtw 3d1908982a Merge branch 'feature-24647/Konfigurierbare_Dashboards' into feature-25999/C4 2023-02-09 16:12:36 +01:00
cgfhtw 9f72206796 Stundenplan Widget Basic 2023-02-06 11:44:36 +01:00
cgfhtw 13b898179e Widget classes 2023-02-06 09:46:32 +01:00
cgfhtw 7e2d63e3fe Css cleanup 2023-02-06 08:53:32 +01:00
cgfhtw 0f60ab2a54 Stundenplan & Calendar 2023-02-06 08:43:43 +01:00
cgfhtw d1f69d4696 MyLV Verbesserungen & cleanup 2023-02-06 08:42:42 +01:00
cgfhtw 034bed6580 cleanup 2023-01-16 11:40:40 +01:00
cgfhtw 2e126692f2 MyLv: Permissions & notFound fallback 2023-01-16 11:38:24 +01:00
cgfhtw 559e4d2bc0 cleanup 2023-01-16 11:22:53 +01:00
cgfhtw 2f2f19306b MyLv 2023-01-16 10:32:24 +01:00
cgfhtw ebc7b5a3d9 Login/Logout 2023-01-16 10:31:02 +01:00
cgfhtw c5b996f35e use vue for cms for link correction 2022-12-16 13:41:16 +01:00
cgfhtw 00c52e4880 cleanup 2022-12-16 11:43:35 +01:00
cgfhtw 4335c2da80 add Dashboard to HMVC 2022-12-16 11:36:33 +01:00
cgfhtw 085ed750ca using cis.php and routing news 2022-12-16 11:34:39 +01:00
cgfhtw c56b774d1d 3 Versions 2022-12-15 09:42:28 +01:00
cgfhtw 266ba7523f s&d 2022-11-29 08:48:50 +01:00
cgfhtw 546e55ed96 Merge branch 'feature-24647/Konfigurierbare_Dashboards' into feature-25999/C4 2022-11-24 15:36:38 +01:00
cgfhtw 4120f5a566 Merge remote-tracking branch 'origin/feature-24647/Konfigurierbare_Dashboards' into feature-24647/Konfigurierbare_Dashboards 2022-11-24 11:53:06 +01:00
cgfhtw 4758fcb413 access rights 2022-11-24 11:52:09 +01:00
cgfhtw 3e0aa849d4 bugfixes & "+" background 2022-11-24 11:52:01 +01:00
Harald Bamberger 3e17892831 fixed path to news placeholder image 2022-11-24 11:50:09 +01:00
cgfhtw d51a95a8a0 test controller & views 2022-11-24 11:48:46 +01:00
cgfhtw d7c2362a0e double widgets bug 2022-11-22 14:39:33 +01:00
cgfhtw a5749a5ea2 bug: wrong check for empty fields when adding new widgets (coordinates are based on 0,0 not 1,1) 2022-11-08 14:47:44 +01:00
cgfhtw 0e7343acfb bug: uncaught promise on widget-picker abort 2022-11-08 14:46:44 +01:00
cgfhtw 0d65ae5b85 widget icons absolute path 2022-11-03 11:37:13 +01:00
cgfhtw 55959ccd41 modal size 2022-11-03 11:33:52 +01:00
cgfhtw 935881dce2 icon & cursor 2022-11-03 11:28:25 +01:00
cgfhtw 3764df6102 Add widget to preset bugfix 2022-11-03 11:24:29 +01:00
Harald Bamberger e1addbfe04 Merge branch 'master' into feature-24647/Konfigurierbare_Dashboards_api
- mv dbchanges from system/dbupdate_3.3.php to system/dbupdate_3.4.php
- mv dbchanges include file from system/dashboard/ to system/dbupdate_3.4/ and prevent direct script access
2022-11-03 10:41:56 +01:00
Harald Bamberger 677f74781b Merge branch 'feature-24647/Konfigurierbare_Dashboards_widgets' into feature-24647/Konfigurierbare_Dashboards_api 2022-11-03 10:31:36 +01:00
Harald Bamberger c78c731388 renamed Dashboard Controller to DashboardDemo and used view to dashboard_demo 2022-11-03 10:27:39 +01:00
cgfhtw 8fd61edaab Admin Components 2022-10-28 12:41:25 +02:00
cgfhtw 92ec7f44ef Update Dashboard Endpoints for Admin GUI 2022-10-28 12:40:57 +02:00
cgfhtw be6ad8ce2a cleanup 2022-10-28 12:39:19 +02:00
Cris 630c1bc2bc Changed to display 4 Ampeln in Widget 2022-10-25 14:35:38 +02:00
Cris a1ccd392f5 Added News Widget 2022-10-25 14:28:25 +02:00
Cris bc723b22f4 Added getAll() to News Model 2022-10-25 14:28:14 +02:00
Cris 71699f6e74 Added Ampel Widget 2022-10-25 14:17:52 +02:00
Cris 1d6c5b4257 Added Url Widget 2022-10-25 14:17:32 +02:00
Cris 7f1cc966f0 Added API Controller to perform API calls 2022-10-25 13:00:43 +02:00
Cris aaf64a759b Added Widgets to Widget Controller 2022-10-25 12:59:03 +02:00
Cris ae05b34cbf Removed test function 2022-10-25 12:58:14 +02:00
Cris fdc52ae47d Added Offcanvas Component 2022-10-25 12:57:27 +02:00
Cris c5d3f47457 Merged Modal Component, adapted body padding there 2022-10-25 12:55:49 +02:00
Cris 699b76f4cb Added general used methods and computed property to Abstract Mixin Component
. apiurl: returns app root and ci router from FHC_JS_DATA_OBJECT
. formatDateTime: returns human readable date time
. getDate: returns human readable date
2022-10-25 12:54:35 +02:00
cgfhtw 1043714767 adminMode in Sections 2022-10-25 09:51:20 +02:00
cgfhtw a65d297997 use FHC_JS_DATA_STORAGE_OBJECT for apiurl 2022-10-24 16:01:02 +02:00
cgfhtw a3722273e9 use Bootstrap modals 2022-10-24 15:44:12 +02:00
cgfhtw 4aa7b9854a setConfig is an emit not a prop 2022-10-24 15:08:10 +02:00
Cris b6308d1ff5 Merge remote-tracking branch 'origin/feature-24647/Konfigurierbare_Dashboards_api' into feature-24647/Konfigurierbare_Dashboards_widgets 2022-10-24 11:04:31 +02:00
cgfhtw 8983a0e821 Bootstrap Modal (+ Alert,Confirm,Prompt) 2022-10-24 11:01:27 +02:00
Cris 67f1094a97 Added Modal Component 2022-10-17 13:40:18 +02:00
Cris 065dd1d081 Added FHTW illustration image 2022-10-17 13:38:07 +02:00
Cris ecbc6d8e3d Added Dashboard Controller & View 2022-10-17 13:37:08 +02:00
Cris 0bd6af8da1 Merge remote-tracking branch 'origin/feature-24647/Konfigurierbare_Dashboards_api' into feature-24647/Konfigurierbare_Dashboards_widgets 2022-10-13 15:14:29 +02:00
cgfhtw 680787d881 Don't move out of bounds on Drag&Drop 2022-10-13 14:44:33 +02:00
cgfhtw a71ead0a85 Ajax update: better data consistency 2022-10-13 14:38:03 +02:00
cgfhtw fd2aa8a1bb Cleanup & uid from AuthLib 2022-10-13 08:43:08 +02:00
cgfhtw 6570c958b3 Bug: DataTransfer in Chrome 2022-10-12 15:50:40 +02:00
Cris b4053c45fd Merge remote-tracking branch 'origin/feature-24647/Konfigurierbare_Dashboards_api' into feature-24647/Konfigurierbare_Dashboards_widgets 2022-10-12 15:17:47 +02:00
cgfhtw dd4d71bd7d Bug: Deepmerge on update 2022-10-12 10:29:52 +02:00
Cris c7c8913833 Adapted Dashboard DB Update: Berechtigungen ergänzt / Typspezifikation entfernt.
. Berechtigungen ergänzt:
  - dashboard/benutzer
  - dashboard/admin

. Typspezifikation entfernt in Create Sequence
  - war nicht mit PHPSQL 9.6.2 kompatibel.
2022-10-12 09:19:54 +02:00
cgfhtw a468338ead Configurable CSS classes to Default Widget 2022-10-12 09:08:24 +02:00
cgfhtw 39bbcac217 Widget controller & model & table 2022-10-12 08:58:48 +02:00
cgfhtw a3ad8eb337 dashboard.tbl_widget new fields 2022-10-11 15:41:43 +02:00
cgfhtw 4f3e8dcb3c Basic VUE Components & Test WidgetController 2022-10-05 10:43:43 +02:00
Harald Bamberger 90e006feb5 allow widgets array for add operations 2022-10-04 08:22:27 +02:00
Harald Bamberger d14608ed28 level funktion_kurzbz added to presets and overrides 2022-10-03 07:59:11 +02:00
Harald Bamberger ad369bbe44 add dashboard schema and tables create script 2022-09-28 16:53:48 +02:00
Harald Bamberger 252abeafcb dummy config changed to test function level in config 2022-09-28 15:26:45 +02:00
Harald Bamberger fb7f445e22 progress on api endpoints to add and remove presets and overrides 2022-09-21 11:38:16 +02:00
Harald Bamberger 5c9c4b7e2d store configs as json in database and merge them 2022-09-16 10:46:29 +02:00
Harald Bamberger ff93c957cd dashboard config api first steps 2022-09-14 19:05:29 +02:00
Cris 7daa289bb1 Merge branch 'master' into feature-18073/No-Reply-for-Sanchomails 2022-05-10 10:57:50 +02:00
Cris c39174980c Fixed function _getSTGLMailAddress to return same array structure
Different structure was causing errors in handling.
2022-05-09 15:34:22 +02:00
Cris efcef48f89 Changed Sanchomail 'From' to noreply 2022-05-09 11:14:01 +02:00
684 changed files with 66431 additions and 8931 deletions
+2
View File
@@ -2,6 +2,8 @@ documents/
vendor/
/nbproject/
.vscode
composer.phar
/.idea/
.settings
.project
+10 -1
View File
@@ -1,6 +1,6 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
if (!defined('BASEPATH')) exit('No direct script access allowed');
// Deadline for Application given as Time-Interval after Semesterstart.
@@ -24,3 +24,12 @@ $config['send_mail'] = TRUE;
// Display fields to explain equivalence of ECTS and LV-Inhalte
$config['explain_equivalence'] = TRUE;
// Displays infobox if set to true
$config['display_infobox'] = [
'fristen' => TRUE,
'referenzbeispiele_ects' => TRUE,
'voraussetzungen' => TRUE,
'nachweisdokumente' => TRUE,
'herkunft_kenntnisse' => TRUE
];
+9
View File
@@ -0,0 +1,9 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
// CMS Content Id for CIS4 Menu Root
$config['cis_menu_root_content_id'] = 11087;
// send Mails for ProfilUpdate
$config['cis_send_profil_update_mails'] = true;
+7
View File
@@ -0,0 +1,7 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
// use vuejs dev version
$config['use_vuejs_dev_version'] = false;
// use bundled javascript
$config['use_bundled_javascript'] = false;
+15
View File
@@ -32,3 +32,18 @@ $config['validate'] = false; // If true then the email address will be validated
// If enabled will be logged info about emails in Codeigniter error logs
$config['enable_debug'] = false;
// default sender
$config['sancho_mail_default_sender'] = defined('SANCHO_MAIL_DEFAULT_SENDER') ? SANCHO_MAIL_DEFAULT_SENDER : '';
// If to use images for custom mails
$config['sancho_mail_use_images'] = defined('SANCHO_MAIL_USE_IMAGES') ? SANCHO_MAIL_USE_IMAGES : false;
// image path for sancho mail, relativ to document root
$config['sancho_mail_img_path'] = defined('SANCHO_MAIL_IMG_PATH') ? SANCHO_MAIL_IMG_PATH : '';
// header image for custom mails
$config['sancho_mail_header_img'] = defined('SANCHO_MAIL_HEADER_IMG') ? SANCHO_MAIL_HEADER_IMG : '';
// footer image for custom mails
$config['sancho_mail_footer_img'] = defined('SANCHO_MAIL_FOOTER_IMG') ? SANCHO_MAIL_FOOTER_IMG : '';
+24 -4
View File
@@ -1,6 +1,12 @@
<?php
// Header menu
if(defined('CIS4') && CIS4) {
$root = APP_ROOT;
} else {
$root = CIS_ROOT;
}
$config['navigation_header'] = array(
'*' => array(
'fhcomplete' => array(
@@ -50,11 +56,17 @@ $config['navigation_header'] = array(
'requiredPermissions' => 'basis/vilesci:r',
'children' => array(
'cis' => array(
'link' => CIS_ROOT,
'link' => $root,
'icon' => '',
'description' => 'CIS',
'sort' => 10
),
'lehrveranstaltungen' => array(
'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'),
'icon' => '',
'description' => 'Lehrveranstaltungen',
'sort' => 15
),
'reihungstest' => array(
'link' => site_url('organisation/Reihungstest'),
'description' => 'Reihungstests',
@@ -217,7 +229,7 @@ $config['navigation_menu']['organisation/Reihungstest/index'] = array(
'target' => '_blank'
),
'auswertung' => array(
'link' => CIS_ROOT.'/cis/testtool/admin/auswertung.php',
'link' => $root.'/cis/testtool/admin/auswertung.php',
'description' => 'Auswertung',
'icon' => 'list-alt',
'sort' => 1,
@@ -287,6 +299,15 @@ $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array(
)
);
$config['navigation_menu']['lehre/lvplanung/LvTemplateUebersicht/index'] = array(
'lvTemplateUebersicht' => array(
'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'),
'description' => 'LV Template Übersicht',
'icon' => '',
'sort' => 1
)
);
$config['navigation_menu']['system/issues/Issues/*'] = array(
'fehlerzustaendigkeiten' => array(
'link' => site_url('system/issues/IssuesZustaendigkeiten'),
@@ -304,5 +325,4 @@ $config['navigation_menu']['system/issues/Issues/*'] = array(
'target' => '_blank',
'requiredPermissions' => array('admin:rw')
),
);
);
+4 -3
View File
@@ -50,7 +50,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
| Examples: my-controller/index -> my_controller/index
| my-controller/my-method -> my_controller/my_method
*/
$route['default_controller'] = 'Vilesci';
$route['default_controller'] = defined('CIS4') && CIS4 ? 'Cis4' : 'Vilesci';
$route['translate_uri_dashes'] = FALSE;
// Class name conflicts
@@ -61,6 +61,8 @@ $route['api/v1/organisation/[O|o]rganisationseinheit/(:any)'] = 'api/v1/organisa
$route['api/v1/ressource/[B|b]etriebsmittelperson/(:any)'] = 'api/v1/ressource/betriebsmittelperson2/$1';
$route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1';
$route['Cis/Stundenplan/.*'] = 'Cis/Stundenplan/index/$1';
// load routes from extensions
$subdir = 'application/config/extensions';
$dirlist = scandir($subdir);
@@ -81,5 +83,4 @@ if ($dirlist)
}
}
}
}
}
+76
View File
@@ -0,0 +1,76 @@
<?php
$config['tabs'] =
[
'details' => [
//all fields can be configured to be hidden, see class attribute stv-details-details-name for name
'hiddenFields' => [],
'hideUDFs' => false
],
'prestudent' => [
//all fields can be configured to be hidden, see class attribute stv-details-prestudent-name for name
'hiddenFields' => [
//propably used by FH-Communities
'aufnahmeschluessel', 'standort_code', 'facheinschlaegigBerufstaetig'
],
'hideUDFs' => false
],
'finalexam' => [
'documents' => [
'pruefungsprotokoll' => [
'de' => [
'Bakk' => 'PrProtBA',
'Master' => 'PrProtMA',
],
'en' => [
'Bakk' => 'PrProtBAEng',
'Master' => 'PrProtMAEng',
],
],
'pruefungszeugnis' => [
'de' => [
'Bakk' => 'Bakkzeugnis',
'Master' => 'Diplomzeugnis',
],
'en' => [
'Bakk' => 'BakkzeugnisEng',
'Master' => 'DiplomzeugnisEng',
],
],
'urkunde' => [
'de' => [
'Bakk' => 'Bakkurkunde',
'Master' => 'Diplomurkunde',
],
'en' => [
'Bakk' => 'BakkurkundeEng',
'Master' => 'DiplomurkundeEng',
],
],
],
]
];
// List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined
$fieldsZgvDoktor = ['zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', 'zgvdoktor_erfuellt', 'zgvdoktor_code'];
// List of fields to show when ZGV_ERFUELLT_ANZEIGEN is defined
$fieldsZgvErfuellt = ['zgv_erfuellt', 'zgvmas_erfuellt','zgvdoktor_erfuellt'];
//order important: to show zgf_erfuellt_doktor just in case visibility of doktor is true
if (!defined('ZGV_ERFUELLT_ANZEIGEN') || !ZGV_ERFUELLT_ANZEIGEN) {
$config['tabs']['prestudent']['hiddenFields'] = array_merge(
$config['tabs']['prestudent']['hiddenFields'], $fieldsZgvErfuellt
);
}
if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) {
$config['tabs']['prestudent']['hiddenFields'] = array_merge(
$config['tabs']['prestudent']['hiddenFields'],
$fieldsZgvDoktor
);
}
+7
View File
@@ -0,0 +1,7 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
// broaden the allowed URI characters just for tests
$config['permitted_uri_chars'] = 'a-z A-Z 0-9~%.:_\-';
// ensure we read REQUEST_URI
$config['uri_protocol'] = 'REQUEST_URI';
+77
View File
@@ -0,0 +1,77 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Auth extends FHC_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
// Load Helpers
$this->load->helper('form');
$this->load->helper('hlp_authentication');
// Loads phrases system
$this->loadPhrases([
'global'
]);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @return void
*/
public function login()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'required|trim|callback_validation');
$this->form_validation->set_rules('password', 'Password', 'required|trim');
if ($this->form_validation->run())
{
redirect($this->authlib->getLandingPage('/CisVue/Dashboard'));
}
else
{
$this->load->view('Cis/Login');
}
}
/**
* @return boolean
*/
public function validation()
{
$username = $this->input->post('username');
$password = $this->input->post('password');
$this->load->library('AuthLib', [false]); // without authentication otherwise loooooop!
$login = $this->authlib->loginLDAP($username, $password);
if (isSuccess($login))
return true;
$this->form_validation->set_message('validation', 'Incorrect username/password.');
return false;
}
/**
* @return void
*/
public function logout()
{
$this->load->library('AuthLib');
$this->authlib->logout();
redirect('/Cis/Auth/login', 'refresh');
}
}
+192
View File
@@ -0,0 +1,192 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \stdClass as stdClass;
/**
*
*/
class Documents extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct([
'index' => [self::PERM_LOGGED],
'student' => ['admin:r'],
'download' => [self::PERM_LOGGED]
]);
$this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
$this->loadPhrases([
'global',
'tools'
]);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @return void
*/
public function index()
{
return $this->showDocuments(getAuthUID());
}
/**
* @param string $uid Administratoren dürfen die UID als Parameter übergeben um die Dokumente von anderen Personen anzuzeigen
* @return void
*/
public function student($uid)
{
return $this->showDocuments($uid);
}
/**
* @param string $uid
* @return void
*/
protected function showDocuments($uid)
{
$this->load->model('crm/Konto_model', 'KontoModel');
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$stati = $this->PrestudentstatusModel->loadWhereUid($uid, null, true);
if (isError($stati))
return $this->load->view('errors/html/error_db.php', [
'heading' => 'Database Error',
'message' => getError($stati)
]);
$stati = getData($stati);
if (!$stati)
return $this->load->view('errors/html/error_general.php', [
'heading' => 'User ist kein Student',
'message' => 'Es konnten keine Studiensemester gefunden werden in denen der User als Student inskripiert ist'
]);
$stgs = [];
$stsemArray = [];
$buchungstypen = implode('\',\'', defined("CIS_DOKUMENTE_STUDIENBEITRAG_TYPEN") ? unserialize(CIS_DOKUMENTE_STUDIENBEITRAG_TYPEN) : []);
$person_ids = [];
foreach ($stati as $status) {
$person_ids[] = $status->person_id;
if(!in_array($status->studiensemester_kurzbz, $stsemArray)) {
$stsemArray[] = $status->studiensemester_kurzbz;
}
if (!isset($stgs[$status->studiengang_kz])) {
$stg = $this->StudiengangModel->load($status->studiengang_kz);
if (isError($stg))
return $this->load->view('errors/html/error_db.php', [
'heading' => 'Database Error',
'message' => getError($stg)
]);
$stg = getData($stg);
if (!$stg)
return $this->load->view('errors/html/error_db.php', [
'heading' => 'Database Error',
'message' => 'No Studiengang found for studiengang_kz ' . $status->studiengang_kz
]);
$stgs[$status->studiengang_kz] = current($stg);
$stgs[$status->studiengang_kz]->studiensemester = [];
}
if (!isset($stgs[$status->studiengang_kz]->studiensemester[$status->studiensemester_kurzbz])) {
$stgs[$status->studiengang_kz]->studiensemester[$status->studiensemester_kurzbz] = new stdClass();
$stgs[$status->studiengang_kz]->studiensemester[$status->studiensemester_kurzbz]->inskriptionsbestaetigung = (boolean)getData(
$this->KontoModel->checkStudienbeitragFromPrestudent(
$status->prestudent_id,
$status->studiensemester_kurzbz,
$buchungstypen
)
);
}
}
$person_ids = array_unique($person_ids);
$selfservice = null;
if (!defined('CIS_DOKUMENTE_SELFSERVICE') || CIS_DOKUMENTE_SELFSERVICE) {
$this->load->model('crm/Akte_model', 'AkteModel');
$selfservice = [];
foreach ($person_ids as $person_id) {
$result = $this->AkteModel->getArchiv($person_id, null, true);
if (isError($result))
return $this->load->view('errors/html/error_db.php', [
'heading' => 'Database Error',
'message' => getError($result)
]);
$selfservice = array_merge($selfservice, getData($result) ?: []);
}
}
$this->load->view('Cis/Documents', [
'stsemArray' => $stsemArray,
'stgs' => $stgs,
'uid' => $uid,
'studienbuchblatt' => defined('CIS_DOKUMENTE_STUDIENBUCHLBATT_DRUCKEN') && CIS_DOKUMENTE_STUDIENBUCHLBATT_DRUCKEN,
'studienerfolgsbestaetigung' => defined('CIS_DOKUMENTE_STUDIENERFOLGSBESTAETIGUNG_DRUCKEN') && CIS_DOKUMENTE_STUDIENERFOLGSBESTAETIGUNG_DRUCKEN,
'selfservice' => $selfservice
]);
}
/**
* @param integer $akte_id
* @param string $uid (optional) Administratoren dürfen die UID als Parameter übergeben um die Dokumente von anderen Personen anzuzeigen
*
* @return void
*/
public function download($akte_id, $uid = null)
{
if (!is_numeric($akte_id))
return show_404();
$this->load->model('crm/Akte_model', 'AkteModel');
$result = $this->AkteModel->load($akte_id);
if (isError($result))
return show_error(getError($result));
$akte = getData($result);
if (!$akte)
return show_404();
$akte = current($akte);
$admin_access = false;
if ($uid !== null && $this->permissionlib->isBerechtigt('admin')) {
$stati = $this->PrestudentstatusModel->loadWhereUid($uid, null, true);
if (hasData($stati)) {
$person_ids = array_map(function ($status) {
return $status->person_id;
}, getData($stati));
$person_ids = array_unique($person_ids);
if (count($person_ids) == 1 && current($person_ids) == $akte->person_id) {
$admin_access = true;
}
}
}
if (!$admin_access && ($akte->person_id != getAuthPersonId() || !$akte->stud_selfservice))
return show_error('Forbidden', 403);
// NOTE(chris): Log bei einem Download vom Becheid
if (isset($akte->dokument_kurzbz) && ($akte->dokument_kurzbz === 'Bescheid' || $akte->dokument_kurzbz === 'BescheidEng')) {
$this->load->model('system/Webservicelog_model', 'WebservicelogModel');
$this->WebservicelogModel->insert([
'webservicetyp_kurzbz' => 'content',
'request_id' => (isset($akte->akte_id) && !empty($akte->akte_id)) ? $akte->akte_id : null,
'beschreibung' => 'Bescheidbestaetigungsdownload',
'request_data' => $_SERVER['QUERY_STRING'],
'execute_time' => date('c'),
'execute_user' => getAuthUID()
]);
}
$this->output->set_content_type($akte->mimetype);
$this->output->set_output(base64_decode($akte->inhalt));
}
}
@@ -3,30 +3,28 @@
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Test VBform Vue Component
*
*/
class TestVBform extends Auth_Controller
class InfoTerminal extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'system/developer:r'
)
);
parent::__construct([
'index' => ['basis/cis:r'],
]);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Everything has a beginning
* @return void
*/
public function index()
{
$this->load->view('system/logs/testVBform.php');
$this->load->view('Cis/InfoTerminal.php', []);
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class MyLv extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct([
'index' => ['basis/cis:r'],
'Info' => [self::PERM_LOGGED]
]);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @return void
*/
public function index()
{
$viewData = array(
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'MyLv']);
}
public function Info($studien_semester,$lvid)
{
$this->load->view('Cis/LvInfo',['lvid'=> $lvid, 'studien_semester' => $studien_semester]);
}
}
+742
View File
@@ -0,0 +1,742 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Profil extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct([
'index' => ['basis/cis:r'],
'foto_sperre_function' => ['basis/cis:r'],
'getView' => ['basis/cis:r'],
'View' => ['basis/cis:r'],
'isMitarbeiter' => ['basis/cis:r'],
'isStudent' => ['basis/cis:r'],
'getZustellAdresse' => ['basis/cis:r'],
'getZustellKontakt' => ['basis/cis:r'],
'getAllNationen' => ['basis/cis:r'],
'getGemeinden' => ['basis/cis:r'],
]);
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('person/Person_model', 'PersonModel');
$this->load->model('person/Adresse_model', 'AdresseModel');
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel');
$this->load->model('ressource/Betriebsmittelperson_model', 'BetriebsmittelpersonModel');
$this->load->model('person/Kontakt_model', 'KontaktModel');
$this->load->model('person/Profil_update_model', 'ProfilUpdateModel');
$this->load->model('content/DmsVersion_model', 'DmsVersionModel');
//? put the uid and pid inside the controller for reusability
$this->uid = getAuthUID();
$this->pid = getAuthPersonID();
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* index loads the Profil view
* @access public
* @return void
*/
public function index()
{
$viewData = array(
);
$this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'profilIndex']);
}
/**
* redirects to the index function (needed to allow calling this URI)
* @access public
* @return void
*/
public function View($uid)
{
$viewData = array ('uid' => $uid);
$this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'profilViewUid']);
}
/**
* checks whether a specific userID is a mitarbeiter or not (foreword declaration of the function isMitarbeiter in Mitarbeiter_model.php)
* @access public
* @param $uid the userID used to check if it is a mitarbeiter
* @return boolean
*/
public function isStudent($uid)
{
$result = $this->StudentModel->isStudent($uid);
if (isError($result)) {
show_error("error when calling Student_model function isStudent with uid " . $uid);
}
$result = getData($result);
echo json_encode($result);
}
/**
* checks whether a specific userID is a mitarbeiter or not (foreword declaration of the function isMitarbeiter in Mitarbeiter_model.php)
* @access public
* @param $uid the userID used to check if it is a mitarbeiter
* @return boolean
*/
public function isMitarbeiter($uid)
{
$result = $this->MitarbeiterModel->isMitarbeiter($uid);
if (isError($result)) {
show_error("error when calling Mitarbeiter_model function isMitarbeiter with uid " . $uid);
}
$result = getData($result);
echo json_encode($result);
}
/**
* gets the adressen that are marked as zustell from the currenlty logged in user
* @access public
* @return array a list of adresse_id's
*/
public function getZustellAdresse()
{
$this->AdresseModel->addSelect(["adresse_id"]);
$adressen_res = $this->AdresseModel->loadWhere(['person_id' => $this->pid, 'zustelladresse' => true]);
$adressen_res = hasData($adressen_res) ? getData($adressen_res) : null;
$adressen_res = array_map(function ($item) {
return $item->adresse_id;
}, $adressen_res);
echo json_encode($adressen_res);
}
/**
* gets the kontakte that are marked as zustell from the currenlty logged in user
* @access public
* @return array a list of kontakt_id's
*/
public function getZustellKontakt()
{
$this->KontaktModel->addSelect(["kontakt_id"]);
$kontakt_res = $this->KontaktModel->loadWhere(['person_id' => $this->pid, 'zustellung' => true]);
$kontakt_res = hasData($kontakt_res) ? getData($kontakt_res) : null;
$kontakt_res = array_map(function ($item) {
return $item->kontakt_id;
}, $kontakt_res);
echo json_encode($kontakt_res);
}
/**
* function that returns the data used for the corresponding view
* the client side parses the @param $uid and calls this function to get the data to the correct view
* @access public
* @param boolean $uid the userID used to identify which information should be retrieved for which view
* @return stdClass all the data corresponding to a view of a user
*/
public function getView($uid)
{
$res = new stdClass();
// if parsing the URL did not found a UID then the UID of the logged in user is used
if ($uid == "Profil" || $uid == $this->uid) {
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($this->uid);
if (isError($isMitarbeiter)) {
show_error("error while checking if UID: " . $this->uid . " is a mitarbeiter");
}
$isMitarbeiter = getData($isMitarbeiter);
if ($isMitarbeiter) {
$res->view = "MitarbeiterProfil";
$res->data = $this->mitarbeiterProfil();
$res->data->pid = $this->pid;
} else {
$res->view = "StudentProfil";
$res->data = $this->studentProfil();
$res->data->pid = $this->pid;
}
}
// UID is availabe when accessing Profil/View/:uid
else {
$this->PersonModel->addSelect(["person_id"]);
$pid = $this->PersonModel->getByUid($uid);
if (isError($pid)) {
show_error("error while trying to update table public.tbl_person while searching for a person with UID: " . $uid);
}
$pid = hasData($pid) ? getData($pid)[0] : null;
if (!$pid) {
show_error("Person with UID: " . $uid . " does not exist");
}
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid);
if (isError($isMitarbeiter)) {
show_error("error while checking if UID: " . $uid . " is a mitarbeiter");
}
$isMitarbeiter = getData($isMitarbeiter);
if ($isMitarbeiter) {
$res->view = "ViewMitarbeiterProfil";
$res->data = $this->viewMitarbeiterProfil($uid);
} else {
$res->view = "ViewStudentProfil";
$res->data = $this->viewStudentProfil($uid);
}
}
echo json_encode($res);
}
/**
* update column foto_sperre in public.tbl_person
* @access public
* @param boolean $value new value for the column
* @return boolean the new value added to the column in public.tbl_person
*/
public function foto_sperre_function($value)
{
$res = $this->PersonModel->update($this->pid, ["foto_sperre" => $value]);
if (isError($res)) {
show_error("error while trying to update table public.tbl_person");
}
$this->PersonModel->addSelect("foto_sperre");
$res = $this->PersonModel->load($this->pid);
if (isError($res)) {
show_error("error while trying to query table public.tbl_person");
}
$res = hasData($res) ? getData($res)[0] : null;
echo json_encode($res);
}
/**
* gets all nations in the table bis.tbl_nation
*
* @access public
* @return array all the nations in table bis.tbl_nation
*/
public function getAllNationen()
{
$this->load->model('codex/Nation_model', "NationModel");
$this->NationModel->addSelect(["nation_code as code", "langtext"]);
$nation_res = $this->NationModel->load();
if (isError($nation_res)) {
show_error("error while trying to query table codex.tbl_nation");
}
$nation_res = hasData($nation_res) ? getData($nation_res) : null;
echo json_encode($nation_res);
}
/**
* gets specific gemeinden which are related to the ZIP and the Nation passed in the body of the get request
* @access public
* @var $_GET function uses GET request payload
* @return boolean the new value added to the column in public.tbl_person
*/
public function getGemeinden()
{
/** @var $nation value parsed out of the body of the get request */
$nation = $this->input->get('nation', true);
/** @var $zip value parsed out of the body of the get request and converted to a php integer with json_decode */
$zip = json_decode($this->input->get('zip', true));
$this->load->model('codex/Gemeinde_model', "GemeindeModel");
$this->GemeindeModel->addDistinct();
$this->GemeindeModel->addSelect(["name"]);
if ($nation == "A") {
if (isset($zip) && $zip > 999 && $zip < 32000) {
$gemeinde_res = $this->GemeindeModel->loadWhere(['plz' => $zip]);
if (isError($gemeinde_res)) {
show_error("error while trying to query bis.tbl_gemeinde");
}
$gemeinde_res = hasData($gemeinde_res) ? getData($gemeinde_res) : null;
$gemeinde_res = array_map(function ($obj) {
return $obj->name;
}, $gemeinde_res);
echo json_encode($gemeinde_res);
} else {
echo json_encode(error("ortschaftskennziffer code was not valid"));
}
} else {
echo json_encode(error("Nation was not 'A' (Austria)"));
}
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
/**
* function that returns the data used for viewing another mitarbeiter profile
* @access private
* @param integer $uid the userID to retrieve the mitarbeiter data
* @return stdClass restricted mitarbeiter data
*/
private function viewMitarbeiterProfil($uid)
{
$mailverteiler_res = $this->getMailverteiler($uid);
$benutzer_funktion_res = $this->getBenutzerFunktion($uid);
$benutzer_res = $this->getBenutzerAlias($uid);
$person_res = $this->getPersonInfo($uid);
$mitarbeiter_res = $this->getMitarbeiterInfo($uid);
$telefon_res = $this->getTelefonInfo($uid);
$res = new stdClass();
$res->username = $uid;
//? Person Info
foreach ($person_res as $key => $val) {
$res->$key = $val;
}
//? Mitarbeiter Info
foreach ($mitarbeiter_res as $key => $val) {
$res->$key = $val;
}
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $uid . "@" . DOMAIN;
$extern_email = array();
$extern_email["type"] = "alias";
$extern_email["email"] = $benutzer_res->alias . "@" . DOMAIN;
$res->emails = array($intern_email, $extern_email);
$res->funktionen = $benutzer_funktion_res;
$res->mailverteiler = $mailverteiler_res;
$res->standort_telefon = isset($telefon_res) ? $telefon_res->kontakt : null;
return $res;
}
/**
* function that returns the data used for viewing another student profile
* @access private
* @param integer $uid the userID to retrieve the student data
* @return stdClass restricted student data
*/
private function viewStudentProfil($uid)
{
$mailverteiler_res = $this->getMailverteiler($uid);
$person_res = $this->getPersonInfo($uid);
$student_res = $this->getStudentInfo($uid);
$matr_res = $this->getMatrikelNummer($uid);
$res = new stdClass();
$res->username = $uid;
//? Person Information
foreach ($person_res as $key => $value) {
$res->$key = $value;
}
//? Student Information
foreach ($student_res as $key => $value) {
$res->$key = $value;
}
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $uid . "@" . DOMAIN;
$res->emails = [$intern_email];
$res->matrikelnummer = $matr_res->matr_nr;
$res->mailverteiler = $mailverteiler_res;
return $res;
}
/**
* function that returns the data used for the mitarbeiter profile
* @access private
* @return stdClass mitarbeiter data
*/
private function mitarbeiterProfil()
{
$zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid);
$adresse_res = $this->getAdressenInfo($this->pid);
$kontakte_res = $this->getKontaktInfo($this->pid);
$mailverteiler_res = $this->getMailverteiler($this->uid);
$person_res = $this->getPersonInfo($this->uid, true);
$benutzer_funktion_res = $this->getBenutzerFunktion($this->uid);
$betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid);
$profilUpdates = $this->getProfilUpdates($this->uid);
$telefon_res = $this->getTelefonInfo($this->uid);
$mitarbeiter_res = $this->getMitarbeiterInfo($this->uid);
$res = new stdClass();
$res->username = $this->uid;
//? Person Information
foreach ($person_res as $key => $value) {
$res->$key = $value;
}
//? Mitarbeiter Information
foreach ($mitarbeiter_res as $key => $value) {
$res->$key = $value;
}
$res->adressen = $adresse_res;
$res->zutrittsdatum = $zutrittskarte_ausgegebenam;
$res->kontakte = $kontakte_res;
$res->mittel = $betriebsmittelperson_res;
$res->mailverteiler = $mailverteiler_res;
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $this->uid . "@" . DOMAIN;
$extern_email = array();
$extern_email["type"] = "alias";
$extern_email["email"] = $mitarbeiter_res->alias . "@" . DOMAIN;
$res->emails = [$intern_email, $extern_email];
$res->funktionen = $benutzer_funktion_res;
$res->standort_telefon = $telefon_res;
$res->profilUpdates = $profilUpdates;
return $res;
}
/**
* function that returns the data used for the student profile
* @access private
* @return stdClass student data
*/
private function studentProfil()
{
$betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid);
$kontakte_res = $this->getKontaktInfo($this->pid);
$zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid);
$adresse_res = $this->getAdressenInfo($this->pid);
$mailverteiler_res = $this->getMailverteiler($this->uid);
$person_res = $this->getPersonInfo($this->uid, true);
$zutrittsgruppe_res = $this->getZutrittsgruppen($this->uid);
$student_res = $this->getStudentInfo($this->uid);
$matr_res = $this->getMatrikelNummer($this->uid);
$profilUpdates = $this->getProfilUpdates($this->uid);
$res = new stdClass();
$res->username = $this->uid;
//? Person Information
foreach ($person_res as $key => $value) {
$res->$key = $value;
}
//? Student Information
foreach ($student_res as $key => $value) {
$res->$key = trim($value);
}
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $this->uid . "@" . DOMAIN;
$res->emails = [$intern_email];
$res->adressen = $adresse_res;
$res->zutrittsdatum = $zutrittskarte_ausgegebenam;
$res->kontakte = $kontakte_res;
$res->mittel = $betriebsmittelperson_res;
$res->matrikelnummer = $matr_res->matr_nr;
$res->zuttritsgruppen = $zutrittsgruppe_res;
$res->mailverteiler = $mailverteiler_res;
$res->profilUpdates = $profilUpdates;
return $res;
}
/**
* gets all the mailverteiler using the tables: tbl_benutzer, tbl_benutzergruppe, tbl_gruppe
* @access private
* @param integer $uid the userID used to retrieve the mailverteiler
* @return array returns the mailvertailer corresponding to a userID
*/
private function getMailverteiler($uid)
{
$this->PersonModel->addSelect('gruppe_kurzbz, beschreibung');
$this->PersonModel->addJoin('tbl_benutzer', 'person_id');
$this->PersonModel->addJoin('tbl_benutzergruppe', 'uid');
$this->PersonModel->addJoin('tbl_gruppe', 'gruppe_kurzbz');
$mailverteiler_res = $this->PersonModel->loadWhere(array('mailgrp' => true, 'uid' => $uid));
if (isError($mailverteiler_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($mailverteiler_res));
}
$mailverteiler_res = hasData($mailverteiler_res) ? getData($mailverteiler_res) : null;
$mailverteiler_res = array_map(function ($element) {
$element->mailto = "mailto:" . $element->gruppe_kurzbz . "@" . DOMAIN;
return $element;
}, $mailverteiler_res);
return $mailverteiler_res;
}
/**
* gets all the Benutzerfunktionen of a corresponding user
* @access private
* @param integer $uid the userID used to retrieve the Benutzerfunktionen
* @return array returns the Benutzerfunktionen corresponding to a userID
*/
private function getBenutzerFunktion($uid)
{
$this->BenutzerfunktionModel->addSelect(["tbl_benutzerfunktion.bezeichnung as Bezeichnung", "tbl_organisationseinheit.bezeichnung as Organisationseinheit", "datum_von as Gültig_von", "datum_bis as Gültig_bis", "wochenstunden as Wochenstunden"]);
$this->BenutzerfunktionModel->addJoin("tbl_organisationseinheit", "oe_kurzbz");
$benutzer_funktion_res = $this->BenutzerfunktionModel->loadWhere(array('uid' => $uid));
if (isError($benutzer_funktion_res)) {
show_error("was not able to query the table public.tbl_benutzerfunktion:" . getData($benutzer_funktion_res));
}
$benutzer_funktion_res = hasData($benutzer_funktion_res) ? getData($benutzer_funktion_res) : null;
return $benutzer_funktion_res;
}
/**
* gets all the Betriebsmittel of a corresponding user
* @access private
* @param integer $uid the userID used to retrieve the Betriebsmittel
* @return array returns the Betriebsmittel corresponding to a userID
*/
private function getBetriebsmittelInfo($pid)
{
$this->BetriebsmittelpersonModel->addSelect(["CONCAT(betriebsmitteltyp, ' ' ,beschreibung) as Betriebsmittel", "nummer as Nummer", "ausgegebenam as Ausgegeben_am"]);
//? betriebsmittel are not needed in a view
$betriebsmittelperson_res = $this->BetriebsmittelpersonModel->getBetriebsmittel($pid);
if (isError($betriebsmittelperson_res)) {
show_error("was not able to query the table public.tbl_betriebsmittelperson:" . getData($betriebsmittelperson_res));
}
$betriebsmittelperson_res = hasData($betriebsmittelperson_res) ? getData($betriebsmittelperson_res) : null;
return $betriebsmittelperson_res;
}
/**
* gets the alias of a corresponding user
* @access private
* @param integer $uid the userID used to get the alias
* @return string the alias of the userID
*/
private function getBenutzerAlias($uid)
{
$this->BenutzerModel->addSelect(["alias"]);
$benutzer_res = $this->BenutzerModel->load([$uid]);
if (isError($benutzer_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($benutzer_res));
} else {
$benutzer_res = hasData($benutzer_res) ? getData($benutzer_res)[0] : null;
}
return $benutzer_res;
}
/**
* gets the person information corresponding to a user
* @access private
* @param integer $uid the userID used to get the person information
* @param integer $geburtsInfo flag wether to add the columns gebort, gebdatum, foto_sperre or not
* @return array all the person informaion corresponding to a userID
*/
private function getPersonInfo($uid, $geburtsInfo = null)
{
$selectClause = ["foto", "anrede", "titelpost as postnomen", "titelpre as titel", "vorname", "nachname"];
/** @param integer $geburtsInfo */
if ($geburtsInfo) {
array_push($selectClause, "gebort");
array_push($selectClause, "gebdatum");
array_push($selectClause, "foto_sperre");
}
$this->BenutzerModel->addSelect($selectClause);
$this->BenutzerModel->addJoin("tbl_person", "person_id");
$person_res = $this->BenutzerModel->load([$uid]);
if (isError($person_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($person_res));
} else {
$person_res = hasData($person_res) ? getData($person_res)[0] : null;
}
return $person_res;
}
/**
* gets the mitarbeiter information corresponding to a user
* @access private
* @param integer $uid the userID used to get the mitarbeiter information
* @return array all the mitarbeiter informaion corresponding to a userID
*/
private function getMitarbeiterInfo($uid)
{
$this->MitarbeiterModel->addSelect(["kurzbz", "telefonklappe", "alias", "ort_kurzbz"]);
$this->MitarbeiterModel->addJoin("tbl_benutzer", "tbl_benutzer.uid = tbl_mitarbeiter.mitarbeiter_uid");
$mitarbeiter_res = $this->MitarbeiterModel->load($uid);
if (isError($mitarbeiter_res)) {
show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($mitarbeiter_res));
} else {
$mitarbeiter_res = hasData($mitarbeiter_res) ? getData($mitarbeiter_res)[0] : null;
}
return $mitarbeiter_res;
}
/**
* gets the telefon information corresponding to a user
* @access private
* @param integer $uid the userID used to get the telefon information
* @return array all the telefon informaion corresponding to a userID
*/
private function getTelefonInfo($uid)
{
$this->MitarbeiterModel->addSelect(["kontakt"]);
$this->MitarbeiterModel->addJoin("tbl_kontakt", "tbl_mitarbeiter.standort_id = tbl_kontakt.standort_id");
$this->MitarbeiterModel->addLimit(1);
$telefon_res = $this->MitarbeiterModel->loadWhere(["mitarbeiter_uid" => $uid, "kontakttyp" => "telefon"]);
if (isError($telefon_res)) {
show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($telefon_res));
}
$telefon_res = hasData($telefon_res) ? getData($telefon_res)[0] : null;
return $telefon_res;
}
/**
* gets the student information corresponding to a user
* @access private
* @param integer $uid the userID used to get the student information
* @return array all the student informaion corresponding to a userID
*/
private function getStudentInfo($uid)
{
$this->StudentModel->addSelect(['tbl_studiengang.bezeichnung as studiengang', 'tbl_student.semester', 'tbl_student.verband', 'tbl_student.gruppe', 'tbl_student.matrikelnr as personenkennzeichen']);
$this->StudentModel->addJoin('tbl_studiengang', "tbl_studiengang.studiengang_kz=tbl_student.studiengang_kz");
$student_res = $this->StudentModel->load([$uid]);
if (isError($student_res)) {
show_error("was not able to query the table public.tbl_student:" . getData($student_res));
}
$student_res = hasData($student_res) ? getData($student_res)[0] : null;
return $student_res;
}
/**
* gets the profil updates corresponding to a user
* @access private
* @param integer $uid the userID used to get the profil updates
* @return array all the profil updates corresponding to a userID
*/
private function getProfilUpdates($uid)
{
$profilUpdates = $this->ProfilUpdateModel->getProfilUpdatesWhere(['uid' => $uid]);
if (isError($profilUpdates)) {
show_error("was not able to query the table public.tbl_profil_update:" . getData($profilUpdates));
}
$profilUpdates = hasData($profilUpdates) ? getData($profilUpdates) : null;
return $profilUpdates;
}
/**
* gets the Matrikelnummer corresponding to a user
* @access private
* @param integer $uid the userID used to get the Matrikelnummer
* @return integer the Matrikelnummer corresponding to a userID
*/
private function getMatrikelNummer($uid)
{
$this->BenutzerModel->addSelect(["matr_nr"]);
$this->BenutzerModel->addJoin("tbl_person", "person_id");
$matr_res = $this->BenutzerModel->load([$uid]);
if (isError($matr_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($matr_res));
}
$matr_res = hasData($matr_res) ? getData($matr_res)[0] : [];
return $matr_res;
}
/**
* gets the Zutrittsgruppen corresponding to a user
* @access private
* @param integer $uid the userID used to get the Zutrittsgruppen
* @return array all the Zutrittsgruppen corresponding to a userID
*/
private function getZutrittsgruppen($uid)
{
$this->BenutzergruppeModel->addSelect(['bezeichnung']);
$this->BenutzergruppeModel->addJoin('tbl_gruppe', 'gruppe_kurzbz');
$zutrittsgruppe_res = $this->BenutzergruppeModel->loadWhere(array("uid" => $uid, "zutrittssystem" => true));
if (isError($zutrittsgruppe_res)) {
show_error("was not able to query the table public.tbl_benutzergruppe:" . getData($zutrittsgruppe_res));
}
$zutrittsgruppe_res = hasData($zutrittsgruppe_res) ? getData($zutrittsgruppe_res) : null;
return $zutrittsgruppe_res;
}
/**
* gets the address information corresponding to a user
* @access private
* @param integer $uid the userID used to get the address information
* @return array all the address information corresponding to a userID
*/
private function getAdressenInfo($pid)
{
$adresse_res = $this->AdresseModel->addSelect(["adresse_id", "strasse", "tbl_adressentyp.bezeichnung as typ", "plz", "ort", "zustelladresse", "gemeinde", "nation"]);
$adresse_res = $this->AdresseModel->addOrder("zustelladresse", "DESC");
$adresse_res = $this->AdresseModel->addJoin("tbl_adressentyp", "typ=adressentyp_kurzbz");
$adresse_res = $this->AdresseModel->loadWhere(["person_id" => $pid]);
if (isError($adresse_res)) {
show_error("was not able to query the table public.tbl_adresse:" . getData($adresse_res));
}
$adresse_res = hasData($adresse_res) ? getData($adresse_res) : null;
return $adresse_res;
}
/**
* gets the kontakt information corresponding to a user
* @access private
* @param integer $uid the userID used to get the kontakt information
* @return array all the kontakt information corresponding to a userID
*/
private function getKontaktInfo($pid)
{
$this->KontaktModel->addSelect(['kontakttyp', 'kontakt_id', 'kontakt', 'tbl_kontakt.anmerkung', 'tbl_kontakt.zustellung']);
$this->KontaktModel->addJoin('public.tbl_standort', 'standort_id', 'LEFT');
$this->KontaktModel->addJoin('public.tbl_firma', 'firma_id', 'LEFT');
$this->KontaktModel->addOrder('kontakttyp, kontakt, tbl_kontakt.updateamum, tbl_kontakt.insertamum');
$kontakte_res = $this->KontaktModel->loadWhere(['person_id' => $pid]);
if (isError($kontakte_res)) {
show_error("was not able to query the table public.tbl_kontakt:" . getData($kontakte_res));
}
$kontakte_res = hasData($kontakte_res) ? getData($kontakte_res) : null;
return $kontakte_res;
}
/**
* gets the date of issue of the FH access card corresponding to a user
* @access private
* @param integer $uid the userID used to get the date of issue of the FH access card
* @return string the date of issue of the FH access card corresponding to a userID
*/
private function getZutrittskarteDatum($uid)
{
$zutrittskarte_ausgegebenam = $this->BetriebsmittelpersonModel->getBetriebsmittelByUid($uid, "Zutrittskarte");
if (isError($zutrittskarte_ausgegebenam)) {
show_error("was not able to query the table wavi.tbl_bentriebsmittelperson:" . getData($zutrittskarte_ausgegebenam));
}
$zutrittskarte_ausgegebenam = hasData($zutrittskarte_ausgegebenam) ? getData($zutrittskarte_ausgegebenam)[0]->ausgegebenam : null;
//? formats date from 01-01-2000 to 01.01.2000
$zutrittskarte_ausgegebenam = str_replace("-", ".", $zutrittskarte_ausgegebenam);
return $zutrittskarte_ausgegebenam;
}
}
@@ -0,0 +1,814 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
/**
*
*/
class ProfilUpdate extends Auth_Controller
{
public static $STATUS_PENDING = NULL;
public static $STATUS_ACCEPTED = NULL;
public static $STATUS_REJECTED = NULL;
public static $TOPICS = [];
public function __construct()
{
parent::__construct([
'index' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'],
'id' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'],
'getProfilUpdateWithPermission' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'],
'acceptProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'],
'denyProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'],
'show' => ['basis/cis:r'],
'insertProfilRequest' => ['basis/cis:rw'],
'updateProfilRequest' => ['basis/cis:rw'],
'deleteProfilRequest' => ['basis/cis:rw'],
'selectProfilRequest' => ['basis/cis:r'],
'insertFile' => ['basis/cis:rw'],
'getProfilRequestFiles' => ['basis/cis:r'],
'getStatus' => ['basis/cis:r'],
'getTopic' => ['basis/cis:r'],
]);
$this->load->config('cis');
$this->load->model('person/Profil_update_model', 'ProfilUpdateModel');
$this->load->model('person/Kontakt_model', 'KontaktModel');
$this->load->model('person/Adresse_model', 'AdresseModel');
$this->load->model('person/Adressentyp_model', 'AdressenTypModel');
$this->load->model('person/Person_model', 'PersonModel');
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('system/Sprache_model', 'SpracheModel');
$this->load->model('person/Profil_update_status_model', 'ProfilUpdateStatusModel');
$this->load->model('person/Profil_update_topic_model', 'ProfilUpdateTopicModel');
// Load language phrases
$this->loadPhrases(
array(
'ui',
'global',
'person',
'profil',
'profilUpdate'
)
);
$this->load->library('DmsLib');
$this->load->library('PermissionLib');
//? put the uid and pid inside the controller for reusability
$this->uid = getAuthUID();
$this->pid = getAuthPersonID();
// setup the ProfilUpdate states
$this->ProfilUpdateStatusModel->addSelect(['status_kurzbz']);
$status_kurzbz = $this->ProfilUpdateStatusModel->load();
if (hasData($status_kurzbz)) {
list($status_pending, $status_accepted, $status_rejected) = getData($status_kurzbz);
self::$STATUS_PENDING = $status_pending->status_kurzbz;
self::$STATUS_ACCEPTED = $status_accepted->status_kurzbz;
self::$STATUS_REJECTED = $status_rejected->status_kurzbz;
}
// setup the ProfilUpdate topics
$this->ProfilUpdateTopicModel->addSelect(['topic_kurzbz']);
$topic_kurzbz = $this->ProfilUpdateTopicModel->load();
if (hasData($topic_kurzbz)) {
foreach (getData($topic_kurzbz) as $topic) {
self::$TOPICS[$topic->topic_kurzbz] = $topic->topic_kurzbz;
}
}
}
public function index()
{
$this->load->view('Cis/ProfilUpdate');
}
public function id($profil_update_id = null)
{
$this->load->view('Cis/ProfilUpdate', ['profil_update_id' => $profil_update_id]);
}
public function getStatus()
{
echo json_encode([self::$STATUS_PENDING => self::$STATUS_PENDING, self::$STATUS_ACCEPTED => self::$STATUS_ACCEPTED, self::$STATUS_REJECTED => self::$STATUS_REJECTED]);
}
public function getTopic()
{
echo json_encode(self::$TOPICS);
}
private function sendEmail_onProfilUpdate_response($uid, $topic, $status)
{
if($this->config->item('cis_send_profil_update_mails') === false)
{
return;
}
$this->load->helper('hlp_sancho_helper');
$email = $uid . "@" . DOMAIN;
function languageQuery($language)
{
return "select index from public.tbl_sprache where sprache = '" + $language + "'";
}
$this->ProfilUpdateStatusModel->addSelect(["bezeichnung_mehrsprachig[(" . languageQuery('German') . ")] as status_de", "bezeichnung_mehrsprachig[(" . languageQuery('English') . ")] as status_en"]);
$status_translation = $this->ProfilUpdateStatusModel->loadWhere(["status_kurzbz" => $status]);
if (isError($status_translation)) {
show_error($this->p->t('profilUpdate', 'ProfilUpdateStatusTranslationError'));
}
$status_translation = hasData($status_translation) ? getData($status_translation)[0] : null;
if (isset($status_translation)) {
$mail_res = sendSanchoMail("profil_update_response", ['topic' => $topic, 'status_de' => $status_translation->status_de, 'status_en' => $status_translation->status_en, 'href' => APP_ROOT . 'Cis/Profil'], $email, ("Profil Änderung " . $this->p->t('profilUpdate', 'pending')));
if (!$mail_res) {
show_error($this->p->t('profilUpdate', 'profilUpdate_email_error'));
}
}
}
private function sendEmail_onProfilUpdate_insertion($uid, $profil_update_id, $topic)
{
if($this->config->item('cis_send_profil_update_mails') === false)
{
return;
}
$this->load->helper('hlp_sancho_helper');
$emails = [];
$isMitarbeiter_res = $this->MitarbeiterModel->isMitarbeiter($uid);
if (isError($isMitarbeiter_res)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error'));
}
$isMitarbeiter_res = getData($isMitarbeiter_res);
//! if the $uid is a mitarbeiter and student, only the hr is notified by email
if ($isMitarbeiter_res) {
//? user is not a student therefore he is a mitarbeiter, send email to Personalverwaltung
//? use constant variable MAIL_GST to mail to the personalverwaltung
$this->MitarbeiterModel->addSelect([TRUE]);
$this->MitarbeiterModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid");
//? check if the the userID is a mitarbeiter and if the benutzer is active
$res = $this->MitarbeiterModel->loadWhere(["public.tbl_mitarbeiter.mitarbeiter_uid" => $uid, "public.tbl_benutzer.aktiv" => TRUE]);
if (isError($res)) {
show_error("was not able to query the mitarbeiter and benutzer by the uid: " . $uid);
}
if (hasData($res)) {
array_push($emails, MAIL_GST);
} else {
show_error($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error'));
}
} else {
//? if it is not a mitarbeiter, check whether it is a student and send email to studiengang
$isStudent_res = $this->StudentModel->isStudent($uid);
if (isError($isStudent_res)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_studentCheck_error'));
}
$isStudent_res = getData($isStudent_res);
if ($isStudent_res) {
//? Send email to the Studiengangsassistentinnen
$this->StudentModel->addSelect(["public.tbl_studiengang.email"]);
$this->StudentModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_student.student_uid");
$this->StudentModel->addJoin("public.tbl_prestudent", "public.tbl_benutzer.person_id = public.tbl_prestudent.person_id");
$this->StudentModel->addJoin("public.tbl_prestudentstatus", "public.tbl_prestudentstatus.prestudent_id = public.tbl_prestudent.prestudent_id");
$this->StudentModel->addJoin("public.tbl_studiengang", "public.tbl_studiengang.studiengang_kz = public.tbl_prestudent.studiengang_kz");
//* check if the benutzer itself is active
//* check if the student status is Student or Diplomand (active students)
$this->StudentModel->db->where_in("public.tbl_prestudentstatus.status_kurzbz", ['Student', 'Diplomand']);
$res = $this->StudentModel->loadWhere(["public.tbl_benutzer.aktiv" => TRUE, "public.tbl_student.student_uid" => $uid]);
if (isError($res)) {
show_error(getData($res));
} else {
$res = hasData($res) ? getData($res) : [];
foreach ($res as $emailObj) {
array_push($emails, $emailObj->email);
}
}
}
}
$mail_res = [];
//? sending email
foreach ($emails as $email) {
array_push($mail_res, sendSanchoMail("profil_update", ['uid' => $uid, 'topic' => $topic, 'href' => APP_ROOT . 'Cis/ProfilUpdate/id/' . $profil_update_id], $email, ("Profil Änderung von " . $uid)));
}
foreach ($mail_res as $m_res) {
if (!$m_res) {
show_error($this->p->t('profilUpdate', 'profilUpdate_email_error'));
}
}
}
public function show($dms_id)
{
$profil_update = $this->ProfilUpdateModel->loadWhere(['attachment_id' => $dms_id]);
$profil_update = hasData($profil_update) ? getData($profil_update)[0] : null;
//? checks if an profil update exists with the dms_id requested from the user
if ($profil_update) {
$is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($profil_update->uid));
$is_student_profil_update = getData($this->StudentModel->isStudent($profil_update->uid));
if (
$this->permissionlib->isBerechtigt('student/stammdaten:r') && $is_student_profil_update ||
$this->permissionlib->isBerechtigt('mitarbeiter/stammdaten:r') && $is_mitarbeiter_profil_update ||
$this->uid == $profil_update->uid
) {
// Get file to be downloaded from DMS
$newFilename = $this->uid . "/document_" . $dms_id;
$download = $this->dmslib->download($dms_id);
if (isError($download))
return $download;
// Download file
$this->outputFile(getData($download));
} else {
show_error($this->p->t('profilUpdate', 'profilUpdate_permission_error'));
return;
}
} else {
show_error($this->p->t('profilUpdate', 'profilUpdate_dms_error'));
return;
}
}
public function insertFile($replace)
{
$replace = json_decode($replace);
if (!count($_FILES)) {
echo json_encode([]);
return;
}
//? if replace is set it contains the profil_update_id in which the attachment_id has to be replaced
if (isset($replace)) {
$this->ProfilUpdateModel->addSelect(["attachment_id"]);
$profilUpdate = $this->ProfilUpdateModel->load([$replace]);
if (isError($profilUpdate)) {
return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_loading_error')));
}
//? get the attachmentID
$dms_id = hasData($profilUpdate) ? getData($profilUpdate)[0]->attachment_id : null;
//? delete old dms_file of Profil Update
$this->deleteOldVersionFile($dms_id);
}
$files = $_FILES['files'];
$file_count = count($files['name']);
$res = [];
for ($i = 0; $i < $file_count; $i++) {
$_FILES['files']['name'] = $files['name'][$i];
$_FILES['files']['type'] = $files['type'][$i];
$_FILES['files']['tmp_name'] = $files['tmp_name'][$i];
$_FILES['files']['error'] = $files['error'][$i];
$_FILES['files']['size'] = $files['size'][$i];
$dms = [
"kategorie_kurzbz" => "profil_aenderung",
"version" => 0,
"name" => $_FILES['files']['name'],
"mimetype" => $_FILES['files']['type'],
"beschreibung" => $this->uid . " Profil Änderung",
"insertvon" => $this->uid,
"insertamum" => "NOW()",
];
$tmp_res = $this->dmslib->upload($dms, 'files', array("jpg", "png", "pdf"));
$tmp_res = hasData($tmp_res) ? getData($tmp_res) : null;
array_push($res, $tmp_res);
}
echo json_encode($res);
}
public function selectProfilRequest()
{
$_GET = json_decode($this->input->raw_input_stream, true);
$uid = $this->input->get('uid');
$id = $this->input->get('id');
$whereClause = ['uid' => $this->uid];
if (isset($uid))
$whereClause['uid'] = $uid;
if (isset($id))
$whereClause['id'] = $id;
$res = $this->ProfilUpdateModel->getProfilUpdatesWhere($whereClause);
$res = hasData($res) ? getData($res) : null;
echo json_encode($res);
}
public function getProfilRequestFiles()
{
$id = json_decode($this->input->raw_input_stream);
$this->ProfilUpdateModel->addSelect(["attachment_id"]);
$attachmentID = $this->ProfilUpdateModel->load([$id]);
if (isError($attachmentID)) {
return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_loading_error')));
}
//? get the attachmentID
$dms_id = hasData($attachmentID) ? getData($attachmentID)[0]->attachment_id : null;
//? get the name to the file
$this->DmsVersionModel->addSelect(["name", "dms_id"]);
$attachment = $this->DmsVersionModel->load([$dms_id, 0]);
if (isError($attachment)) {
return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_dmsVersion_error')));
}
$attachment = hasData($attachment) ? getData($attachment) : null;
//? returns {name:..., dms_id:...}
echo json_encode($attachment);
}
public function insertProfilRequest()
{
$json = json_decode($this->input->raw_input_stream);
$payload = $json->payload;
$identifier = property_exists($json->payload, "kontakt_id") ? "kontakt_id" : (property_exists($json->payload, "adresse_id") ? "adresse_id" : null);
$data = ["topic" => $json->topic, "uid" => $this->uid, "requested_change" => json_encode($payload), "insertamum" => "NOW()", "insertvon" => $this->uid, "status" => self::$STATUS_PENDING ?: 'Pending'];
//? insert fileID in the dataset if sent with post request
if (isset($json->fileID)) {
$data['attachment_id'] = $json->fileID;
}
//? loops over all updateRequests from a user to validate if the new request is valid
$res = $this->ProfilUpdateModel->getProfilUpdatesWhere(["uid" => $this->uid]);
if (isError($res)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_loading_error'));
}
$res = hasData($res) ? getData($res) : null;
//? the user cannot delete a zustelladresse/kontakt
if (isset($payload->delete) && $payload->{$identifier == "kontakt_id" ? "zustellung" : "zustelladresse"}) {
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error')));
return;
}
//? if the user tries to delete a adresse, checks whether the adresse is a heimatadresse, if so an error is raised
if (isset($payload->delete) && $identifier == "adresse_id") {
$adr = $this->AdresseModel->load($payload->$identifier);
$adr = getData($adr)[0];
if ($adr->heimatadresse) {
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error')));
return;
}
}
if ($res) {
$pending_changes = array_filter($res, function ($element) {
return $element->status == (self::$STATUS_PENDING ?: "Pending");
});
foreach ($pending_changes as $update_request) {
$existing_change = $update_request->requested_change;
//? the user can add as many new kontakte/adressen as he likes
if (!isset($payload->add) && property_exists($existing_change, $identifier) && property_exists($payload, $identifier) && $existing_change->$identifier == $payload->$identifier) {
//? the kontakt_id / adresse_id of a change has to be unique
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_changeTwice_error')));
return;
}
//? if it is not updating any kontakt/adresse, the topic has to be unique
elseif (!$identifier && $update_request->topic == $json->topic) {
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_changeTopicTwice_error', ['0' => $update_request->topic])));
return;
}
}
}
$insertID = $this->ProfilUpdateModel->insert($data);
if (isError($insertID)) {
show_error(getData($insertID));
} else {
$insertID = hasData($insertID) ? getData($insertID) : null;
//? sends emails to the correspondents of the $uid
$this->sendEmail_onProfilUpdate_insertion($this->uid, $insertID, $json->topic);
echo json_encode(success($insertID));
}
}
public function updateProfilRequest()
{
$json = json_decode($this->input->raw_input_stream);
$updateData = ["requested_change" => json_encode($json->payload), "updateamum" => "NOW()", "updatevon" => $this->uid];
if (isset($json->fileID)) {
$updateData['attachment_id'] = json_decode($json->fileID);
}
$updateID = $this->ProfilUpdateModel->update([$json->ID], $updateData);
//? insert fileID in the dataset if sent with post request
if (isError($updateID)) {
//catch error
} else {
$updateID = hasData($updateID) ? getData($updateID)[0] : null;
//TODO: should an email be sent to the responsable people when the user changes his profil update
echo json_encode(success($updateID));
}
}
public function deleteProfilRequest()
{
$json = json_decode($this->input->raw_input_stream);
$delete_res = $this->ProfilUpdateModel->delete([$json]);
echo json_encode($delete_res);
}
public function getProfilUpdateWithPermission($status = null)
{
// early return if no status has been passed as argument
if (!isset($status)) {
echo json_encode($this->ProfilUpdateModel->getProfilUpdateWithPermission());
return;
}
// get the sprache of the user
$sprachenIndex = $this->SpracheModel->loadWhere(["sprache" => getUserLanguage()]);
$sprachenIndex = hasData($sprachenIndex) ? getData($sprachenIndex)[0]->index : null;
if (isset($sprachenIndex) && isset($status)) {
// get the corresponding status kurz_bz primary key out of the translation
$status = $this->ProfilUpdateStatusModel->execReadOnlyQuery("select * from public.tbl_profil_update_status where ? = ANY(bezeichnung_mehrsprachig)", [$status]);
$status = hasData($status) ? getData($status)[0]->status_kurzbz : null;
$res = $this->ProfilUpdateModel->getProfilUpdateWithPermission(isset($status) ? ['status' => $status] : null);
echo json_encode($res);
}
}
private function getOE_from_student($student_uid)
{
//? returns the oe_einheit eines Studenten
$query = "SELECT public.tbl_studiengang.oe_kurzbz
FROM public.tbl_student
JOIN public.tbl_studiengang ON tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz
WHERE public.tbl_student.student_uid = ?;";
$res = $this->StudentModel->execReadOnlyQuery($query, [$student_uid]);
if (!isSuccess($res)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_loadingOE_error'));
}
$res = hasData($res) ? getData($res) : [];
$res = array_map(
function ($item) {
return $item->oe_kurzbz;
},
$res
);
return $res;
}
public function acceptProfilRequest()
{
$_POST = json_decode($this->input->raw_input_stream, true);
$id = $this->input->post('profil_update_id', true);
$uid = $this->input->post('uid', true);
//? fetching person_id using UID
$personID = $this->PersonModel->getByUid($uid);
$personID = hasData($personID) ? getData($personID)[0]->person_id : null;
$status_message = $this->input->post('status_message', true);
$topic = $this->input->post('topic', true);
//! somehow the xss check converted boolean false to empty string
$requested_change = $this->input->post('requested_change');
//! check for required information
if (!isset($id) || !isset($uid) || !isset($personID) || !isset($requested_change) || !isset($topic)) {
return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_requiredInformation_error')));
}
$is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($uid));
$is_student_profil_update = getData($this->StudentModel->isStudent($uid));
//? check if the permissions are set correctly
if (
$this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) && $is_student_profil_update ||
$this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid") && $is_mitarbeiter_profil_update
) {
if (is_array($requested_change) && array_key_exists("adresse_id", $requested_change)) {
$insertID = $this->handleAdresse($requested_change, $personID);
$insertID = hasData($insertID) ? getData($insertID) : null;
if (isset($insertID)) {
$requested_change['adresse_id'] = $insertID;
$update_res = $this->updateRequestedChange($id, $requested_change);
if (isError($update_res)) {
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_address_error', [$insertID])));
return;
}
}
} else if (is_array($requested_change) && array_key_exists("kontakt_id", $requested_change)) {
$insertID = $this->handleKontakt($requested_change, $personID);
$insertID = hasData($insertID) ? getData($insertID) : null;
if (isset($insertID)) {
$requested_change['kontakt_id'] = $insertID;
$update_res = $this->updateRequestedChange($id, $requested_change);
if (isError($update_res)) {
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_kontakt_error', [$insertID])));
return;
}
}
} else {
switch ($topic) {
// mapping phrasen to database columns to make the update with the correct column names
case self::$TOPICS['Titel']:
$topic = "titelpre";
break;
case self::$TOPICS['Postnomen']:
$topic = "titelpost";
break;
case self::$TOPICS['Vorname']:
$topic = "vorname";
break;
case self::$TOPICS['Nachname']:
$topic = "nachname";
break;
default:
show_error($this->p->t('profilUpdate', 'profilUpdate_topic_error', [$topic]));
return;
}
$result = $this->PersonModel->update($personID, [$topic => $requested_change["value"]]);
if (isError($result)) {
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_insert_error')));
return;
}
}
$this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_ACCEPTED);
echo json_encode($this->setStatusOnUpdateRequest($id, self::$STATUS_ACCEPTED, $status_message, $requested_change));
} else {
show_error($this->p->t('profilUpdate', 'profilUpdate_permission_error'));
}
}
public function denyProfilRequest()
{
$_POST = json_decode($this->input->raw_input_stream, true);
$id = $this->input->post('profil_update_id', true);
$uid = $this->input->post('uid', true);
$topic = $this->input->post('topic', true);
$status_message = $this->input->post('status_message', true);
$is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($uid));
$is_student_profil_update = getData($this->StudentModel->isStudent($uid));
if (
$this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) && $is_student_profil_update ||
$this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid") && $is_mitarbeiter_profil_update
) {
$this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_REJECTED);
echo json_encode($this->setStatusOnUpdateRequest($id, self::$STATUS_REJECTED, $status_message));
} else {
show_error($this->p->t('profilUpdate', 'profilUpdate_permission_error'));
}
}
private function updateRequestedChange($id, $requested_change)
{
return $this->ProfilUpdateModel->update([$id], ['requested_change' => json_encode($requested_change)]);
}
private function setStatusOnUpdateRequest($id, $status, $status_message)
{
return $this->ProfilUpdateModel->update([$id], ["status" => $status, "status_timestamp" => "NOW()", "status_message" => $status_message]);
}
private function deleteOldVersionFile($dms_id)
{
if (!isset($dms_id)) {
return;
}
//? collect all the results of the deleted versions in an array
$res = array();
//? delete all the different versions of the dms_file
$dmsVersions = $this->DmsVersionModel->loadWhere(["dms_id" => $dms_id]);
$dmsVersions = hasData($dmsVersions) ? getData($dmsVersions) : null;
if (isset($dmsVersions)) {
$zwischen_res = array_map(function ($item) {
return $item->version;
}, $dmsVersions);
foreach ($zwischen_res as $version) {
array_push($res, $this->DmsVersionModel->delete([$dms_id, $version]));
}
} else {
echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_dmsVersion_error')));
}
//? returns a result for each deleted dms_file
return $res;
}
private function handleKontakt($requested_change, $personID)
{
$kontakt_id = $requested_change["kontakt_id"];
//? removes the kontakt_id because we don't want to update the kontakt_id in the database
unset($requested_change["kontakt_id"]);
//! ADD
if (array_key_exists('add', $requested_change) && $requested_change['add']) {
//? removes add flag
unset($requested_change['add']);
$requested_change['person_id'] = $personID;
$requested_change['insertamum'] = "NOW()";
$requested_change['insertvon'] = getAuthUID();
$insertID = $this->KontaktModel->insert($requested_change);
$insert_kontakt_id = $insertID;
if (isError($insert_kontakt_id)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_insertKontakt_error'));
}
$insert_kontakt_id = hasData($insert_kontakt_id) ? getData($insert_kontakt_id) : null;
if ($insert_kontakt_id) {
$this->handleDupplicateZustellKontakte($requested_change['zustellung'], $insert_kontakt_id);
}
}
//! DELETE
elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) {
$this->KontaktModel->delete($kontakt_id);
}
//! UPDATE
else {
$requested_change['updateamum'] = "NOW()";
$requested_change['updatevon'] = getAuthUID();
$update_kontakt_id = $this->KontaktModel->update($kontakt_id, $requested_change);
if (isError($update_kontakt_id)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_updateKontakt_error'));
}
$update_kontakt_id = hasData($update_kontakt_id) ? getData($update_kontakt_id) : null;
if ($update_kontakt_id) {
$this->handleDupplicateZustellKontakte($requested_change['zustellung'], $update_kontakt_id);
}
}
return isset($insertID) ? $insertID : null;
}
private function handleAdresse($requested_change, $personID)
{
$this->AdressenTypModel->addSelect(["adressentyp_kurzbz"]);
$adr_kurzbz = $this->AdressenTypModel->loadWhere(["bezeichnung" => $requested_change['typ']]);
$adr_kurzbz = hasData($adr_kurzbz) ? getData($adr_kurzbz)[0]->adressentyp_kurzbz : null;
//? replace the address_typ with its correct kurzbz foreign key
$requested_change['typ'] = $adr_kurzbz;
$adresse_id = $requested_change["adresse_id"];
//? removes the adresse_id because we don't want to update the kontakt_id in the database
unset($requested_change["adresse_id"]);
//! ADD
if (array_key_exists('add', $requested_change) && $requested_change['add']) {
//? removes add flag
unset($requested_change['add']);
$requested_change['insertamum'] = "NOW()";
$requested_change['insertvon'] = getAuthUID();
$requested_change['person_id'] = $personID;
//TODO: zustelladresse, heimatadresse, rechnungsadresse und nation werden nicht beachtet
$insertID = $this->AdresseModel->insert($requested_change);
$insert_adresse_id = $insertID;
if (isError($insert_adresse_id)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_insertAdresse_error'));
}
$insert_adresse_id = hasData($insert_adresse_id) ? getData($insert_adresse_id) : null;
if ($insert_adresse_id) {
$this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $insert_adresse_id);
}
}
//! DELETE
elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) {
$this->AdresseModel->delete($adresse_id);
}
//! UPDATE
else {
$requested_change['updateamum'] = "NOW()";
$requested_change['updatevon'] = getAuthUID();
$update_adresse_id = $this->AdresseModel->update($adresse_id, $requested_change);
if (isError($update_adresse_id)) {
show_error($this->p->t('profilUpdate', 'profilUpdate_updateAdresse_error'));
}
$update_adresse_id = hasData($update_adresse_id) ? getData($update_adresse_id) : null;
if ($update_adresse_id) {
$this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $update_adresse_id);
}
}
return isset($insertID) ? $insertID : null;
}
private function handleDupplicateZustellKontakte($zustellung, $kontakt_id)
{
if ($zustellung) {
$this->PersonModel->addSelect("public.tbl_kontakt.kontakt_id");
$this->PersonModel->addJoin("public.tbl_kontakt", "public.tbl_kontakt.person_id = public.tbl_person.person_id");
$zustellKontakteArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustellung" => TRUE]);
if (!isSuccess($zustellKontakteArray)) {
return error($this->p->t('profilUpdate', 'profilUpdate_loadingZustellkontakte_error'));
}
$zustellKontakteArray = hasData($zustellKontakteArray) ? getData($zustellKontakteArray) : null;
if ($zustellung && count($zustellKontakteArray) > 0) {
$zustellKontakteArray = array_filter($zustellKontakteArray, function ($kontakt) use ($kontakt_id) {
return $kontakt->kontakt_id != $kontakt_id;
});
foreach ($zustellKontakteArray as $kontakt) {
$this->KontaktModel->update($kontakt->kontakt_id, ["zustellung" => FALSE]);
}
}
}
}
private function handleDupplicateZustellAdressen($zustellung, $adresse_id)
{
if ($zustellung) {
$this->PersonModel->addSelect("public.tbl_adresse.adresse_id");
$this->PersonModel->addJoin("public.tbl_adresse", "public.tbl_adresse.person_id = public.tbl_person.person_id");
$zustellAdressenArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustelladresse" => TRUE]);
if (!isSuccess($zustellAdressenArray)) {
return error($this->p->t('profilUpdate', 'profilUpdate_loadingZustellAdressen_error'));
}
$zustellAdressenArray = hasData($zustellAdressenArray) ? getData($zustellAdressenArray) : null;
if ($zustellung && count($zustellAdressenArray) > 0) {
$zustellAdressenArray = array_filter($zustellAdressenArray, function ($adresse) use ($adresse_id) {
return $adresse->adresse_id != $adresse_id;
});
foreach ($zustellAdressenArray as $adresse) {
$this->AdresseModel->update($adresse->adresse_id, ["zustelladresse" => FALSE]);
}
}
}
}
}
+167
View File
@@ -0,0 +1,167 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Pub extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'bild' => ['basis/cis:r']
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @param string $source [person|akte]
* @param integer $id
* @return void
*/
public function bild($source, $id)
{
$this->load->model('person/Person_model', 'PersonModel');
$person_id_user = '';
$serverzugriff = false;
// Wenn das Bild direkt aufgerufen wird, ist eine Authentifizierung erforderlich
// Wenn es vom Server selbst aufgerufen wird, ist keine Auth. notwendig
// (z.B. fuer die Erstellung von PDFs)
if ($_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) {
// Wenn Session gesetzt ist, keine Abfrage, da diese Personen noch keine UID haben
if (isset($_SESSION['incoming/user'])) { // Von Incomingtool
$result = $this->PersonModel->loadWhere([
'zugangscode' => $_SESSION['incoming/user']
]);
if (hasData($result))
$person_id_user = current(getData($result))->person_id;
} elseif (isset($_SESSION['prestudent/user'])) { // Von Prestudententool
$result = $this->PersonModel->loadWhere([
'zugangscode' => $_SESSION['prestudent/user']
]);
if (hasData($result))
$person_id_user = current(getData($result))->person_id;
} elseif (isset($_SESSION['bewerbung/personId'])) { // Von Bewerbungstool
$person_id_user = $_SESSION['bewerbung/personId'];
} else {
$person_id_user = getAuthPersonId();
}
} else {
$serverzugriff = true;
}
// Default Bild (Dummy Profilbild)
$cTmpHEX = base64_encode(file_get_contents(FHCPATH . 'skin/images/profilbild_dummy.jpg'));
if ($source == 'person' && $id) {
$foto_gesperrt = false;
// Person laden und Fotosperre überprüfen
$result = $this->PersonModel->load($id);
if (hasData($result)) {
$person = current(getData($result));
if ($person->foto_sperre) {
// Wenn der User selbst darauf zugreift darf er das Bild sehen
$foto_gesperrt = ($person_id_user != $id);
} elseif (!$person_id_user && !$serverzugriff) {
$foto_gesperrt = true;
}
if ($person->foto && !$foto_gesperrt) {
$cTmpHEX = base64_decode($person->foto);
}
}
}
if($source == 'akte' && $id != '')
{
$this->load->model('crm/Akte_model', 'AkteModel');
$this->AkteModel->addJoin('public.tbl_person', 'person_id');
$result = $this->AkteModel->loadWhere([
'person_id' => $id,
'dokument_kurzbz' => 'Lichtbil'
]);
if (hasData($result)) {
$foto_gesperrt = false;
$akte = current(getData($result));
if ($akte->foto_sperre) {
// Wenn der User selbst darauf zugreift darf er das Bild sehen
$foto_gesperrt = ($person_id_user != $id);
} elseif (!$person_id_user && !$serverzugriff) {
$foto_gesperrt = true;
}
// Wenn das Foto nicht im Inhalt steht wird aus aus dem DMS geladen
if (!$akte->inhalt && $akte->dms_id) {
$this->load->model('content/Dms_model', 'DmsModel');
$this->load->model('content/DmsVersion_model', 'DmsVersionModel');
$this->DmsModel->addJoin('campus.tbl_dms_version', 'dms_id');
$this->DmsModel->addOrder('version', 'DESC');
$this->DmsModel->addLimit(1);
$result = $this->DmsModel->load($akte->dms_id);
if (!hasData($result))
die('Kein Dokument vorhanden');
$dms = current(getData($result));
$filename = DMS_PATH . $dms->filename;
$this->DmsVersionModel->update([
'dms_id' => $dms->dms_id,
'version' => $dms->version
], [
'letzterzugriff' => date('c')
]);
if (file_exists($filename)) {
$handle = fopen($filename, "r");
if ($handle) {
while (!feof($handle)) {
$akte->inhalt .= fread($handle, 8192);
}
fclose($handle);
} else {
echo 'Fehler: Datei konnte nicht geoeffnet werden';
}
} else {
echo 'Die Datei existiert nicht';
}
}
if ($akte->inhalt && !$foto_gesperrt) {
$cTmpHEX = $akte->inhalt;
}
}
}
// die bilder werden, sofern es funktioniert, in jpg umgewandelt da es sonst zu fehlern beim erstellen
// von pdfs kommen kann.
$im = @imagecreatefromstring(base64_decode($cTmpHEX));
if ($im) {
@ob_clean();
header("Content-type: image/jpeg");
exit(imagejpeg($im));
} else {
// bei manchen Bildern funktioniert die konvertierung nicht
// diese werden dann einfach so angezeigt.
@ob_clean();
header("Content-type: image/gif");
exit($cTmpHEX);
}
}
}
@@ -0,0 +1,35 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Stundenplan extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct([
'index' => ['basis/cis:r']
]);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @return void
*/
public function index()
{
$viewData = array(
'uid'=>getAuthUID(),
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Stundenplan']);
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Cis4 extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'basis/cis:r'
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @return void
*/
public function index()
{
$this->load->model('person/Person_model','PersonModel');
$personData = getData($this->PersonModel->getByUid(getAuthUID()))[0];
$viewData = array(
'uid' => getAuthUID(),
'name' => $personData->vorname,
'person_id' => $personData->person_id
);
$this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'FhcDashboard']);
}
}
+96
View File
@@ -0,0 +1,96 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
/**
*
*/
class Cms extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'content' => 'basis/cis:r',
'getNews' => 'basis/cis:r',
'getNewsRowCount' => 'basis/cis:r',
'getRoomInformation' => 'basis/cis:r',
'news' => 'basis/cis:r'
)
);
// Loads Libraries
$this->load->library('CmsLib');
// Loads phrases system
$this->loadPhrases([
'global'
]);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @param int $content_id
* @param int $version
* @param string $sprache
* @param boolean $sichtbar
*
* @return void
*/
public function content($content_id, $version = null, $sprache = null, $sichtbar = true)
{
// return early if the content_id for the content is missing
if (!isset($content_id))
$this->terminateWithError("content_id is missing");
$content = $this->ContentModel->load($content_id);
if (isError($content))
$this->terminateWithError(getError($content));
$content = getData($content);
if (NULL === $content)
$this->terminateWithError("Content not found");
$content = current($content);
$viewData = array(
'content_id' => $content_id,
'template_kurzbz' => $content->template_kurzbz,
'version' => $version,
'sichtbar' => $sichtbar
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Content']);
}
/**
* @param boolean $infoscreen
* @param string | null $studiengang_kz
* @param int | null $semester
* @param boolean $mischen
* @param string $titel
* @param boolean $edit
* @param boolean $sichtbar
*
* @return void
*/
public function news($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true)
{
$viewData = array();
$this->load->view('CisRouterView/CisRouterView.php', ['viewData'=>$viewData, 'route' => 'News']);
}
public function getRoomInformation($ort_kurzbz){
$viewData = array(
'ort_kurzbz' => $ort_kurzbz
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'CmsRoom']);
}
}
@@ -0,0 +1,43 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Dashboard extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'dashboard/benutzer:r'
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @return void
*/
public function index()
{
$this->load->model('person/Person_model','PersonModel');
$personData = getData($this->PersonModel->getByUid(getAuthUID()))[0];
$viewData = array(
'uid' => getAuthUID(),
'name' => $personData->vorname,
'person_id' => $personData->person_id
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData]);
}
}
+294
View File
@@ -0,0 +1,294 @@
<?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 handles output and access to documents.
* It creates a XML file, transforms it with the XSL-FO Vorlage from the
* database and generates a PDF file with unoconv or docsbox.
* This file is then outputted as download.
*
* It is the CodeIgniter version of content/pdfExport.php when not using the
* get paremeters: "archivdokument" and "archive".
* Use exportSigned() instead of providing the "sign" get parameter and
* export() otherwise.
*/
class Documents extends Auth_Controller
{
public function __construct()
{
parent::__construct([
'export' => self::PERM_LOGGED,
'exportSigned' => self::PERM_LOGGED
]);
// Load Phrases
$this->loadPhrases([
'stv'
]);
}
/**
* Download a not signed document.
*
* @param string $xml
* @param string $xsl
*
* @return void
*/
public function export($xml, $xsl)
{
return $this->_export($xml, $xsl);
}
/**
* Download a signed document.
*
* @param string $xml
* @param string $xsl
*
* @return void
*/
public function exportSigned($xml, $xsl)
{
return $this->_export($xml, $xsl, getAuthUID());
}
/**
* Helper function for export() and exportSigned()
*
* @param string $xml
* @param string $xsl
* @param string $sign_user (optional)
*
* @return void
*/
protected function _export($xml, $xsl, $sign_user = null)
{
$xsl_oe_kurzbz = null;
$version = $this->input->post_get('version') ?: null;
// Get the OE or STG of the document
$xsl_oe_kurzbz = $this->input->post_get('xsl_oe_kurzbz')
?: $this->input->post_get('xsl_stg_kz')
?: $this->input->post_get('stg_kz');
if (is_null($xsl_oe_kurzbz)) {
$uid = $this->input->post_get('uid');
if ($uid) {
$uid = current(explode(';', $uid));
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$uid]);
if (!isError($result) && hasData($result))
$xsl_oe_kurzbz = current(getData($result))->studiengang_kz;
}
}
if (is_null($xsl_oe_kurzbz)) {
$prestudent_id = $this->input->post_get('prestudent_id');
if ($prestudent_id) {
$prestudent_id = current(explode(';', $prestudent_id));
$this->load->model('crm/Prestudent_model', 'PrestudentModel');
$result = $this->PrestudentModel->load($prestudent_id);
if (!isError($result) && hasData($result))
$xsl_oe_kurzbz = current(getData($result))->studiengang_kz;
}
}
if (is_null($xsl_oe_kurzbz))
$xsl_oe_kurzbz = 0;
// Access rights
if ($xsl == 'AccountInfo') {
$this->load->model('resource/Mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('crm/Student_model', 'StudentModel');
$uids = $this->input->post_get('uid');
if ($uids) {
$uids = explode(';', $uids);
foreach ($uids as $uid) {
$result = $this->MitarbeiterModel->load($uid);
if (!isError($result) && hasData($result)) {
if (!$this->permissionlib->isBerechtigt('admin', 'suid', 0)
&& !$this->permissionlib->isBerechtigt('mitarbeiter', 'suid', 0))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'mitarbeiter:rw']]);
} else {
$result = $this->StudentModel->load([$uid]);
if (!isError($result) && hasData($result)) {
$student = current(getData($result));
if (!$this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz)
&& !$this->permissionlib->isBerechtigt('admin', 'suid', 0)
&& !$this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz)
&& !$this->permissionlib->isBerechtigt('assistenz', 'suid', 0)
&& !$this->permissionlib->isBerechtigt('support', 'suid', 0))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw', 'support:rw']]);
}
}
}
}
} else {
$this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel');
$result = $this->VorlagestudiengangModel->getCurrent($xsl, $xsl_oe_kurzbz, $version);
if (isError($result))
return show_error(getError($result));
if (!hasData($result))
return show_404();
$access_rights = current(getData($result))->berechtigung;
if (!$access_rights)
return show_404();
$allowed = false;
foreach ($access_rights as $access_right) {
if ($this->permissionlib->isBerechtigt($access_right)) {
$allowed = true;
break;
}
}
if (!$allowed)
return $this->_outputAuthError([$this->router->method => $access_rights]);
}
// Output format
$outputformat = $this->input->post_get('output') ?: 'pdf';
if ($outputformat != 'pdf'
// An der FHTW darf das Studienblatt und das Prüfungsprotokoll auch in anderen Formaten exportiert werden
&& !(CAMPUS_NAME == 'FH Technikum Wien'
&& ($xsl == 'Studienblatt'
|| $xsl == 'StudienblattEng'
|| $xsl == 'PrProtBA'
|| $xsl == 'PrProtBAEng'
|| $xsl == 'PrProtMA'
|| $xsl == 'PrProtMAEng'
)
)
&& !$this->permissionlib->isBerechtigt('system/change_outputformat', null, $xsl_oe_kurzbz)
) {
$outputformat = 'pdf';
}
// XML Params
$params = 'xmlformat=xml';
foreach ([
'uid',
'stg_kz',
'person_id',
'id',
'prestudent_id',
'buchungsnummern',
'ss',
'abschlusspruefung_id',
'typ',
'all',
'preoutgoing_id',
'lvid',
'projekt_kurzbz',
'von',
'bis',
'stundevon',
'stundebis',
'sem',
'lehreinheit',
'mitarbeiter_uid',
'studienordnung_id',
'fixangestellt',
'standort',
'abrechnungsmonat',
'form',
'projektarbeit_id',
'betreuerart_kurzbz',
'studiensemester_kurzbz'
] as $key) {
$value = $this->input->post_get($key);
if ($value !== null)
$params .= '&' . $key . '=' . urlencode($value);
}
$value = $this->input->post_get('vertrag_id');
if ($value !== null) {
foreach ($value as $id)
$params .= '&vertrag_id[]=' . urlencode($id);
}
$this->load->library('DocumentExportLib');
$this->load->model('system/Vorlage_model', 'VorlageModel');
$result = $this->VorlageModel->load($xsl);
if (isError($result))
return show_error(getError($result));
if (!hasData($result))
show_404();
$vorlage = current(getData($result));
if ($sign_user && !$vorlage->signierbar)
return show_error($this->p->t("stv", "grades_error_sign"));
// Filename
$filename = ($vorlage->bezeichnung ?: $vorlage->vorlage_kurzbz);
switch ($xsl) {
case 'LV_Informationen':
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$result = $this->StudiengangModel->load($this->input->post_get('stg_kz'));
if (!isError($result) && hasData($result))
$filename .= '_' . sanitizeProblemChars(current(getData($result))->kurzbzlang);
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->StudiensemesterModel->load($this->input->post_get('ss'));
if (!isError($result) && hasData($result))
$filename .= '_' . sanitizeProblemChars(current(getData($result))->studiensemester_kurzbz);
break;
case 'Honorarvertrag':
$uid = str_replace(';', '', $this->input->post_get('uid') ?: '');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->BenutzerModel->addJoin('public.tbl_person', 'person_id', 'LEFT');
$result = $this->BenutzerModel->load([$uid]);
if (!isError($result) && hasData($result)) {
$user = current(getData($result));
$filename .= '_' . sanitizeProblemChars($user->nachname) . '_' . sanitizeProblemChars($user->vorname);
}
break;
case 'Studienordnung':
$filename = 'Studienordnung-Studienplan-';
$this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
$result = $this->StudienordnungModel->load($this->input->post_get('studienordnung_id'));
if (!isError($result) && hasData($result)) {
$so = current(getData($result));
$filename .= sprintf("%'.04d", $so->studiengang_kz) . '-' . $so->studiengangkurzbzlang;
}
break;
default:
$uid = str_replace(';', '', $this->input->post_get('uid') ?: '');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->BenutzerModel->addJoin('public.tbl_person', 'person_id', 'LEFT');
$result = $this->BenutzerModel->load([$uid]);
if (!isError($result) && hasData($result)) {
$user = current(getData($result));
$filename .= '_' . sanitizeProblemChars($user->nachname);
}
break;
}
// XML Data
$result = $this->documentexportlib->getDataURL($xml, $params);
if (isError($result))
return show_error(getError($result));
$data = getData($result);
// Output
$this->documentexportlib->showContent($filename, $vorlage, $data, $xsl_oe_kurzbz, $version, $outputformat, $sign_user);
}
}
@@ -30,7 +30,8 @@ class Studentenverwaltung extends Auth_Controller
'admin' => $this->permissionlib->isBerechtigt('admin'),
'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz','suid'),
'student/keine_studstatuspruefung' => $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'),
'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht')
'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht'),
'system/change_outputformat' => $this->permissionlib->getOE_isEntitledFor('system/change_outputformat'),
],
'variables' => [
'semester_aktuell' => $this->variablelib->getVar('semester_aktuell')
-16
View File
@@ -1,16 +0,0 @@
<?php
if ( !defined("PHPUNIT_TEST") ) {
show_404();
}
class Test extends CI_Controller
{
public function index()
{
// Yep... This is all we need.
ini_set('error_reporting', E_ALL); // or error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
}
}
@@ -0,0 +1,145 @@
<?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');
class Ampeln extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'open' => self::PERM_LOGGED,
'all' => self::PERM_LOGGED,
'confirm' => self::PERM_LOGGED,
'alleAmpeln' => self::PERM_LOGGED,
]);
$this->load->model('content/Ampel_model', 'AmpelModel');
$this->load->model('system/Sprache_model', 'SpracheModel');
$this->uid = getAuthUID();
$this->pid = getAuthPersonID();
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* confirms ampel and inserts ampel_id in public.tbl_ampel_benutzer_bestaetigt
* @access public
*
*/
public function confirm($ampel_id)
{
$this->load->library('form_validation');
$this->form_validation->set_data(['ampel_id'=> $ampel_id]);
$this->form_validation->set_rules('ampel_id', 'Ampel ID', 'required|integer');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
// load Ampel_benutzer_bestaetigt_model to confirm the ampel
$this->load->model('content/Ampel_Benutzer_Bestaetigt_model', 'AmpelBenutzerBestaetigtModel');
$insert_into_result = $this->AmpelBenutzerBestaetigtModel->insert(["ampel_id"=> $ampel_id, "uid"=> $this->uid]);
$insert_into_result = $this->getDataOrTerminateWithError($insert_into_result);
$this->terminateWithSuccess($insert_into_result);
}
/**
* queries active and not confirmed ampeln by the user
* @access public
*
*/
public function open()
{
$userAmpeln = array();
// fetch active ampeln
$activeAmpeln = $this->AmpelModel->openActive($this->uid, false);
$activeAmpeln = $this->getDataOrTerminateWithError($activeAmpeln);
foreach ($activeAmpeln as $ampel) {
// only include non confirmed active ampeln in the result
if (!$ampel->bestaetigt) {
// check if the user was assigned to the ampel
$zugeteilt = $this->AmpelModel->isZugeteilt($this->uid, $ampel->benutzer_select);
$zugeteilt = $this->getDataOrTerminateWithError($zugeteilt);
if($zugeteilt) $userAmpeln[] = $ampel;
}
}
$this->terminateWithSuccess($userAmpeln);
}
/**
* queries all ampeln of the user
* @access public
*
*/
public function all()
{
$userAmpeln = array();
$ampel_result = $this->AmpelModel->active(false, $this->uid);
$ampel_result = $this->getDataOrTerminateWithError($ampel_result);
foreach ($ampel_result as $ampel) {
// check if the ampel was assigned to the user
$zugeteilt = $this->AmpelModel->isZugeteilt($this->uid, $ampel->benutzer_select);
$zugeteilt = $this->getDataOrTerminateWithError($zugeteilt);
if ($zugeteilt) $userAmpeln[] = $ampel;
}
$this->terminateWithSuccess($userAmpeln);
}
/**
* queries all ampeln that were assigned to the user until start of first work day
* @access public
*
*/
public function alleAmpeln()
{
//fetch all ampeln
$alle_ampeln = $this->AmpelModel->alleAmpeln($this->uid);
$alle_ampeln = $this->getDataOrTerminateWithError($alle_ampeln);
$alle_ampeln = array_map(function ($ampel) {
// check if ampel is confirmed by user
$confirmedByUser = $this->AmpelModel->isConfirmed($ampel->ampel_id, $this->uid);
$ampel->bestaetigt = $confirmedByUser;
return $ampel;
}, $alle_ampeln);
$this->terminateWithSuccess($alle_ampeln);
}
}
@@ -0,0 +1,52 @@
<?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');
class AuthInfo extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getAuthUID' => self::PERM_LOGGED,
]);
$this->uid = getAuthUID();
$this->pid = getAuthPersonID();
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* returns the uid of the currently logged in user
* @access public
*
*/
public function getAuthUID()
{
$this->terminateWithSuccess(['uid'=>$this->uid]);
}
}
@@ -0,0 +1,276 @@
<?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');
/**
* @SWG\Info(
* title="Bookmark API",
* version="1.0.0"
* )
*/
/**
* @SWG\Swagger(
* schemes={"https"},
* basePath="/fhcompletecis4/cis.php/api/frontend/v1/Bookmark/"
* )
*/
/**
* @SWG\SecurityScheme(
* securityDefinition="basicAuth",
* type="basic"
* )
*/
class Bookmark extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getBookmarks' => self::PERM_LOGGED,
'delete' => self::PERM_LOGGED,
'insert' => self::PERM_LOGGED,
'update' => self::PERM_LOGGED,
'test_true' => self::PERM_LOGGED
]);
$this->load->model('dashboard/Bookmark_model', 'BookmarkModel');
$this->uid = getAuthUID();
$this->pid = getAuthPersonID();
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* gets the bookmarks associated to a user
* @access public
* @return void
* @SWG\Get(
* path="/getBookmarks",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Get user's bookmarks",
* description="Returns all bookmarks associated with the authenticated user.",
* @SWG\Response(
* response=200,
* description="List of bookmarks"
* ),
* @SWG\Response(
* response=401,
* description="Unauthorized"
* )
* )
*/
public function getBookmarks()
{
$this->BookmarkModel->addOrder("bookmark_id");
$bookmarks = $this->BookmarkModel->loadWhere(["uid"=>$this->uid]);
$bookmarks = $this->getDataOrTerminateWithError($bookmarks);
$this->terminateWithSuccess($bookmarks);
}
/**
* deletes bookmark from associated user
* @access public
* @return void
* @SWG\Post(
* path="/delete/{bookmark_id}",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Delete a bookmark",
* description="Deletes a bookmark if the user is the owner or an admin.",
* @SWG\Parameter(
* name="bookmark_id",
* in="path",
* required=true,
* type="integer"
* ),
* @SWG\Response(
* response=200,
* description="Bookmark deleted successfully"
* ),
* @SWG\Response(
* response=403,
* description="Forbidden - not the owner"
* ),
* @SWG\Response(
* response=404,
* description="Bookmark not found"
* )
* )
*/
public function delete($bookmark_id)
{
$bookmark = $this->BookmarkModel->load($bookmark_id);
$bookmark = current($this->getDataOrTerminateWithError($bookmark));
// only delete bookmark if the user is the owner of the bookmark
if($bookmark->uid == $this->uid || $this->permissionlib->isBerechtigt('admin')){
$delete_result = $this->BookmarkModel->delete($bookmark_id);
$delete_result = $this->getDataOrTerminateWithError($delete_result);
$this->terminateWithSuccess($delete_result);
}else{
$this->_outputAuthError(['delete' => ['admin:rw']]);
}
}
/**
* inserts new bookmark into the bookmark table
* @access public
* @return void
* @SWG\Post(
* path="/insert",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Insert a new bookmark",
* @SWG\Parameter(
* name="body",
* in="body",
* required=true,
* @SWG\Schema(
* type="object",
* required={"url", "title"},
* @SWG\Property(
* property="url",
* type="string",
* example="https://github.com/swagger-api/swagger-codegen"
* ),
* @SWG\Property(
* property="title",
* type="string",
* example="Swagger Codegen"
* ),
* @SWG\Property(
* property="tag",
* type="string",
* example="API"
* )
* )
* ),
* @SWG\Response(
* response=201,
* description="Bookmark created"
* ),
* @SWG\Response(
* response=400,
* description="Validation error"
* )
* )
*/
public function insert()
{
// form validation
$this->load->library('form_validation');
$this->form_validation->set_rules('url', 'URL', 'required|valid_url|max_length[511]');
$this->form_validation->set_rules('title', 'Title', 'required|max_length[255]');
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$url = $this->input->post('url',true);
$title = $this->input->post('title',true);
$tag = $this->input->post('tag', true);
$insert_into_result = $this->BookmarkModel->insert(['uid'=>$this->uid, 'url'=>$url, 'title'=>$title,'tag'=>$tag, 'insertvon'=>$this->uid, 'updateamum'=>NULL, 'updatevon'=>NULL]);
$insert_into_result = $this->getDataOrTerminateWithError($insert_into_result);
$this->terminateWithSuccess($insert_into_result);
}
/**
* @SWG\Post(
* path="/update/{bookmark_id}",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Update a bookmark",
* description="Updates a bookmark's URL and title for the given ID.",
* @SWG\Parameter(
* name="bookmark_id",
* in="path",
* required=true,
* type="integer",
* description="ID of the bookmark to update"
* ),
* @SWG\Parameter(
* name="body",
* in="body",
* required=true,
* @SWG\Schema(
* type="object",
* required={"url", "title"},
* @SWG\Property(
* property="url",
* type="string",
* example="https://updated-url.com"
* ),
* @SWG\Property(
* property="title",
* type="string",
* example="Updated Title"
* )
* )
* ),
* @SWG\Response(
* response=200,
* description="Bookmark updated"
* ),
* @SWG\Response(
* response=400,
* description="Validation error"
* )
* )
*/
public function update($bookmark_id)
{
// form validation
$this->load->library('form_validation');
$this->form_validation->set_rules('url', 'URL', 'required|valid_url|max_length[511]');
$this->form_validation->set_rules('title', 'Title', 'required|max_length[255]');
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$url = $this->input->post('url',true);
$title = $this->input->post('title',true);
$now = new DateTime();
$now = $now->format('Y-m-d H:i:s');
$update_result = $this->BookmarkModel->update($bookmark_id,['url'=>$url, 'title'=>$title,'updateamum'=>$now]);
$update_result = $this->getDataOrTerminateWithError($update_result);
$this->terminateWithSuccess($update_result);
}
}
@@ -0,0 +1,58 @@
<?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');
class Cis4FhcApi extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getViewData' => self::PERM_LOGGED,
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* fetches ViewData
*/
public function getViewData()
{
$this->load->model('person/Person_model','PersonModel');
$personData = getData($this->PersonModel->getByUid(getAuthUID()))[0];
$viewData = array(
'uid' => getAuthUID(),
'name' => $personData->vorname,
'person_id' => $personData->person_id
);
$this->terminateWithSuccess($viewData);
}
}
@@ -0,0 +1,58 @@
<?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');
class CisMenu extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getMenu' => self::PERM_LOGGED,
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* fetches the menu for CIS from the database based on the userLanguage
*/
public function getMenu()
{
$this->load->model('content/Content_model', 'ContentModel');
$this->load->config('cis');
$cis4_content_id =$this->config->item('cis_menu_root_content_id');
$result = $this->ContentModel->getMenu($cis4_content_id, getAuthUID(),getUserLanguage());
$result = $this->getDataOrTerminateWithError($result);
$menu = $result->childs ?? [];
$this->terminateWithSuccess($menu);
}
}
@@ -0,0 +1,207 @@
<?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 SearchBarLib (back-end)
* Provides data to the ajax get calls about the searchbar component
* This controller works with JSON calls on the HTTP GET and the output is always JSON
*/
class Cms extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
// NOTE(chris): additional permission checks will be done in SearchBarLib
parent::__construct([
'ContentID' => self::PERM_LOGGED,
'getOrtKurzbzContent' => self::PERM_LOGGED,
'content' => self::PERM_LOGGED,
'news' => self::PERM_LOGGED,
'getNewsRowCount' => self::PERM_LOGGED,
'getNews' => self::PERM_LOGGED,
]);
$this->load->model('content/News_model', 'NewsModel');
// setting up the papgination_size
$this->page_size = 10;
$this->load->library('CmsLib');
// Loads phrases system
$this->loadPhrases([
'global'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* fetches the content with the content_id and additional parameters
*/
public function content()
{
// form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('content_id','Content ID','required|is_natural');
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
// getting the get parameters
$content_id = $this->input->get("content_id",TRUE);
$version = $this->input->get("version",TRUE);
$sprache = $this->input->get("sprache",TRUE);
$sichtbar = $this->input->get("sichtbar",TRUE);
$content = $this->cmslib->getContent($content_id, $version, $sprache, $sichtbar);
$content = $this->getDataOrTerminateWithError($content);
$this->terminateWithSuccess($content);
}
/**
* Gets a JSON body via HTTP POST and provides the parameters
*/
public function ContentID()
{
// form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('ort_kurzbz', 'Ort', 'required');
if ($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$ort_kurzbz = $this->input->get('ort_kurzbz',TRUE);
$content_id = $this->OrtModel->getContentID($ort_kurzbz);
$content_id = current($this->getDataOrTerminateWithError($content_id))->content_id;
$this->terminateWithSuccess($content_id);
}
public function news()
{
// form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('limit','Limit','required|is_natural_no_zero');
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$this->load->model('content/news_model', 'NewsModel');
$limit = $this->input->get('limit',TRUE);
//query the news
$news = $this->NewsModel->getAll($limit);
//get the data or terminate with error
$news = $this->getDataOrTerminateWithError($news);
// array that keeps track of which news don't have a betreff and have to be removed from the news array
$newsToRemove = array();
// collect the content of the news
foreach($news as $index=>$news_element){
$this->NewsModel->resetQuery();
$content = $this->cmslib->getContent($news_element->content_id);
if(isError($content))
{
// removes the news from the news array, so that the response does not include a invalid news
array_push($newsToRemove,$index);
//add the error to the api response? visual feedback
//$this->addError(print_r($content->retval,true));
continue;
}
$content = getData($content);
$news_element->content_obj = $content;
}
//removes all news that don't have a betreff
foreach($newsToRemove as $removeNewsIndex)
{
unset($news[$removeNewsIndex]);
}
$withContent = function($news) {
return $news->content_obj != null;
};
$newsWithContent = array_filter($news, $withContent);
$this->terminateWithSuccess($newsWithContent);
}
public function getNewsRowCount($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $fachbereich_kurzbz = null, $maxalter = 0, $edit = false, $sichtbar = true, $page = 1, $page_size = 10)
{
list($studiengang_kz, $semester) = $this->cmslib->getStgAndSem($studiengang_kz, $semester);
$all = $edit;
$this->load->model('content/News_model','NewsModel');
$num_rows = $this->NewsModel->countNewsWithContent(getSprache(), $studiengang_kz, $semester, $fachbereich_kurzbz, $sichtbar, $maxalter, $page, $page_size, $all, $mischen);
$num_rows = $this->getDataOrTerminateWithError($num_rows);
$this->terminateWithSuccess($num_rows);
}
public function getNews($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true)
{
//form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('page','Page','required|is_natural');
$this->form_validation->set_rules('page_size', 'PageSize', 'is_natural');
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
// getting the GET parameters
$page = intval($this->input->get('page', true));
$page_size = intval($this->input->get('page_size', true));
$sprache = $this->input->get('sprache', true);
if(!$sprache)
{
$sprache = getUserLanguage();
}
// default value for the page_size is 10
$page_size = $page_size ?? 10;
$news = $this->cmslib->getNews($infoscreen, $studiengang_kz, $semester, $mischen, $titel, $edit, $sichtbar, $page, $page_size, $sprache);
$news = $this->getDataOrTerminateWithError($news);
$this->addMeta('phrases', json_decode($this->p->getJson()));
$this->terminateWithSuccess($news);
}
}
@@ -0,0 +1,422 @@
<?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 documents
* Listens to ajax post calls to change the documents data
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*
* This controller handles output and access to documents.
* It checks permissions to render documents in an alternative format
* or it creates a XML file, transforms it with the XSL-FO Vorlage from the
* database and generates a PDF file with unoconv or docsbox.
* This file is then archivated in the database.
*
* The last part is the CodeIgniter version of content/pdfExport.php when not
* using the get paremeter: "archivdokument" but using the get parameter:
* "archive".
* Use archiveSigned() instead of providing the "sign" get parameter and
* archive() otherwise.
*/
class Documents extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'permissionAlternativeFormat' => self::PERM_LOGGED,
'archive' => ['admin:rw', 'assistenz:rw'],
'archiveSigned' => ['admin:rw', 'assistenz:rw']
]);
// Load Phrases
$this->loadPhrases([
'stv'
]);
}
/**
* Checks if the current user has permission to render documents in an
* alternative format.
*
* @param string $oe_kurzbz Or studiengang_kz
*
* @return void
*/
public function permissionAlternativeFormat($oe_kurzbz)
{
$this->terminateWithSuccess($this->permissionlib->isBerechtigt('system/change_outputformat', null, $oe_kurzbz));
}
/**
* Download a not signed document.
*
* @param string $xml (optional)
* @param string $xsl (optional)
*
* @return void
*/
public function archive($xml = null, $xsl = null)
{
return $this->_archive($xml, $xsl);
}
/**
* Download a signed document.
*
* @param string $xml (optional)
* @param string $xsl (optional)
*
* @return void
*/
public function archiveSigned($xml = null, $xsl = null)
{
return $this->_archive($xml, $xsl, getAuthUID());
}
/**
* Helper function for archive() and archiveSigned()
*
* @param string $xml
* @param string $xsl
* @param string $sign_user (optional)
*
* @return void
*/
public function _archive($xml, $xsl, $sign_user = null)
{
if (!$xml || !$xsl) {
$this->load->library('form_validation');
if (!$xml) {
$xml = $this->input->post_get('xml');
$this->form_validation->set_rules('xml', 'xml', 'required');
}
if (!$xsl) {
$xsl = $this->input->post_get('xsl');
$this->form_validation->set_rules('xsl', 'xsl', 'required');
}
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$xsl_oe_kurzbz = null;
$version = $this->input->post_get('version') ?: null;
// Get the OE or STG of the document
$xsl_oe_kurzbz = $this->input->post_get('xsl_oe_kurzbz')
?: $this->input->post_get('xsl_stg_kz')
?: $this->input->post_get('stg_kz');
if (is_null($xsl_oe_kurzbz)) {
$uid = $this->input->post_get('uid');
if ($uid) {
$uid = current(explode(';', $uid));
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$uid]);
if (!isError($result) && hasData($result))
$xsl_oe_kurzbz = current(getData($result))->studiengang_kz;
}
}
if (is_null($xsl_oe_kurzbz)) {
$prestudent_id = $this->input->post_get('prestudent_id');
if ($prestudent_id) {
$prestudent_id = current(explode(';', $prestudent_id));
$this->load->model('crm/Prestudent_model', 'PrestudentModel');
$result = $this->PrestudentModel->load($prestudent_id);
if (!isError($result) && hasData($result))
$xsl_oe_kurzbz = current(getData($result))->studiengang_kz;
}
}
if (is_null($xsl_oe_kurzbz))
$xsl_oe_kurzbz = 0;
// Vorlage
$this->load->model('system/Vorlage_model', 'VorlageModel');
$result = $this->VorlageModel->load($xsl);
$vorlage = current($this->getDataOrTerminateWithError($result));
if (!$vorlage)
show_404();
// Akte Data
$akteData = [
'dokument_kurzbz' => $vorlage->dokument_kurzbz ?: 'Zeugnis',
'mimetype' => 'application/pdf',
'erstelltam' => date('Y-m-d'),
'gedruckt' => true,
'insertamum' => date('c'),
'insertvon' => getAuthUID(),
'uid' => $this->input->post_get('uid') ?: '',
'archiv' => true,
'signiert' => !!$sign_user,
'stud_selfservice' => $vorlage->stud_selfservice
];
$studiengang_kz = null;
if ($akteData['uid']) {
$this->load->model('crm/Student_model', 'StudentModel');
$this->StudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT');
$result = $this->StudentModel->load([$akteData['uid']]);
$student = current($this->getDataOrTerminateWithError($result));
$ss = $this->input->post_get('ss');
if ($ss !== null) {
$this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel');
$result = $this->PrestudentstatusModel->getLastStatus($student->prestudent_id, $ss);
$status = current($this->getDataOrTerminateWithError($result));
if (!$status)
$this->terminateWithError($this->p->t("stv", "grades_error_prestudentstatus"));
$semester = $status->ausbildungssemester;
$this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
$this->StudentlehrverbandModel->addJoin('public.tbl_benutzer', 'uid = student_uid');
$this->StudentlehrverbandModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$result = $this->StudentlehrverbandModel->load([
'studiensemester_kurzbz' => $ss,
'student_uid' => $akteData['uid']
]);
$res = current($this->getDataOrTerminateWithError($result));
$studiengang_kz = $res->studiengang_kz;
$akteData['person_id'] = $res->person_id;
switch ($xsl) {
case 'Ausbildungsver':
case 'AusbVerEng':
$akteData['titel'] = mb_substr($xsl .
"_" .
strtoupper($res->typ) .
strtoupper($res->kurzbz) .
"_" .
$semester .
"_" .
$ss, 0, 64);
$akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64);
break;
case 'LVZeugnisEng':
case 'LVZeugnis':
case 'Zertifikat':
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->load($this->input->post_get('lvid'));
$lv = current($this->getDataOrTerminateWithError($result));
$akteData['dokument_kurzbz'] = $xsl;
$akteData['titel'] = mb_substr($xsl .
"_" .
strtoupper($res->typ) .
strtoupper($res->kurzbz) .
"_" .
$semester .
'_' .
$ss .
'_' .
str_replace(' ', '_', $lv->bezeichnung), 0, 60);
$akteData['bezeichnung'] = mb_substr($xsl .
" " .
strtoupper($res->typ) .
strtoupper($res->kurzbz) .
" " .
$semester .
". Semester" .
' ' .
$ss .
' ' .
$lv->bezeichnung, 0, 64);
break;
case 'SZeugnis':
$akteData['titel'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64);
$akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64);
break;
default:
$akteData['titel'] = mb_substr($xsl .
"_" .
strtoupper($res->typ) .
strtoupper($res->kurzbz) .
"_" .
$semester .
"_" .
$ss, 0, 64);
$akteData['bezeichnung'] = mb_substr($xsl .
" " .
strtoupper($res->typ) .
strtoupper($res->kurzbz) .
" " .
$semester .
". Semester" .
' ' .
$ss, 0, 64);
break;
}
} else {
$studiengang_kz = $student->studiengang_kz;
$akteData['person_id'] = $student->person_id;
$akteData['titel'] = $vorlage->bezeichnung . '_' . $student->kuerzel;
$akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64);
}
} else {
$prestudent_id = $this->input->post_get('prestudent_id');
if ($prestudent_id) {
$this->load->model('crm/prestudent_model', 'PrestudentModel');
$this->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT');
$result = $this->PrestudentModel->load($prestudent_id);
$prestudent = current($this->getDataOrTerminateWithError($result));
$studiengang_kz = $prestudent->studiengang_kz;
$akteData['person_id'] = $prestudent->person_id;
$akteData['titel'] = mb_substr($xsl . "_" . $prestudent->kuerzel, 0, 64);
$akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $prestudent->kuerzel, 0, 64);
}
}
// Access rights
if (!$this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz)
&& !$this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]);
if ($xsl == 'AccountInfo') {
$this->load->model('resource/Mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('crm/Student_model', 'StudentModel');
$uids = $this->input->post_get('uid');
if ($uids) {
$uids = explode(';', $uids);
foreach ($uids as $uid) {
$result = $this->MitarbeiterModel->load($uid);
if (!isError($result) && hasData($result)) {
if (!$this->permissionlib->isBerechtigt('admin', 'suid', 0)
&& !$this->permissionlib->isBerechtigt('mitarbeiter', 'suid', 0))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'mitarbeiter:rw']]);
} else {
$result = $this->StudentModel->load([$uid]);
if (!isError($result) && hasData($result)) {
$student = current(getData($result));
if (!$this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz)
&& !$this->permissionlib->isBerechtigt('admin', 'suid', 0)
&& !$this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz)
&& !$this->permissionlib->isBerechtigt('assistenz', 'suid', 0)
&& !$this->permissionlib->isBerechtigt('support', 'suid', 0))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw', 'support:rw']]);
}
}
}
}
} else {
$this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel');
$result = $this->VorlagestudiengangModel->getCurrent($xsl, $xsl_oe_kurzbz, $version);
$access_rights = current($this->getDataOrTerminateWithError($result));
if (!$access_rights || !$access_rights->berechtigung)
return show_404();
$allowed = false;
foreach ($access_rights->berechtigung as $access_right) {
if ($this->permissionlib->isBerechtigt($access_right)) {
$allowed = true;
break;
}
}
if (!$allowed)
return $this->_outputAuthError([$this->router->method => $access_rights]);
}
// Output format
$outputformat = $this->input->post_get('output') ?: 'pdf';
if ($outputformat != 'pdf'
// An der FHTW darf das Studienblatt und das Prüfungsprotokoll auch in anderen Formaten exportiert werden
&& !(CAMPUS_NAME == 'FH Technikum Wien'
&& ($xsl == 'Studienblatt'
|| $xsl == 'StudienblattEng'
|| $xsl == 'PrProtBA'
|| $xsl == 'PrProtBAEng'
|| $xsl == 'PrProtMA'
|| $xsl == 'PrProtMAEng'
)
)
&& !$this->permissionlib->isBerechtigt('system/change_outputformat', null, $xsl_oe_kurzbz)
) {
$outputformat = 'pdf';
}
// XML Params
$params = 'xmlformat=xml';
foreach ([
'uid',
'stg_kz',
'person_id',
'id',
'prestudent_id',
'buchungsnummern',
'ss',
'abschlusspruefung_id',
'typ',
'all',
'preoutgoing_id',
'lvid',
'projekt_kurzbz',
'von',
'bis',
'stundevon',
'stundebis',
'sem',
'lehreinheit',
'mitarbeiter_uid',
'studienordnung_id',
'fixangestellt',
'standort',
'abrechnungsmonat',
'form',
'projektarbeit_id',
'betreuerart_kurzbz',
'studiensemester_kurzbz'
] as $key) {
$value = $this->input->post_get($key);
if ($value !== null)
$params .= '&' . $key . '=' . urlencode($value);
}
$value = $this->input->post_get('vertrag_id');
if ($value !== null) {
foreach ($value as $id)
$params .= '&vertrag_id[]=' . urlencode($id);
}
if (!$vorlage->archivierbar)
$this->terminateWithError($this->p->t("stv", "grades_error_archive"));
if ($sign_user && !$vorlage->signierbar)
$this->terminateWithError($this->p->t("stv", "grades_error_sign"));
$this->load->library('DocumentExportLib');
// XML Data
$result = $this->documentexportlib->getDataURL($xml, $params);
$data = $this->getDataOrTerminateWithError($result);
$this->documentexportlib->addArchiveToData($data);
// Output
$result = $this->documentexportlib->getContent($vorlage, $data, $xsl_oe_kurzbz, $version, $outputformat, $sign_user);
$content = $this->getDataOrTerminateWithError($result);
$akteData['titel'] .= '.pdf';
$akteData['inhalt'] = base64_encode($content);
$this->load->model('crm/Akte_model', 'AkteModel');
$result = $this->AkteModel->insert($akteData);
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(true);
}
}
@@ -113,7 +113,7 @@ class Filter extends FHCAPI_Controller
*/
public function applyFilterFields()
{
$this->form_validation->set_rules('filterFields', 'filterFields', 'required');
$this->form_validation->set_rules('filterFields[]', 'filterFields', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
@@ -0,0 +1,103 @@
<?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');
class Lehre extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'lvStudentenMail' => self::PERM_LOGGED,
'LV' => self::PERM_LOGGED,
'Pruefungen' => self::PERM_LOGGED,
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* constructs the emails of the groups from a lehrveranstaltung
*/
public function lvStudentenMail()
{
$lehreinheit_id = $this->input->get("lehreinheit_id",TRUE);
// return early if the required parameter is missing
if(!isset($lehreinheit_id))
{
$this->terminateWithError('Missing required parameter', self::ERROR_TYPE_GENERAL);
}
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$studentenMails = $this->LehreinheitModel->getStudentenMail($lehreinheit_id);
$studentenMails = $this->getDataOrTerminateWithError($studentenMails);
//convert array of objects into array of strings
$studentenMails = array_map(function($element){
return $element->mail;
}, $studentenMails);
$this->terminateWithSuccess($studentenMails);
}
public function LV($studiensemester_kurzbz, $lehrveranstaltung_id)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage(), $lehrveranstaltung_id);
$result = current($this->getDataOrTerminateWithError($result));
$this->terminateWithSuccess($result);
}
/**
* fetches all Pruefungen of a student for a specific lehrveranstaltung
* if the student passed the Pruefung on the first attempt, no information about the Pruefungen is stored in the database
* @param mixed $lehrveranstaltung_id
* @return void
*/
public function Pruefungen($lehrveranstaltung_id)
{
$this->load->model('education/Pruefung_model', 'PruefungModel');
$result = $this->PruefungModel->getByStudentAndLv(getAuthUID(), $lehrveranstaltung_id, getUserLanguage());
$result = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($result);
}
}
@@ -0,0 +1,534 @@
<?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');
use CI3_Events as Events;
/**
* This controller operates between (interface) the JS (GUI) and the SearchBarLib (back-end)
* Provides data to the ajax get calls about the searchbar component
* This controller works with JSON calls on the HTTP GET and the output is always JSON
*/
class LvMenu extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getLvMenu' => self::PERM_LOGGED
]);
$this->load->model("ressource/Mitarbeiter_model");
$this->load->model("education/Lehreinheit_model");
$this->load->model("education/Lehrveranstaltung_model");
$this->load->model("organisation/Studiengang_model");
$this->load->model("accounting/Vertrag_model");
$this->load->model("system/Variable_model");
$this->load->model("person/Benutzergruppe_model");
$this->load->model("education/Lvangebot_model");
$this->load->model("ressource/Lehretools_model");
$this->load->library("PermissionLib", null, 'PermissionLib');
$this->load->library("PhrasesLib");
$this->loadPhrases(array('global', 'lehre'));
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* alternative function to get multiple lvMenus with a single http request
*/
public function getMultipleLvMenu($lvMenuOptionList){
$result =[];
foreach($lvMenuOptionList as $lvMenuOptions){
$lvMenu = $this->getLvMenu($lvMenuOptions['lvid'],$lvMenuOptions['studiensemester_kurzbz']);
if(isError($lvMenu)){
// TODO: some lvMenu threw an error, handle error here
}
$result[$lvMenuOptions['lvid']]=$lvMenu;
}
$this->terminateWithSuccess($result);
}
/**
*
*/
public function getLvMenu($lvid, $studiensemester_kurzbz)
{
// return early if parameters are missing
if(!isset($lvid) || !isset($studiensemester_kurzbz))
$this->terminateWithError('Missing parameters', self::ERROR_TYPE_GENERAL);
// get the sprache
$sprache = getUserLanguage();
// get the user
if (!$user=getAuthUID())
$this->terminateWithError($this->p->t('global', 'nichtAngemeldet'));
// check if is_lector
$is_lector = false;
$mares = $this->Mitarbeiter_model->isMitarbeiter($user);
if(hasData($mares))
{
$is_lector = getData($mares);
}
// definition of user_is_allowed_to_upload
$user_is_allowed_to_upload=false;
$angezeigtes_stsem = $studiensemester_kurzbz;
// load lehrveranstaltung
$lvres = $this->Lehrveranstaltung_model->load($lvid);
if(!hasData($lvres))
{
$this->terminateWithError('LV ' . $lvid . ' not found.');
}
$lv = (getData($lvres))[0];
$this->addMeta('lvInfo',$lv);
// define studiengang_kz / semester / lehrverzeichnis
$studiengang_kz = $lv->studiengang_kz;
$semester = $lv->semester;
$short = $lv->lehreverzeichnis;
// return empty menu for studiengang_kz = 0
if($studiengang_kz == 0){
$this->terminateWithSuccess("organisatorische_einheit");
}
// load studiengang
$stgres = $this->Studiengang_model->load(strval($studiengang_kz));
if(!hasData($stgres))
{
$this->terminateWithError('Stg ' . $lv->studiengang_kz . ' not found.');
}
$stg = (getData($stgres))[0];
$kurzbz = strtoupper($stg->typ . $stg->kurzbz);
$short_name = $lv->bezeichnung;
$short_short_name = $lv->lehreverzeichnis;
// angemeldet
$angemeldet = true;
if(defined('CIS_LEHRVERANSTALTUNG_WENNANGEMELDET_DETAILS_ANZEIGEN') && CIS_LEHRVERANSTALTUNG_WENNANGEMELDET_DETAILS_ANZEIGEN && !$is_lector)
{
$angemeldet = false;
$lesres = $this->Lehreinheit_model->getLehreinheitenForStudentAndStudienSemester(
$lvid, $user, $angezeigtes_stsem
);
if(hasData($lesres) && count(getData($lesres)) > 0)
$angemeldet = true;
}
// lehrfach
$lehrfach_id='';
if(defined('CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN') && CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN)
{
// Wenn der eingeloggte User zu einer der Lehreinheiten zugeteilt ist
// wird zusätzlich das Lehrfach der Lehreinheit angezeigt.
if($is_lector )
{
$result = $this->Lehreinheit_model->getLehrfachIdMitarbeiter($angezeigtes_stsem,$user,$lvid);
}
else
{
$result = $this->Lehreinheit_model->getLehrfachIdStudierender($angezeigtes_stsem,$user,$lvid);
}
// Wenn die LV mehrere verschiedenen Lehrfaecher hat, und der User zu mehreren davon zugeteilt ist
// wird das Lehrfach nicht angezeigt damit es nicht zu verwirrungen kommt.
if( ($lehrfaecher = getData($result)) && count($lehrfaecher)==1 && ($lehrfach = $lehrfaecher[0]))
{
$lehrfach_id=$lehrfach->lehrfach_id;
}
}
// lektor der lv
$lektor_der_lv=false;
$leinfores = $this->Lehreinheit_model->getLehreinheitInfo($lvid,$angezeigtes_stsem,$lehrfach_id);
$db_result = hasData($leinfores) ? getData($leinfores) : array();
foreach($db_result as $row_lector)
{
// Lektor wird erst angezeigt wenn der Auftrag erteilt wurde
if (defined('CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON')
&& CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON != '')
{
if (!$this->Vertrag_model->isVertragErteiltLV($lvid, $angezeigtes_stsem, $row_lector->uid))
{
continue;
}
}
if($user == $row_lector->uid)
{
$lektor_der_lv=true;
$user_is_allowed_to_upload=true;
}
// style of the link
if($row_lector->lvleiter === true)
$style='style="font-weight: bold"';
else
$style='';
}
//Berechtigungen auf Fachbereichsebene
$lehrfach_oe_kurzbz_arr = array();
$fbres = $this->Lehrveranstaltung_model->getBerechtigungenAufFachberechsebene($lvid, $angezeigtes_stsem);
$fbs = (hasData($fbres)) ? getData($fbres) : array();
foreach($fbs as $row)
{
$lehrfach_oe_kurzbz_arr[] = $row->oe_kurzbz;
if($this->PermissionLib->isBerechtigt('lehre', null, $row->oe_kurzbz)
|| $this->PermissionLib->isBerechtigt('assistenz', null, $stg->oe_kurzbz))
{
$user_is_allowed_to_upload=true;
}
}
// FH-Core Menu Logic
// ##########################################################################################
$menu = array();
$this->fhc_menu_lvinfo($menu, $lvid, $studiengang_kz, $lektor_der_lv, $is_lector, $lehrfach_oe_kurzbz_arr);
$this->fhc_menu_feedback($menu, $angemeldet, $lvid);
$this->fhc_menu_gesamtnote($menu, $angemeldet, $lvid, $lv, $is_lector, $angezeigtes_stsem);
$this->fhc_menu_emailStudierende($menu, $user, $angemeldet, $lvid, $angezeigtes_stsem);
$this->fhc_menu_abmeldung($menu, $user, $is_lector, $lvid, $angezeigtes_stsem);
$this->fhc_menu_lehretools($menu, $lvid, $angezeigtes_stsem, $sprache);
$this->fhc_menu_anrechnungStudent($menu, $lvid, $angezeigtes_stsem);
$this->fhc_menu_anrechnungLector($menu, $angezeigtes_stsem);
// Addons Menu Logic
// ##########################################################################################
$params = [
'sprache'=>$sprache,
//'p'=>$p,
'ci_p'=> $this->p,
//'db'=>$db,
'user'=>$user,
'is_lector'=>$is_lector,
'user_is_allowed_to_upload'=>$user_is_allowed_to_upload,
//'rechte'=>$rechte,
'angezeigtes_stsem'=>$angezeigtes_stsem,
//'lehreinheit'=>$lehreinheit,
'lv_obj'=>$lv,
'lv'=>$lv,
'lvid'=>$lvid,
'studiengang_kz'=>$studiengang_kz,
'semester'=>$semester,
'short'=>$short,
'stg_obj'=>$stg,
'kurzbz'=>$kurzbz,
'short_name'=>$short_name,
'short_short_name'=>$short_short_name,
//'dir_name'=>$dir_name,
'angemeldet'=>$angemeldet,
'lehrfach_id'=>$lehrfach_id,
'lektor_der_lv'=>$lektor_der_lv,
'lehrfach_oe_kurzbz_arr'=>$lehrfach_oe_kurzbz_arr,
];
Events::trigger('lvMenuBuild',
// passing $menu per reference
function & () use (&$menu) {
return $menu;
},
$params
);
// Menu sortieren
// ##########################################################################################
foreach ($menu as $key => $row){
// removes menu points that are not needed in the c4 lvUebersicht
if( !array_key_exists('c4_link',$row) || !array_key_exists('c4_icon',$row)){
unset($menu[$key]);
continue;
}
// fills pos array to sort the menu
$pos[$key] = $row['position'];
}
array_multisort($pos, SORT_ASC, SORT_NUMERIC, $menu);
// HTTP response
// ##########################################################################################
$this->terminateWithSuccess($menu);
}
private function fhc_menu_lvinfo(&$menu, $lvid, $studiengang_kz, $lektor_der_lv, $is_lector, $lehrfach_oe_kurzbz_arr){
// LVINFO
if(!defined('CIS_LEHRVERANSTALTUNG_LVINFO_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_LVINFO_ANZEIGEN)
{
$c4_linkList=array();
// Bearbeiten Button anzeigen wenn Lektor der LV und bearbeiten fuer Lektoren aktiviert ist
// Oder Berechtigung zum Bearbeiten eingetragen ist
if((!defined('CIS_LEHRVERANSTALTUNG_LVINFO_LEKTOR_EDIT') && $lektor_der_lv)
|| (defined('CIS_LEHRVERANSTALTUNG_LVINFO_LEKTOR_EDIT') && CIS_LEHRVERANSTALTUNG_LVINFO_LEKTOR_EDIT==true && $lektor_der_lv)
|| $this->PermissionLib->isBerechtigt('lehre/lvinfo',$studiengang_kz)
|| $this->PermissionLib->isBerechtigtMultipleOe('lehre/lvinfo', $lehrfach_oe_kurzbz_arr)
)
{
$c4_linkList[]= [$this->p->t('lehre', 'lvInfoBearbeiten'), 'ects/index.php?lvid='.$lvid];
}
elseif ($is_lector)
{
$c4_linkList[]= ["Bearbeiten der LV-Infos derzeit gesperrt",'#'];
}
$menu[]=array
(
'id'=>'core_menu_lvinfo',
'position'=>'10',
'name'=>$this->p->t('lehre', 'lehrveranstaltungsinformation'),
'icon'=>'../../../skin/images/button_lvinfo.png',
'link'=>'',
'c4_icon'=> base_url('skin/images/button_lvinfo.png'),
'c4_link'=>'',
'c4_linkList'=>$c4_linkList
);
}
}
private function fhc_menu_feedback(&$menu, $angemeldet, $lvid){
//FEEDBACK
if((!defined('CIS_LEHRVERANSTALTUNG_FEEDBACK_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_FEEDBACK_ANZEIGEN) && $angemeldet)
{
$menu[]=array
(
'id'=>'core_menu_feedback',
'position'=>'60',
'name'=>$this->p->t('lehre', 'feedback'),
'c4_icon'=> base_url('skin/images/button_feedback.png'),
'c4_link'=> base_url('feedback.php?lvid='.$lvid),
);
}
}
private function fhc_menu_gesamtnote(&$menu, $angemeldet, $lvid, $lv_obj, $is_lector, $angezeigtes_stsem){
//Gesamtnote
if($is_lector && ((!defined('CIS_LEHRVERANSTALTUNG_GESAMTNOTE_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_GESAMTNOTE_ANZEIGEN) && $angemeldet))
{
if($lv_obj->benotung)
{
$menu[]=array
(
'id'=>'core_menu_gesamtnote',
'position'=>'80',
'name'=>$this->p->t('lehre', 'gesamtnote'),
'c4_icon'=> base_url('skin/images/button_endnote.png'),
'c4_link'=> base_url('cis/private/lehre/benotungstool/lvgesamtnoteverwalten.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem))
//'c4_link'=> base_url('benotungstool/lvgesamtnoteverwalten.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem))
);
}
else
{
$menu[]=array
(
'id'=>'core_menu_gesamtnote',
'position'=>'80',
'name'=>$this->p->t('lehre', 'gesamtnote'),
'c4_icon'=>base_url('skin/images/button_endnote.png'),
'c4_link'=>'#',
'c4_linkList'=>[[$this->p->t('lehre', 'noteneingabedeaktiviert'),'#']],
);
}
}
}
private function fhc_menu_emailStudierende(&$menu, $user, $angemeldet, $lvid, $angezeigtes_stsem){
// Email an Studierende
if((!defined('CIS_LEHRVERANSTALTUNG_MAILSTUDIERENDE_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_MAILSTUDIERENDE_ANZEIGEN) && $angemeldet)
{
$mailto='mailto:';
$c4_linkList=array();
$studentMailsRes = $this->Lehrveranstaltung_model->getStudentEMail($lvid, $angezeigtes_stsem);
// get the data of the database result and map the array of objects to their object property
$studentMails = $this->getDataOrTerminateWithError($studentMailsRes, 'No student mails found');
$nomail='';
$variablesres = $this->Variable_model->getVariables($user);
$variables = (hasData($variablesres)) ? getData($variablesres) : array();
foreach ($studentMails as $row)
{
if($row->gruppe_kurzbz != '')
{
$bngrp_uids = $this->Benutzergruppe_model->getUids($row->gruppe_kurzbz, $angezeigtes_stsem);
if(count($bngrp_uids) > 0)
{
if(!$row->mailgrp)
{
$nomail = $row->gruppe_kurzbz . ' ';
}
else
{
$mailto .= mb_strtolower($row->gruppe_kurzbz . '@'
. DOMAIN . $variables['emailadressentrennzeichen']);
}
}
}
else
{
$mailto .= mb_strtolower($row->stg_typ . $row->stg_kurzbz
. $row->semester . trim($row->verband) . trim($row->gruppe)
. '@' . DOMAIN . $variables['emailadressentrennzeichen']);
}
}
if($nomail != '')
{
$c4_linkList[] = array(
$this->p->t('lehre', 'keinMailverteiler', array('nomail' => $nomail)),
'#'
);
$link_onclick = 'alert(\''.$this->p->t('lehre', 'keinMailverteiler', array('nomail' => $nomail)) . '\');';
}
else
{
$link_onclick = '';
}
$menu[]=array
(
'id'=>'core_menu_mailanstudierende',
'position'=>'100',
'name'=>$this->p->t('lehre', 'mail'),
'c4_icon'=>base_url('skin/images/button_feedback.png'),
'c4_icon2' => 'fa-regular fa-envelope',
'c4_link'=>$mailto,
'c4_linkList'=>$c4_linkList,
'link_onclick'=>$link_onclick
);
}
}
private function fhc_menu_abmeldung(&$menu, $user, $is_lector, $lvid, $angezeigtes_stsem){
if(!defined('CIS_LEHRVERANSTALTUNG_ABMELDUNG_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_ABMELDUNG_ANZEIGEN)
{
if(!$is_lector)
{
$gruppen = $this->Lvangebot_model->AbmeldungMoeglich($lvid, $angezeigtes_stsem, $user);
if(count($gruppen) > 0)
{
$menu[]=array
(
'id'=>'core_menu_abmeldung',
'position'=>'120',
'name'=>$this->p->t('lehre', 'abmelden'),
'c4_icon'=>base_url('skin/images/button_studiupload.png'),
'c4_link'=>base_url('abmeldung.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem)),
);
}
}
}
}
private function fhc_menu_lehretools(&$menu, $lvid, $angezeigtes_stsem, $sprache){
//Anzeigen von zusaetzlichen Lehre-Tools
$lehretools = $this->Lehretools_model->getTools($lvid, $angezeigtes_stsem, $sprache);
foreach($lehretools as $row)
{
$menu[] = array(
'id' => 'core_menu_lehretools_' . $row->lehre_tools_id,
'position' => '1000',
'name' => $row->bezeichnung,
'c4_icon' => base_url('cms/dms.php?id='.$row->logo_dms_id),
'c4_link' => $row->basis_url,
);
}
}
private function fhc_menu_anrechnungStudent(&$menu, $lvid, $angezeigtes_stsem){
// Anerkennung nachgewiesener Kenntnisse (Anrechnung) - Anzeige fuer Studenten
if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN)
&& $this->PermissionLib->isBerechtigt('student/anrechnung_beantragen'))
{
$menu[]=array
(
'id' => 'core_menu_anerkennungNachgewiesenerKenntnisse',
'position' => '128',
'name' => $this->p->t('lehre', 'anrechnung'),
'c4_icon' => base_url('skin/images/button_listen.png'),
'c4_icon2' => 'fa-regular fa-folder-open',
'c4_link' => base_url('cis.php/lehre/anrechnung/RequestAnrechnung?studiensemester='.urlencode($angezeigtes_stsem).'&lv_id='.urlencode($lvid))
);
}
}
private function fhc_menu_anrechnungLector(&$menu, $angezeigtes_stsem){
// Anerkennung nachgewiesener Kenntnisse (Anrechnung) - Anzeige fuer LektorInnen
if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN)
&& $this->PermissionLib->isBerechtigt('lehre/anrechnung_empfehlen'))
{
$menu[]=array
(
'id' => 'core_menu_anerkennungNachgewiesenerKenntnisse_empfehlen',
'position' => '128',
'name' => $this->p->t('lehre', 'anrechnungen'),
'c4_icon'=> base_url('skin/images/button_listen.png'),
'c4_icon2' => 'fa-regular fa-folder-open',
'c4_link' => base_url('cis.php/lehre/anrechnung/ReviewAnrechnungUebersicht?studiensemester='.urlencode($angezeigtes_stsem))
);
}
}
}
@@ -0,0 +1,95 @@
<?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 SearchBarLib (back-end)
* Provides data to the ajax get calls about the searchbar component
* This controller works with JSON calls on the HTTP GET and the output is always JSON
*/
class Ort extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
// NOTE(chris): additional permission checks will be done in SearchBarLib
parent::__construct([
'ContentID' => self::PERM_LOGGED,
'getOrtKurzbzContent' => self::PERM_LOGGED,
]);
$this->load->model('ressource/Ort_model', 'OrtModel');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Gets a JSON body via HTTP POST and provides the parameters
*/
public function ContentID()
{
// if error
//$this->terminateWithError(SearchBarLib::ERROR_WRONG_JSON, self::ERROR_TYPE_GENERAL);
$ort_kurzbz = $this->input->get('ort_kurzbz',TRUE);
if(!$ort_kurzbz){
$this->terminateWithError("missing ort_kurzbz parameter", self::ERROR_TYPE_GENERAL);
}
$result = $this->OrtModel->getContentID($ort_kurzbz);
if(isError($result)){
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$result = hasData($result) ? current(getData($result)) : null;
$this->terminateWithSuccess($result->content_id ?? NULL);
}
/**
* @param int $version
* @param string $sprache
* @param boolean $sichtbar
*
* @return $content
*/
public function getOrtKurzbzContent($version = null, $sprache = null, $sichtbar = true)
{
$content_id = $this->input->get("content_id",TRUE);
$this->load->library('CmsLib');
$content = $this->cmslib->getContent($content_id, $version, $sprache, $sichtbar);
if (isError($content))
$this->terminateWithError(getError($content), self::ERROR_TYPE_GENERAL);
$content = hasData($content) ? getData($content) : null;
$this->terminateWithSuccess($content);
}
}
@@ -28,8 +28,13 @@ class Phrasen extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
'loadModule' => self::PERM_ANONYMOUS
'loadModule' => self::PERM_ANONYMOUS,
'setLanguage' => self::PERM_ANONYMOUS,
'getLanguage' => self::PERM_ANONYMOUS,
'getAllLanguages' => self::PERM_ANONYMOUS,
]);
$this->load->helper('hlp_language');
}
//------------------------------------------------------------------------------------------------------------------
@@ -43,4 +48,48 @@ class Phrasen extends FHCAPI_Controller
$this->load->library('PhrasesLib', [$module], 'pj');
$this->terminateWithSuccess(json_decode($this->pj->getJSON()));
}
}
public function setLanguage()
{
$postParams = $this->getPostJSON();
$language = $postParams->language;
$categories = $postParams->categories;
setUserLanguage($language);
$this->load->library('PhrasesLib', array($categories, $language), 'p');
$phrases = $this->p->setPhrases($categories, $language);
$this->terminateWithSuccess($phrases);
}
// gets the langauge of the currently logged in user session and otherwhise the system language
public function getLanguage()
{
$lang = getUserLanguage();
$this->terminateWithSuccess($lang);
}
// gets all languages that are set as active in the database
public function getAllLanguages()
{
$this->load->model('system/Sprache_model', 'SprachenModel');
// Add order clause by index and select the sprache,bezeichnung and index column
$this->SprachenModel->addOrder('index');
$this->SprachenModel->addSelect('sprache, bezeichnung, index');
// Retrieves from public.tbl_sprache
$langs = $this->SprachenModel->loadWhere(array('content' => true));
$langs = $this->getDataOrTerminateWithError($langs);
$langs = array_map(function($lang){
$data = new stdClass();
$data->sprache = $lang->sprache;
$data->bezeichnung = $lang->bezeichnung[($lang->index-1)];
return $data;
}, $langs);
$this->terminateWithSuccess($langs);
}
}
@@ -0,0 +1,695 @@
<?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');
class Profil extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getView' => self::PERM_LOGGED,
'fotoSperre' => self::PERM_LOGGED,
'getGemeinden' => self::PERM_LOGGED,
'getAllNationen' => self::PERM_LOGGED,
'isMitarbeiter' => self::PERM_LOGGED,
]);
$this->load->library('PermissionLib');
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('person/Person_model', 'PersonModel');
$this->load->model('person/Adresse_model', 'AdresseModel');
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel');
$this->load->model('ressource/Betriebsmittelperson_model', 'BetriebsmittelpersonModel');
$this->load->model('person/Kontakt_model', 'KontaktModel');
$this->load->model('person/Profil_update_model', 'ProfilUpdateModel');
$this->load->model('content/DmsVersion_model', 'DmsVersionModel');
//? put the uid and pid inside the controller for reusability
$this->uid = getAuthUID();
$this->pid = getAuthPersonID();
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* function that returns the data used for the corresponding view
* the client side parses the @param $uid and calls this function to get the data to the correct view
* @access public
* @param boolean $uid the userID used to identify which information should be retrieved for which view
* @return stdClass all the data corresponding to a view of a user
*/
public function getView($uid)
{
$res = new stdClass();
$editAllowed = getAuthUID() == $uid || $this->permissionlib->isBerechtigt('admin');
// if parsing the URL did not found a UID then the UID of the logged in user is used
if ($uid == "Profil" || $uid == $this->uid) {
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($this->uid);
if (isError($isMitarbeiter)) {
show_error("error while checking if UID: " . $this->uid . " is a mitarbeiter");
}
$isMitarbeiter = getData($isMitarbeiter);
if ($isMitarbeiter) {
$res->view = "MitarbeiterProfil";
$res->data = $this->mitarbeiterProfil();
$res->data->pid = $this->pid;
} else {
$res->view = "StudentProfil";
$res->data = $this->studentProfil();
$res->data->pid = $this->pid;
}
// editing your own profil - true
$editAllowed = true;
}
// UID is availabe when accessing Profil/View/:uid
else {
$this->PersonModel->addSelect(["person_id"]);
$pid = $this->PersonModel->getByUid($uid);
if (isError($pid)) {
show_error("error while trying to update table public.tbl_person while searching for a person with UID: " . $uid);
}
$pid = hasData($pid) ? getData($pid)[0] : null;
if (!$pid) {
show_error("Person with UID: " . $uid . " does not exist");
}
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid);
if (isError($isMitarbeiter)) {
show_error("error while checking if UID: " . $uid . " is a mitarbeiter");
}
$isMitarbeiter = getData($isMitarbeiter);
if ($isMitarbeiter) {
$res->view = "ViewMitarbeiterProfil";
$res->data = $this->viewMitarbeiterProfil($uid);
} else {
$res->view = "ViewStudentProfil";
$res->data = $this->viewStudentProfil($uid);
}
}
$res->data->editAllowed = $editAllowed;
$this->terminateWithSuccess($res);
}
/**
* update column foto_sperre in public.tbl_person
* @access public
* @param boolean $value new value for the column
* @return boolean the new value added to the column in public.tbl_person
*/
public function fotoSperre($value)
{
if(!isset($value)){
$this->terminateWithError("Missing parameter", self::ERROR_TYPE_GENERAL);
}
$res = $this->PersonModel->update($this->pid, ["foto_sperre" => $value]);
if (isError($res)) {
show_error("error while trying to update table public.tbl_person");
}
$this->PersonModel->addSelect("foto_sperre");
$res = $this->PersonModel->load($this->pid);
if (isError($res)) {
show_error("error while trying to query table public.tbl_person");
}
$res = $this->getDataOrTerminateWithError($res);
$this->terminateWithSuccess(current($res));
}
/**
* gets all nations in the table bis.tbl_nation
*
* @access public
* @return array all the nations in table bis.tbl_nation
*/
public function getAllNationen()
{
// load the nationen from the database
$this->load->model('codex/Nation_model', "NationModel");
$this->NationModel->addSelect(["nation_code as code", "langtext"]);
$nation_res = $this->NationModel->load();
if (isError($nation_res)) {
$this->terminateWithError("error while trying to query table codex.tbl_nation", self::ERROR_TYPE_GENERAL);
}
$nation_res = $this->getDataOrTerminateWithError($nation_res);
$this->terminateWithSuccess($nation_res);
}
public function getGemeinden($nation, $zip)
{
if(!isset($nation) || !isset($zip)){
echo json_encode(error("Missing parameters"));
return;
}
$this->load->model('codex/Gemeinde_model', "GemeindeModel");
$gemeinde_res = $this->GemeindeModel->getGemeindeByPlz($zip);
if (isError($gemeinde_res)) {
$this->terminateWithError(getError($gemeinde_res),self::ERROR_TYPE_GENERAL);
}
$gemeinde_res = $this->getDataOrTerminateWithError($gemeinde_res);
/* $gemeinde_res = array_map(function ($obj) {
return $obj->ortschaftsname;
}, $gemeinde_res); */
$this->terminateWithSuccess($gemeinde_res);
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
/**
* function that returns the data used for viewing another mitarbeiter profile
* @access private
* @param integer $uid the userID to retrieve the mitarbeiter data
* @return stdClass restricted mitarbeiter data
*/
private function viewMitarbeiterProfil($uid)
{
$mailverteiler_res = $this->getMailverteiler($uid);
$benutzer_funktion_res = $this->getBenutzerFunktion($uid);
$benutzer_res = $this->getBenutzerAlias($uid);
$person_res = $this->getPersonInfo($uid);
$mitarbeiter_res = $this->getMitarbeiterInfo($uid);
$telefon_res = $this->getTelefonInfo($uid);
$res = new stdClass();
$res->username = $uid;
//? Person Info
foreach ($person_res as $key => $val) {
$res->$key = $val;
}
//? Mitarbeiter Info
foreach ($mitarbeiter_res as $key => $val) {
$res->$key = $val;
}
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $uid . "@" . DOMAIN;
$extern_email = array();
$extern_email["type"] = "alias";
$extern_email["email"] = $benutzer_res->alias . "@" . DOMAIN;
$res->emails = array($intern_email, $extern_email);
$res->funktionen = $benutzer_funktion_res;
$res->mailverteiler = $mailverteiler_res;
$res->standort_telefon = isset($telefon_res) ? $telefon_res->kontakt : null;
return $res;
}
/**
* function that returns the data used for viewing another student profile
* @access private
* @param integer $uid the userID to retrieve the student data
* @return stdClass restricted student data
*/
private function viewStudentProfil($uid)
{
$mailverteiler_res = $this->getMailverteiler($uid);
$person_res = $this->getPersonInfo($uid);
$student_res = $this->getStudentInfo($uid);
$matr_res = $this->getMatrikelNummer($uid);
$res = new stdClass();
$res->username = $uid;
//? Person Information
foreach ($person_res as $key => $value) {
$res->$key = $value;
}
//? Student Information
foreach ($student_res as $key => $value) {
$res->$key = $value;
}
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $uid . "@" . DOMAIN;
$res->emails = [$intern_email];
$res->matrikelnummer = $matr_res->matr_nr;
$res->mailverteiler = $mailverteiler_res;
return $res;
}
/**
* checks whether a specific userID is a mitarbeiter or not (foreword declaration of the function isMitarbeiter in Mitarbeiter_model.php)
* @access public
* @param $uid the userID used to check if it is a mitarbeiter
* @return boolean
*/
public function isMitarbeiter($uid)
{
if(!$uid) $this->terminateWithError("No uid provided", self::ERROR_TYPE_GENERAL);
$result = $this->MitarbeiterModel->isMitarbeiter($uid);
if (isError($result)) {
$this->terminateWithError("error when calling Mitarbeiter_model function isMitarbeiter with uid " . $uid, self::ERROR_TYPE_GENERAL);
}
$result = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($result);
}
/**
* function that returns the data used for the mitarbeiter profile
* @access private
* @return stdClass mitarbeiter data
*/
private function mitarbeiterProfil()
{
$zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid);
$adresse_res = $this->getAdressenInfo($this->pid);
$kontakte_res = $this->getKontaktInfo($this->pid);
$mailverteiler_res = $this->getMailverteiler($this->uid);
$person_res = $this->getPersonInfo($this->uid, true);
$benutzer_funktion_res = $this->getBenutzerFunktion($this->uid);
$betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid);
$profilUpdates = $this->getProfilUpdates($this->uid);
$telefon_res = $this->getTelefonInfo($this->uid);
$mitarbeiter_res = $this->getMitarbeiterInfo($this->uid);
$res = new stdClass();
$res->username = $this->uid;
//? Person Information
foreach ($person_res as $key => $value) {
$res->$key = $value;
}
//? Mitarbeiter Information
foreach ($mitarbeiter_res as $key => $value) {
$res->$key = $value;
}
$res->adressen = $adresse_res;
$res->zutrittsdatum = $zutrittskarte_ausgegebenam;
$res->kontakte = $kontakte_res;
$res->mittel = $betriebsmittelperson_res;
$res->mailverteiler = $mailverteiler_res;
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $this->uid . "@" . DOMAIN;
$extern_email = array();
$extern_email["type"] = "alias";
$extern_email["email"] = $mitarbeiter_res->alias . "@" . DOMAIN;
$res->emails = [$intern_email, $extern_email];
$res->funktionen = $benutzer_funktion_res;
$res->standort_telefon = $telefon_res;
$res->profilUpdates = $profilUpdates;
return $res;
}
/**
* function that returns the data used for the student profile
* @access private
* @return stdClass student data
*/
private function studentProfil()
{
$betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid);
$kontakte_res = $this->getKontaktInfo($this->pid);
$zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid);
$adresse_res = $this->getAdressenInfo($this->pid);
$mailverteiler_res = $this->getMailverteiler($this->uid);
$person_res = $this->getPersonInfo($this->uid, true);
$zutrittsgruppe_res = $this->getZutrittsgruppen($this->uid);
$student_res = $this->getStudentInfo($this->uid);
$matr_res = $this->getMatrikelNummer($this->uid);
$profilUpdates = $this->getProfilUpdates($this->uid);
$res = new stdClass();
$res->username = $this->uid;
//? Person Information
foreach ($person_res as $key => $value) {
$res->$key = $value;
}
//? Student Information
foreach ($student_res as $key => $value) {
$res->$key = trim($value);
}
$intern_email = array();
$intern_email["type"] = "intern";
$intern_email["email"] = $this->uid . "@" . DOMAIN;
$res->emails = [$intern_email];
$res->adressen = $adresse_res;
$res->zutrittsdatum = $zutrittskarte_ausgegebenam;
$res->kontakte = $kontakte_res;
$res->mittel = $betriebsmittelperson_res;
$res->matrikelnummer = $matr_res->matr_nr;
$res->zuttritsgruppen = $zutrittsgruppe_res;
$res->mailverteiler = $mailverteiler_res;
$res->profilUpdates = $profilUpdates;
return $res;
}
/**
* gets all the mailverteiler using the tables: tbl_benutzer, tbl_benutzergruppe, tbl_gruppe
* @access private
* @param integer $uid the userID used to retrieve the mailverteiler
* @return array returns the mailvertailer corresponding to a userID
*/
private function getMailverteiler($uid)
{
$this->PersonModel->addSelect('gruppe_kurzbz, beschreibung');
$this->PersonModel->addJoin('tbl_benutzer', 'person_id');
$this->PersonModel->addJoin('tbl_benutzergruppe', 'uid');
$this->PersonModel->addJoin('tbl_gruppe', 'gruppe_kurzbz');
$mailverteiler_res = $this->PersonModel->loadWhere(array('mailgrp' => true, 'uid' => $uid));
if (isError($mailverteiler_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($mailverteiler_res));
}
$mailverteiler_res = hasData($mailverteiler_res) ? getData($mailverteiler_res) : null;
$mailverteiler_res = array_map(function ($element) {
$element->mailto = "mailto:" . $element->gruppe_kurzbz . "@" . DOMAIN;
return $element;
}, $mailverteiler_res);
return $mailverteiler_res;
}
/**
* gets all the Benutzerfunktionen of a corresponding user
* @access private
* @param integer $uid the userID used to retrieve the Benutzerfunktionen
* @return array returns the Benutzerfunktionen corresponding to a userID
*/
private function getBenutzerFunktion($uid)
{
$this->BenutzerfunktionModel->addSelect(["tbl_benutzerfunktion.bezeichnung as Bezeichnung", "tbl_organisationseinheit.bezeichnung as Organisationseinheit", "datum_von as Gültig_von", "datum_bis as Gültig_bis", "wochenstunden as Wochenstunden"]);
$this->BenutzerfunktionModel->addJoin("tbl_organisationseinheit", "oe_kurzbz");
$benutzer_funktion_res = $this->BenutzerfunktionModel->loadWhere(array('uid' => $uid));
if (isError($benutzer_funktion_res)) {
show_error("was not able to query the table public.tbl_benutzerfunktion:" . getData($benutzer_funktion_res));
}
$benutzer_funktion_res = hasData($benutzer_funktion_res) ? getData($benutzer_funktion_res) : null;
return $benutzer_funktion_res;
}
/**
* gets all the Betriebsmittel of a corresponding user
* @access private
* @param integer $uid the userID used to retrieve the Betriebsmittel
* @return array returns the Betriebsmittel corresponding to a userID
*/
private function getBetriebsmittelInfo($pid)
{
$this->BetriebsmittelpersonModel->addSelect(["CONCAT(betriebsmitteltyp, ' ' ,beschreibung) as Betriebsmittel", "nummer as Nummer", "ausgegebenam as Ausgegeben_am"]);
//? betriebsmittel are not needed in a view
$betriebsmittelperson_res = $this->BetriebsmittelpersonModel->getBetriebsmittel($pid);
if (isError($betriebsmittelperson_res)) {
show_error("was not able to query the table public.tbl_betriebsmittelperson:" . getData($betriebsmittelperson_res));
}
$betriebsmittelperson_res = hasData($betriebsmittelperson_res) ? getData($betriebsmittelperson_res) : null;
return $betriebsmittelperson_res;
}
/**
* gets the alias of a corresponding user
* @access private
* @param integer $uid the userID used to get the alias
* @return string the alias of the userID
*/
private function getBenutzerAlias($uid)
{
$this->BenutzerModel->addSelect(["alias"]);
$benutzer_res = $this->BenutzerModel->load([$uid]);
if (isError($benutzer_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($benutzer_res));
} else {
$benutzer_res = hasData($benutzer_res) ? getData($benutzer_res)[0] : null;
}
return $benutzer_res;
}
/**
* gets the person information corresponding to a user
* @access private
* @param integer $uid the userID used to get the person information
* @param integer $geburtsInfo flag wether to add the columns gebort, gebdatum, foto_sperre or not
* @return array all the person informaion corresponding to a userID
*/
private function getPersonInfo($uid, $geburtsInfo = null)
{
$selectClause = ["foto", "foto_sperre", "anrede", "titelpost as postnomen", "titelpre as titel", "vorname", "nachname"];
/** @param integer $geburtsInfo */
if ($geburtsInfo) {
array_push($selectClause, "gebort");
array_push($selectClause, "TO_CHAR(gebdatum, 'DD.MM.YYYY') as gebdatum");
}
$this->BenutzerModel->addSelect($selectClause);
$this->BenutzerModel->addJoin("tbl_person", "person_id");
$person_res = $this->BenutzerModel->load([$uid]);
if (isError($person_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($person_res));
} else {
$person_res = hasData($person_res) ? getData($person_res)[0] : null;
}
if( ($person_res->foto === null) || (($this->uid !== $uid) && ($person_res->foto_sperre !== false)) )
{
$dummy_foto = base64_encode(file_get_contents(DOC_ROOT.'skin/images/profilbild_dummy.jpg'));
$person_res->foto = $dummy_foto;
}
return $person_res;
}
/**
* gets the mitarbeiter information corresponding to a user
* @access private
* @param integer $uid the userID used to get the mitarbeiter information
* @return array all the mitarbeiter informaion corresponding to a userID
*/
private function getMitarbeiterInfo($uid)
{
$this->MitarbeiterModel->addSelect(["kurzbz", "telefonklappe", "alias", "ort_kurzbz"]);
$this->MitarbeiterModel->addJoin("tbl_benutzer", "tbl_benutzer.uid = tbl_mitarbeiter.mitarbeiter_uid");
$mitarbeiter_res = $this->MitarbeiterModel->load($uid);
if (isError($mitarbeiter_res)) {
show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($mitarbeiter_res));
} else {
$mitarbeiter_res = hasData($mitarbeiter_res) ? getData($mitarbeiter_res)[0] : null;
}
return $mitarbeiter_res;
}
/**
* gets the telefon information corresponding to a user
* @access private
* @param integer $uid the userID used to get the telefon information
* @return array all the telefon informaion corresponding to a userID
*/
private function getTelefonInfo($uid)
{
$this->MitarbeiterModel->addSelect(["kontakt"]);
$this->MitarbeiterModel->addJoin("tbl_kontakt", "tbl_mitarbeiter.standort_id = tbl_kontakt.standort_id");
$this->MitarbeiterModel->addLimit(1);
$telefon_res = $this->MitarbeiterModel->loadWhere(["mitarbeiter_uid" => $uid, "kontakttyp" => "telefon"]);
if (isError($telefon_res)) {
show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($telefon_res));
}
$telefon_res = hasData($telefon_res) ? getData($telefon_res)[0] : null;
return $telefon_res;
}
/**
* gets the student information corresponding to a user
* @access private
* @param integer $uid the userID used to get the student information
* @return array all the student informaion corresponding to a userID
*/
private function getStudentInfo($uid)
{
$this->StudentModel->addSelect(['tbl_studiengang.bezeichnung as studiengang', 'tbl_studiengang.studiengang_kz as studiengang_kz', 'tbl_student.semester', 'tbl_student.verband', 'tbl_student.gruppe', 'tbl_student.matrikelnr as personenkennzeichen']);
$this->StudentModel->addJoin('tbl_studiengang', "tbl_studiengang.studiengang_kz=tbl_student.studiengang_kz");
$student_res = $this->StudentModel->load([$uid]);
if (isError($student_res)) {
show_error("was not able to query the table public.tbl_student:" . getData($student_res));
}
$student_res = hasData($student_res) ? getData($student_res)[0] : null;
return $student_res;
}
/**
* gets the profil updates corresponding to a user
* @access private
* @param integer $uid the userID used to get the profil updates
* @return array all the profil updates corresponding to a userID
*/
private function getProfilUpdates($uid)
{
$profilUpdates = $this->ProfilUpdateModel->getProfilUpdatesWhere(['uid' => $uid]);
if (isError($profilUpdates)) {
show_error("was not able to query the table public.tbl_profil_update:" . getData($profilUpdates));
}
$profilUpdates = hasData($profilUpdates) ? getData($profilUpdates) : null;
return $profilUpdates;
}
/**
* gets the Matrikelnummer corresponding to a user
* @access private
* @param integer $uid the userID used to get the Matrikelnummer
* @return integer the Matrikelnummer corresponding to a userID
*/
private function getMatrikelNummer($uid)
{
$this->BenutzerModel->addSelect(["matr_nr"]);
$this->BenutzerModel->addJoin("tbl_person", "person_id");
$matr_res = $this->BenutzerModel->load([$uid]);
if (isError($matr_res)) {
show_error("was not able to query the table public.tbl_benutzer:" . getData($matr_res));
}
$matr_res = hasData($matr_res) ? getData($matr_res)[0] : [];
return $matr_res;
}
/**
* gets the Zutrittsgruppen corresponding to a user
* @access private
* @param integer $uid the userID used to get the Zutrittsgruppen
* @return array all the Zutrittsgruppen corresponding to a userID
*/
private function getZutrittsgruppen($uid)
{
$this->BenutzergruppeModel->addSelect(['bezeichnung']);
$this->BenutzergruppeModel->addJoin('tbl_gruppe', 'gruppe_kurzbz');
$zutrittsgruppe_res = $this->BenutzergruppeModel->loadWhere(array("uid" => $uid, "zutrittssystem" => true));
if (isError($zutrittsgruppe_res)) {
show_error("was not able to query the table public.tbl_benutzergruppe:" . getData($zutrittsgruppe_res));
}
$zutrittsgruppe_res = hasData($zutrittsgruppe_res) ? getData($zutrittsgruppe_res) : null;
return $zutrittsgruppe_res;
}
/**
* gets the address information corresponding to a user
* @access private
* @param integer $uid the userID used to get the address information
* @return array all the address information corresponding to a userID
*/
private function getAdressenInfo($pid)
{
$adresse_res = $this->AdresseModel->addSelect(["adresse_id", "strasse", "tbl_adressentyp.bezeichnung as typ", "plz", "ort", "zustelladresse", "gemeinde", "nation"]);
$adresse_res = $this->AdresseModel->addOrder("zustelladresse", "DESC");
$adresse_res = $this->AdresseModel->addJoin("tbl_adressentyp", "typ=adressentyp_kurzbz");
$adresse_res = $this->AdresseModel->loadWhere(["person_id" => $pid]);
if (isError($adresse_res)) {
show_error("was not able to query the table public.tbl_adresse:" . getData($adresse_res));
}
$adresse_res = hasData($adresse_res) ? getData($adresse_res) : null;
return $adresse_res;
}
/**
* gets the kontakt information corresponding to a user
* @access private
* @param integer $uid the userID used to get the kontakt information
* @return array all the kontakt information corresponding to a userID
*/
private function getKontaktInfo($pid)
{
$this->KontaktModel->addSelect(['kontakttyp', 'kontakt_id', 'kontakt', 'tbl_kontakt.anmerkung', 'tbl_kontakt.zustellung']);
$this->KontaktModel->addJoin('public.tbl_standort', 'standort_id', 'LEFT');
$this->KontaktModel->addJoin('public.tbl_firma', 'firma_id', 'LEFT');
$this->KontaktModel->addOrder('kontakttyp, kontakt, tbl_kontakt.updateamum, tbl_kontakt.insertamum');
$kontakte_res = $this->KontaktModel->loadWhere(['person_id' => $pid]);
if (isError($kontakte_res)) {
show_error("was not able to query the table public.tbl_kontakt:" . getData($kontakte_res));
}
$kontakte_res = hasData($kontakte_res) ? getData($kontakte_res) : null;
return $kontakte_res;
}
/**
* gets the date of issue of the FH access card corresponding to a user
* @access private
* @param integer $uid the userID used to get the date of issue of the FH access card
* @return string the date of issue of the FH access card corresponding to a userID
*/
private function getZutrittskarteDatum($uid)
{
$zutrittskarte_ausgegebenam = $this->BetriebsmittelpersonModel->getBetriebsmittelByUid($uid, "Zutrittskarte");
if (isError($zutrittskarte_ausgegebenam)) {
show_error("was not able to query the table wavi.tbl_bentriebsmittelperson:" . getData($zutrittskarte_ausgegebenam));
}
$zutrittskarte_ausgegebenam = hasData($zutrittskarte_ausgegebenam) ? getData($zutrittskarte_ausgegebenam)[0]->ausgegebenam : null;
//? formats date from 01-01-2000 to 01.01.2000
$zutrittskarte_ausgegebenam = str_replace("-", ".", $zutrittskarte_ausgegebenam);
return $zutrittskarte_ausgegebenam;
}
}
@@ -0,0 +1,837 @@
<?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');
class ProfilUpdate extends FHCAPI_Controller
{
public static $STATUS_PENDING = NULL;
public static $STATUS_ACCEPTED = NULL;
public static $STATUS_REJECTED = NULL;
public static $TOPICS = [];
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getStatus' => self::PERM_LOGGED,
'getTopic' => self::PERM_LOGGED,
'getProfilRequestFiles' => self::PERM_LOGGED,
'getProfilUpdateWithPermission' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'],
'denyProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'],
'acceptProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'],
'selectProfilRequest' => self::PERM_LOGGED,
'insertProfilRequest' => self::PERM_LOGGED,
'updateProfilRequest' => self::PERM_LOGGED,
'deleteProfilRequest' => self::PERM_LOGGED,
'insertFile' => self::PERM_LOGGED,
'show' => self::PERM_LOGGED,
]);
$this->load->config('cis');
// Load language phrases
$this->loadPhrases(
array(
'ui',
'global',
'person',
'profil',
'profilUpdate'
)
);
$this->load->model('person/Profil_update_model', 'ProfilUpdateModel');
$this->load->model('person/Kontakt_model', 'KontaktModel');
$this->load->model('person/Adresse_model', 'AdresseModel');
$this->load->model('person/Adressentyp_model', 'AdressenTypModel');
$this->load->model('person/Person_model', 'PersonModel');
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('system/Sprache_model', 'SpracheModel');
$this->load->model('person/Profil_update_status_model', 'ProfilUpdateStatusModel');
$this->load->model('person/Profil_update_topic_model', 'ProfilUpdateTopicModel');
$this->load->library('DmsLib');
$this->load->library('PermissionLib');
//? put the uid and pid inside the controller for reusability
$this->uid = getAuthUID();
$this->pid = getAuthPersonID();
// setup the ProfilUpdate states
$this->ProfilUpdateStatusModel->addSelect(['status_kurzbz']);
$status_kurzbz = $this->ProfilUpdateStatusModel->load();
if (hasData($status_kurzbz)) {
list($status_pending, $status_accepted, $status_rejected) = getData($status_kurzbz);
self::$STATUS_PENDING = $status_pending->status_kurzbz;
self::$STATUS_ACCEPTED = $status_accepted->status_kurzbz;
self::$STATUS_REJECTED = $status_rejected->status_kurzbz;
}
// setup the ProfilUpdate topics
$this->ProfilUpdateTopicModel->addSelect(['topic_kurzbz']);
$topic_kurzbz = $this->ProfilUpdateTopicModel->load();
if (hasData($topic_kurzbz)) {
foreach (getData($topic_kurzbz) as $topic) {
self::$TOPICS[$topic->topic_kurzbz] = $topic->topic_kurzbz;
}
}
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getStatus()
{
$this->terminateWithSuccess([self::$STATUS_PENDING => self::$STATUS_PENDING, self::$STATUS_ACCEPTED => self::$STATUS_ACCEPTED, self::$STATUS_REJECTED => self::$STATUS_REJECTED]);
}
public function getTopic()
{
if(!count(self::$TOPICS)){
$this->terminateWithError('No topics found');
}
$this->terminateWithSuccess(self::$TOPICS);
}
public function show($dms_id)
{
$profil_update = $this->ProfilUpdateModel->loadWhere(['attachment_id' => $dms_id]);
$profil_update = hasData($profil_update) ? getData($profil_update)[0] : null;
//? checks if an profil update exists with the dms_id requested from the user
if ($profil_update) {
$is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($profil_update->uid));
$is_student_profil_update = getData($this->StudentModel->isStudent($profil_update->uid));
if (
$this->permissionlib->isBerechtigt('student/stammdaten:r') && $is_student_profil_update ||
$this->permissionlib->isBerechtigt('mitarbeiter/stammdaten:r') && $is_mitarbeiter_profil_update ||
$this->uid == $profil_update->uid
) {
// Get file to be downloaded from DMS
$download = $this->dmslib->download($dms_id);
$download = $this->getDataOrTerminateWithError($download);
// Download file
$this->outputFile($download);
} else {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_permission_error'));
}
} else {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_dms_error'));
}
}
public function selectProfilRequest()
{
$uid = $this->input->get('uid',true);
$id = $this->input->get('id',true);
$whereClause = ['uid' => $this->uid];
if (isset($uid))
$whereClause['uid'] = $uid;
if (isset($id))
$whereClause['id'] = $id;
$res = $this->ProfilUpdateModel->getProfilUpdatesWhere($whereClause);
$res = $this->getDataOrTerminateWithError($res);
$this->terminateWithSuccess($res);
}
public function insertProfilRequest()
{
$payload = $this->input->post('payload');
$topic = $this->input->post('topic',true);
$fileID = $this->input->post('fileID',true);
if(!isset($payload) || !isset($topic)){
$this->terminateWithError("required parameters are missing");
}
$identifier = array_key_exists("kontakt_id", $payload) ? "kontakt_id" : (array_key_exists("adresse_id", $payload) ? "adresse_id" : null);
$data = ["topic" => $topic, "uid" => $this->uid, "requested_change" => json_encode($payload), "insertamum" => "NOW()", "insertvon" => $this->uid, "status" => self::$STATUS_PENDING ?: 'Pending'];
//? insert fileID in the dataset if sent with post request
if (isset($fileID)) {
$data['attachment_id'] = $fileID;
}
//? loops over all updateRequests from a user to validate if the new request is valid
$res = $this->ProfilUpdateModel->getProfilUpdatesWhere(["uid" => $this->uid]);
$res = $this->getDataOrTerminateWithError($res);
//? the user cannot delete a zustelladresse/kontakt
if (isset($payload["delete"]) && $payload[$identifier == "kontakt_id" ? "zustellung" : "zustelladresse"]) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error'));
}
//? if the user tries to delete a adresse, checks whether the adresse is a heimatadresse, if so an error is raised
if (isset($payload["delete"]) && $identifier == "adresse_id") {
$adr = $this->AdresseModel->load($payload[$identifier]);
$adr = $this->getDataOrTerminateWithError($adr)[0];
if ($adr->heimatadresse) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error'));
}
}
if ($res) {
$pending_changes = array_filter($res, function ($element) {
return $element->status == (self::$STATUS_PENDING ?: "Pending");
});
foreach ($pending_changes as $update_request) {
$existing_change = $update_request->requested_change;
//? the user can add as many new kontakte/adressen as he likes
if (!isset($payload["add"]) && property_exists($existing_change, $identifier) && array_key_exists($identifier,$payload) && $existing_change->$identifier == $payload[$identifier]) {
//? the kontakt_id / adresse_id of a change has to be unique
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_changeTwice_error'));
}
//? if it is not updating any kontakt/adresse, the topic has to be unique
elseif (!$identifier && $update_request->topic == $topic) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_changeTopicTwice_error', ['0' => $update_request->topic]));
}
}
}
$insertID = $this->ProfilUpdateModel->insert($data);
if (isError($insertID)) {
$this->terminateWithError(getError($insertID));
} else {
$insertID = hasData($insertID) ? getData($insertID) : null;
//? sends emails to the correspondents of the $uid
$this->sendEmail_onProfilUpdate_insertion($this->uid, $insertID, $topic);
$this->terminateWithSuccess(success($insertID));
}
}
public function updateProfilRequest()
{
$topic = $this->input->post('topic', true);
$payload = $this->input->post('payload', true);
$ID = $this->input->post('ID', true);
$fileID = $this->input->post('fileID', true);//optional
if(!isset($topic) || !isset($payload) || !isset($ID)){
$this->terminateWithError("required parameters are missing");
}
$updateData = ["requested_change" => json_encode($payload), "updateamum" => "NOW()", "updatevon" => $this->uid];
if (isset($fileID)) {
$updateData['attachment_id'] = json_decode($fileID);
}
$updateID = $this->ProfilUpdateModel->update([$ID], $updateData);
//? insert fileID in the dataset if sent with post request
if (isError($updateID)) {
$this->terminateWithError(getError($updateID));
}
$updateID = $this->getDataOrTerminateWithError($updateID)[0];
$this->terminateWithSuccess(success($updateID));
}
public function deleteProfilRequest()
{
$requestID = $this->input->post('requestID', true);
$result = $this->ProfilUpdateModel->delete([$requestID]);
if (isError($result)) {
$this->terminateWithError(getError($result));
}
$this->terminateWithSuccess($result);
}
public function getProfilRequestFiles($id)
{
if(!$id){
$this->terminateWithError("parameter id is missing");
}
$this->ProfilUpdateModel->addSelect(["attachment_id"]);
$attachmentID = $this->ProfilUpdateModel->load([$id]);
if (isError($attachmentID)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_loading_error'),self::ERROR_TYPE_GENERAL);
}
//? get the attachmentID
$dms_id = $this->getDataOrTerminateWithError($attachmentID)[0]->attachment_id;
//? get the name to the file
$this->DmsVersionModel->addSelect(["name", "dms_id"]);
$attachment = $this->DmsVersionModel->load([$dms_id, 0]);
if (isError($attachment)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_dmsVersion_error'),self::ERROR_TYPE_GENERAL);
}
$attachment = $this->getDataOrTerminateWithError($attachment);
//? returns {name:..., dms_id:...}
$this->terminateWithSuccess($attachment);
}
public function denyProfilRequest()
{
$id = $this->input->post('profil_update_id', true);
$uid = $this->input->post('uid', true);
$topic = $this->input->post('topic', true);
$status_message = $this->input->post('status_message', true); //optional
if(!isset($id) || !isset($uid) || !isset($topic)){
$this->terminateWithError("parameter id, uid, topic or status_message is missing");
}
$is_mitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid);
$is_mitarbeiter = $this->getDataOrTerminateWithError($is_mitarbeiter);
$is_student = $this->StudentModel->isStudent($uid);
$is_student = $this->getDataOrTerminateWithError($is_student);
if (
$is_student && $this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) ||
$is_mitarbeiter && $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid")
) {
$this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_REJECTED);
$this->terminateWithSuccess($this->setStatusOnUpdateRequest($id, self::$STATUS_REJECTED, $status_message));
} else {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_permission_error'),self::ERROR_TYPE_GENERAL);
}
}
public function acceptProfilRequest()
{
$id = $this->input->post('profil_update_id', true);
$uid = $this->input->post('uid', true);
$topic = $this->input->post('topic', true);
$requested_change = $this->input->post('requested_change');
$status_message = $this->input->post('status_message', true); //optional
//? fetching person_id using UID
$personID = $this->PersonModel->getByUid($uid);
$personID = $this->getDataOrTerminateWithError($personID)[0]->person_id;
//! check for required information
if (!isset($id) || !isset($uid) || !isset($personID) || !isset($requested_change) || !isset($topic)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_requiredInformation_error'));
}
$is_mitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid);
$is_mitarbeiter = $this->getDataOrTerminateWithError($is_mitarbeiter);
$is_student = $this->StudentModel->isStudent($uid);
$is_student = $this->getDataOrTerminateWithError($is_student);
//? check if the permissions are set correctly
if (
$is_student && $this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) ||
$is_mitarbeiter && $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid")
) {
if (is_array($requested_change) && array_key_exists("adresse_id", $requested_change)) {
$insertID = $this->handleAdresse($requested_change, $personID);
$insertID = getData($insertID);
if (isset($insertID)) {
$requested_change['adresse_id'] = $insertID;
$update_res = $this->updateRequestedChange($id, $requested_change);
if (isError($update_res)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_address_error', [$insertID]));
}
}
} else if (is_array($requested_change) && array_key_exists("kontakt_id", $requested_change)) {
$insertID = $this->handleKontakt($requested_change, $personID);
$insertID = getData($insertID);
if (isset($insertID)) {
$requested_change['kontakt_id'] = $insertID;
$update_res = $this->updateRequestedChange($id, $requested_change);
if (isError($update_res)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_kontakt_error', [$insertID]));
}
}
} else {
switch ($topic) {
// mapping phrasen to database columns to make the update with the correct column names
case self::$TOPICS['Titel']:
$topic = "titelpre";
break;
case self::$TOPICS['Postnomen']:
$topic = "titelpost";
break;
case self::$TOPICS['Vorname']:
$topic = "vorname";
break;
case self::$TOPICS['Nachname']:
$topic = "nachname";
break;
default:
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_topic_error', [$topic]));
}
$result = $this->PersonModel->update($personID, [$topic => $requested_change["value"]]);
if (isError($result)) $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_insert_error'));
}
$this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_ACCEPTED);
$this->terminateWithSuccess($this->setStatusOnUpdateRequest($id, self::$STATUS_ACCEPTED, $status_message, $requested_change));
} else {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_permission_error'));
}
}
public function insertFile($replace)
{
$replace = json_decode($replace);
if (!count($_FILES)) {
$this->terminateWithError("No file available for upload");
}
//? if replace is set it contains the profil_update_id in which the attachment_id has to be replaced
if (isset($replace)) {
$this->ProfilUpdateModel->addSelect(["attachment_id"]);
$profilUpdate = $this->ProfilUpdateModel->load([$replace]);
if (isError($profilUpdate)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_loading_error'));
}
//? get the attachmentID
$dms_id = $this->getDataOrTerminateWithError($profilUpdate)[0]->attachment_id;
//? delete old dms_file of Profil Update
$deleteOldFile_result = $this->deleteOldVersionFile($dms_id);
if(!$deleteOldFile_result){
$this->terminateWithError("error while deleting the old file");
}
}
$files = $_FILES['files'];
$file_count = count($files['name']);
$res = [];
for ($i = 0; $i < $file_count; $i++) {
$_FILES['files']['name'] = $files['name'][$i];
$_FILES['files']['type'] = $files['type'][$i];
$_FILES['files']['tmp_name'] = $files['tmp_name'][$i];
$_FILES['files']['error'] = $files['error'][$i];
$_FILES['files']['size'] = $files['size'][$i];
$dms = [
"kategorie_kurzbz" => "profil_aenderung",
"version" => 0,
"name" => $_FILES['files']['name'],
"mimetype" => $_FILES['files']['type'],
"beschreibung" => $this->uid . " Profil Änderung",
"insertvon" => $this->uid,
"insertamum" => "NOW()",
];
$tmp_res = $this->dmslib->upload($dms, 'files', array("jpg", "png", "pdf"));
if(isError($tmp_res)){
$this->addError(getError($tmp_res));
}
$tmp_res = $this->getDataOrTerminateWithError($tmp_res);
array_push($res, $tmp_res);
}
$this->terminateWithSuccess($res);
}
public function getProfilUpdateWithPermission($status = null)
{
// early return if no status has been passed as argument
if (!isset($status)) {
echo json_encode($this->ProfilUpdateModel->getProfilUpdateWithPermission());
return;
}
// get the sprache of the user
$sprachenIndex = $this->SpracheModel->loadWhere(["sprache" => getUserLanguage()]);
$sprachenIndex = hasData($sprachenIndex) ? getData($sprachenIndex)[0]->index : null;
if (isset($sprachenIndex) && isset($status)) {
// get the corresponding status kurz_bz primary key out of the translation
$status = $this->ProfilUpdateStatusModel->execReadOnlyQuery("select * from public.tbl_profil_update_status where ? = ANY(bezeichnung_mehrsprachig)", [$status]);
$status = hasData($status) ? getData($status)[0]->status_kurzbz : null;
$res = $this->ProfilUpdateModel->getProfilUpdateWithPermission(isset($status) ? ['status' => $status] : null);
echo json_encode($res);
}
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
private function sendEmail_onProfilUpdate_insertion($uid, $profil_update_id, $topic)
{
if($this->config->item('cis_send_profil_update_mails') === false)
{
return;
}
$this->load->helper('hlp_sancho_helper');
$emails = [];
$is_mitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid);
if (isError($is_mitarbeiter)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error'));
}
$is_mitarbeiter = $this->getDataOrTerminateWithError($is_mitarbeiter);
//! if the $uid is a mitarbeiter and student, only the hr is notified by email
if ($is_mitarbeiter) {
//? user is not a student therefore he is a mitarbeiter, send email to Personalverwaltung
//? use constant variable MAIL_GST to mail to the personalverwaltung
$this->MitarbeiterModel->addSelect([TRUE]);
$this->MitarbeiterModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid");
//? check if the the userID is a mitarbeiter and if the benutzer is active
$res = $this->MitarbeiterModel->loadWhere(["public.tbl_mitarbeiter.mitarbeiter_uid" => $uid, "public.tbl_benutzer.aktiv" => TRUE]);
if (isError($res)) {
$this->terminateWithError("was not able to query the mitarbeiter and benutzer by the uid: " . $uid);
}
if (hasData($res)) {
array_push($emails, MAIL_GST);
} else {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error'));
}
} else {
//? if it is not a mitarbeiter, check whether it is a student and send email to studiengang
$is_student = $this->StudentModel->isStudent($uid);
if (isError($is_student)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_studentCheck_error'));
}
$is_student = $this->getDataOrTerminateWithError($is_student);
if ($is_student) {
//? Send email to the Studiengangsassistentinnen
$this->StudentModel->addSelect(["public.tbl_studiengang.email"]);
$this->StudentModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_student.student_uid");
$this->StudentModel->addJoin("public.tbl_prestudent", "public.tbl_benutzer.person_id = public.tbl_prestudent.person_id");
$this->StudentModel->addJoin("public.tbl_prestudentstatus", "public.tbl_prestudentstatus.prestudent_id = public.tbl_prestudent.prestudent_id");
$this->StudentModel->addJoin("public.tbl_studiengang", "public.tbl_studiengang.studiengang_kz = public.tbl_prestudent.studiengang_kz");
//* check if the benutzer itself is active
//* check if the student status is Student or Diplomand (active students)
$this->StudentModel->db->where_in("public.tbl_prestudentstatus.status_kurzbz", ['Student', 'Diplomand']);
$res = $this->StudentModel->loadWhere(["public.tbl_benutzer.aktiv" => TRUE, "public.tbl_student.student_uid" => $uid]);
if (isError($res)) {
$this->terminateWithError(getError($res));
} else {
$res = $this->getDataOrTerminateWithError($res);
foreach ($res as $emailObj) {
array_push($emails, $emailObj->email);
}
}
}
}
$mail_res = [];
//? sending email
foreach ($emails as $email) {
array_push($mail_res, sendSanchoMail("profil_update", ['uid' => $uid, 'topic' => $topic, 'href' => APP_ROOT . 'Cis/ProfilUpdate/id/' . $profil_update_id], $email, ("Profil Änderung von " . $uid)));
}
foreach ($mail_res as $m_res) {
if (!$m_res) {
$this->addError($this->p->t('profilUpdate', 'profilUpdate_email_error'));
}
}
}
private function sendEmail_onProfilUpdate_response($uid, $topic, $status)
{
if($this->config->item('cis_send_profil_update_mails') === false)
{
return;
}
$this->load->helper('hlp_sancho_helper');
$email = $uid . "@" . DOMAIN;
function languageQuery($language)
{
return "select index from public.tbl_sprache where sprache = '" + $language + "'";
}
$this->ProfilUpdateStatusModel->addSelect(["bezeichnung_mehrsprachig[(" . languageQuery('German') . ")] as status_de", "bezeichnung_mehrsprachig[(" . languageQuery('English') . ")] as status_en"]);
$status_translation = $this->ProfilUpdateStatusModel->loadWhere(["status_kurzbz" => $status]);
if (isError($status_translation)) {
$this->terminateWithError($this->p->t('profilUpdate', 'ProfilUpdateStatusTranslationError'));
}
$status_translation = hasData($status_translation) ? getData($status_translation)[0] : null;
if (isset($status_translation)) {
$mail_res = sendSanchoMail("profil_update_response", ['topic' => $topic, 'status_de' => $status_translation->status_de, 'status_en' => $status_translation->status_en, 'href' => APP_ROOT . 'Cis/Profil'], $email, ("Profil Änderung " . $this->p->t('profilUpdate', 'pending')));
if (!$mail_res) {
$this->addError($this->p->t('profilUpdate', 'profilUpdate_email_error'));
}
}
}
private function setStatusOnUpdateRequest($id, $status, $status_message)
{
return $this->ProfilUpdateModel->update([$id], ["status" => $status, "status_timestamp" => "NOW()", "status_message" => $status_message]);
}
private function updateRequestedChange($id, $requested_change)
{
return $this->ProfilUpdateModel->update([$id], ['requested_change' => json_encode($requested_change)]);
}
private function deleteOldVersionFile($dms_id)
{
// starting the transaction
$this->db->trans_start();
if (!isset($dms_id)) {
return;
}
//? delete the file from the profilUpdate first
$profilUpdateFileDelete = $this->ProfilUpdateModel->removeFileFromProfilUpdate($dms_id);
if(isError($profilUpdateFileDelete)){
$this->terminateWithError(getError($profilUpdateFileDelete));
}
//? delete all the different versions of the dms_file
$dmsVersions = $this->DmsVersionModel->loadWhere(["dms_id" => $dms_id]);
$dmsVersions = $this->getDataOrTerminateWithError($dmsVersions);
$dms_versions = array_map(function ($item) {
return $item->version;
}, $dmsVersions);
$test_array = array();
foreach ($dms_versions as $version) {
$delete_result = $this->dmslib->removeVersion($dms_id, $version);
array_push($test_array, $delete_result);
if(isError($delete_result)){
$this->addError(getError($delete_result));
}
}
// transaction complete
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE)
{
return false;
}
else
{
return true;
}
}
private function getOE_from_student($student_uid)
{
//? returns the oe_einheit eines Studenten
$query = "SELECT public.tbl_studiengang.oe_kurzbz
FROM public.tbl_student
JOIN public.tbl_studiengang ON tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz
WHERE public.tbl_student.student_uid = ?;";
$res = $this->StudentModel->execReadOnlyQuery($query, [$student_uid]);
$res = $this->getDataOrTerminateWithError($res, $this->p->t('profilUpdate', 'profilUpdate_loadingOE_error'));
$res = array_map(
function ($item) {
return $item->oe_kurzbz;
},
$res
);
return $res;
}
private function handleAdresse($requested_change, $personID)
{
$this->AdressenTypModel->addSelect(["adressentyp_kurzbz"]);
$adr_kurzbz = $this->AdressenTypModel->loadWhere(["bezeichnung" => $requested_change['typ']]);
$adr_kurzbz = $this->getDataOrTerminateWithError($adr_kurzbz)[0]->adressentyp_kurzbz;
//? replace the address_typ with its correct kurzbz foreign key
$requested_change['typ'] = $adr_kurzbz;
$adresse_id = $requested_change["adresse_id"];
//? removes the adresse_id because we don't want to update the kontakt_id in the database
unset($requested_change["adresse_id"]);
//! ADD
if (array_key_exists('add', $requested_change) && $requested_change['add']) {
//? removes add flag
unset($requested_change['add']);
$requested_change['insertamum'] = "NOW()";
$requested_change['insertvon'] = getAuthUID();
$requested_change['person_id'] = $personID;
//TODO: zustelladresse, heimatadresse, rechnungsadresse und nation werden nicht beachtet
$insertID = $this->AdresseModel->insert($requested_change);
$insert_adresse_id = $insertID;
$insert_adresse_id = $this->getDataOrTerminateWithError($insert_adresse_id, $this->p->t('profilUpdate', 'profilUpdate_insertAdresse_error'));
if ($insert_adresse_id) {
$this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $insert_adresse_id);
}
}
//! DELETE
elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) {
$result = $this->AdresseModel->delete($adresse_id);
if (isError($result)) {
$this->terminateWithError(getError($result));
}
}
//! UPDATE
else {
$requested_change['updateamum'] = "NOW()";
$requested_change['updatevon'] = getAuthUID();
$update_adresse_id = $this->AdresseModel->update($adresse_id, $requested_change);
$update_adresse_id = $this->getDataOrTerminateWithError($update_adresse_id, $this->p->t('profilUpdate', 'profilUpdate_updateAdresse_error'));
$this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $update_adresse_id);
}
return $insertID ?? null;
}
private function handleKontakt($requested_change, $personID)
{
$kontakt_id = $requested_change["kontakt_id"];
//? removes the kontakt_id because we don't want to update the kontakt_id in the database
unset($requested_change["kontakt_id"]);
//! ADD
if (array_key_exists('add', $requested_change) && $requested_change['add']) {
//? removes add flag
unset($requested_change['add']);
$requested_change['person_id'] = $personID;
$requested_change['insertamum'] = "NOW()";
$requested_change['insertvon'] = getAuthUID();
$insertID = $this->KontaktModel->insert($requested_change);
$insert_kontakt_id = $insertID;
$insert_kontakt_id = $this->getDataOrTerminateWithError($insert_kontakt_id, $this->p->t('profilUpdate', 'profilUpdate_insertKontakt_error'));
if ($insert_kontakt_id) {
$this->handleDupplicateZustellKontakte($requested_change['zustellung'], $insert_kontakt_id);
}
}
//! DELETE
elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) {
$result = $this->KontaktModel->delete($kontakt_id);
if (isError($result)) {
$this->terminateWithError(getError($result));
}
}
//! UPDATE
else {
$requested_change['updateamum'] = "NOW()";
$requested_change['updatevon'] = getAuthUID();
$update_kontakt_id = $this->KontaktModel->update($kontakt_id, $requested_change);
$update_kontakt_id = $this->getDataOrTerminateWithError($update_kontakt_id, $this->p->t('profilUpdate', 'profilUpdate_updateKontakt_error'));
if ($update_kontakt_id) {
$this->handleDupplicateZustellKontakte($requested_change['zustellung'], $update_kontakt_id);
}
}
return isset($insertID) ? $insertID : null;
}
private function handleDupplicateZustellAdressen($zustellung, $adresse_id)
{
if ($zustellung) {
$this->PersonModel->addSelect("public.tbl_adresse.adresse_id");
$this->PersonModel->addJoin("public.tbl_adresse", "public.tbl_adresse.person_id = public.tbl_person.person_id");
$zustellAdressenArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustelladresse" => TRUE]);
if (isError($zustellAdressenArray)) {
$this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_loadingZustellAdressen_error'));
}
$zustellAdressenArray = $this->getDataOrTerminateWithError($zustellAdressenArray);
if (count($zustellAdressenArray) > 0) {
$zustellAdressenArray = array_filter($zustellAdressenArray, function ($adresse) use ($adresse_id) {
return $adresse->adresse_id != $adresse_id;
});
// remove the zustelladresse from all other zustelladressen
foreach ($zustellAdressenArray as $adresse) {
$this->AdresseModel->update($adresse->adresse_id, ["zustelladresse" => FALSE]);
}
}
}
}
private function handleDupplicateZustellKontakte($zustellung, $kontakt_id)
{
if ($zustellung) {
$this->PersonModel->addSelect("public.tbl_kontakt.kontakt_id");
$this->PersonModel->addJoin("public.tbl_kontakt", "public.tbl_kontakt.person_id = public.tbl_person.person_id");
$zustellKontakteArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustellung" => TRUE]);
if (!isSuccess($zustellKontakteArray)) {
return error($this->p->t('profilUpdate', 'profilUpdate_loadingZustellkontakte_error'));
}
$zustellKontakteArray = hasData($zustellKontakteArray) ? getData($zustellKontakteArray) : null;
if ($zustellung && count($zustellKontakteArray) > 0) {
$zustellKontakteArray = array_filter($zustellKontakteArray, function ($kontakt) use ($kontakt_id) {
return $kontakt->kontakt_id != $kontakt_id;
});
foreach ($zustellKontakteArray as $kontakt) {
$this->KontaktModel->update($kontakt->kontakt_id, ["zustellung" => FALSE]);
}
}
}
}
}
@@ -0,0 +1,65 @@
<?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');
class Studgang extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getStudiengangInfo'=> self::PERM_LOGGED,
]);
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
// Loads phrases system
$this->loadPhrases([
'global'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getStudiengangInfo(){
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID());
$isMitarbeiter = $this->getDataOrTerminateWithError($isMitarbeiter);
if($isMitarbeiter) {
$this->terminateWithSuccess(null);
}
// fetches the Studiengang Information which is used next to the news
$studiengangInfo = $this->StudiengangModel->getStudiengangInfoForNews();
$studiengangInfo= $this->getDataOrTerminateWithError($studiengangInfo);
$this->terminateWithSuccess($studiengangInfo);
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
}
@@ -0,0 +1,618 @@
<?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');
class Stundenplan extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getRoomplan' => self::PERM_LOGGED,
'Stunden' => self::PERM_LOGGED,
'Reservierungen' => self::PERM_LOGGED,
'getStundenplan' => self::PERM_LOGGED,
'getLehreinheitStudiensemester' => self::PERM_LOGGED,
'studiensemesterDateInterval' => self::PERM_LOGGED,
]);
$this->load->library('LogLib');
$this->loglib->setConfigs(array(
'classIndex' => 5,
'functionIndex' => 5,
'lineIndex' => 4,
'dbLogType' => 'API', // required
'dbExecuteUser' => 'RESTful API'
));
$this->load->library('form_validation');
//load models
$this->load->model('ressource/Stundenplan_model', 'StundenplanModel');
$this->load->model('ressource/Reservierung_model', 'ReservierungModel');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
//TODO: delete this function if we don't use the old calendar export endpoints anymore
public function studiensemesterDateInterval($date){
$this->load->model('organisation/Studiensemester_model','StudiensemesterModel');
$studiensemester =$this->StudiensemesterModel->getByDate(date_format(date_create($date),'Y-m-d'));
$studiensemester =current($this->getDataOrTerminateWithError($studiensemester));
$this->terminateWithSuccess($studiensemester);
}
/**
* fetches Stunden layout from database
* @access public
*
*/
public function Stunden()
{
$this->load->model('ressource/Stunde_model', 'StundeModel');
$stunden = $this->StundeModel->load();
$stunden = $this->getDataOrTerminateWithError($stunden);
$this->terminateWithSuccess($stunden);
}
/**
* fetches room events from a certain date
* @access public
*
*/
public function getRoomplan()
{
// form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('ort_kurzbz',"Ort","required");
$this->form_validation->set_rules('start_date',"start_date","required");
$this->form_validation->set_rules('end_date',"end_date","required");
if($this->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
// storing the get parameter in local variables
$ort_kurzbz = $this->input->get('ort_kurzbz', TRUE);
$start_date = $this->input->get('start_date', TRUE);
$end_date = $this->input->get('end_date', TRUE);
$roomplan_data = $this->StundenplanModel->stundenplanGruppierung($this->StundenplanModel->getRoomQuery($ort_kurzbz, $start_date, $end_date));
$roomplan_data = $this->getDataOrTerminateWithError($roomplan_data);
$this->expand_object_information($roomplan_data);
$this->terminateWithSuccess($roomplan_data);
}
/**
* fetches stundenplan events from a UID and start/end date
* @access public
*
*/
public function getStundenplan(){
$this->load->model('ressource/Mitarbeiter_model','MitarbeiterModel');
$this->load->model('organisation/Studiensemester_model','StudiensemesterModel');
$this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
$this->load->model('person/Benutzergruppe_model','BenutzergruppeModel');
// form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('start_date', "start_date", "required");
$this->form_validation->set_rules('end_date', "end_date", "required");
if ($this->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->form_validation->error_array());
// storing the get parameter in local variables
$start_date = $this->input->get('start_date', TRUE);
$end_date = $this->input->get('end_date', TRUE);
$lv_id = $this->input->get('lv_id', TRUE);
$student_uid = getAuthUID();
if(is_null($student_uid))
{
$this->terminateWithError("No UID");
}
$semester_range = $this->studienSemesterErmitteln($start_date,$end_date);
$this->sortStudienSemester($semester_range);
$this->applyLoadUeberSemesterHaelfte($semester_range);
if($lv_id) { // fetch Stundenplan for lva, irrelevant of who is requesting it (for now)
$stundenplan_data = $this->StundenplanModel->getStundenplanLVA($start_date, $end_date, $lv_id);
$stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? [];
$this->expand_object_information($stundenplan_data);
// query lv itself in case its Stundenplan is being queried and it has no entries
$this->load->model('education/Lehrveranstaltung_model','LehrveranstaltungModel');
$lv = getData($this->LehrveranstaltungModel->load($lv_id))[0];
$this->addMeta('lv', $lv);
$this->terminateWithSuccess($stundenplan_data);
}
$is_mitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter($student_uid));
if($is_mitarbeiter)
{
$stundenplan_data = $this->StundenplanModel->getStundenplanMitarbeiter($start_date, $end_date, $student_uid);
$stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? [];
$this->expand_object_information($stundenplan_data);
$this->terminateWithSuccess($stundenplan_data);
} else {
// getting the gruppen_kurzbz of the student in the different studiensemester
$benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($semester_range);
// getting the student_lehrverbaende of the student in the different studiensemester
$student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($semester_range);
$stundenplan_query = $this->StundenplanModel->getStundenplanQuery($start_date, $end_date, $semester_range, $benutzer_gruppen, $student_lehrverband);
if(!$stundenplan_query)
{
$this->terminateWithSuccess([]);
}
$stundenplan_data = $this->StundenplanModel->stundenplanGruppierung($stundenplan_query);
$stundenplan_data = $this->getDataOrTerminateWithError($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);
}
}
// gets the reservierungen of a room if the ort_kurzbz parameter is supplied otherwise gets the reservierungen of the stundenplan of a student
public function Reservierungen($ort_kurzbz = null)
{
//form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('start_date', "StartDate", "required");
$this->form_validation->set_rules('end_date', "EndDate", "required");
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$this->load->model('ressource/Mitarbeiter_model','MitarbeiterModel');
// storing the get parameter in local variables
$start_date = $this->input->get('start_date', TRUE);
$end_date = $this->input->get('end_date', TRUE);
$is_mitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter(getAuthUID()));
if($is_mitarbeiter)
{
$reservierungen = $this->ReservierungModel->getReservierungenMitarbeiter($start_date, $end_date, $ort_kurzbz);
} else {
// querying the reservierungen
$reservierungen = $this->ReservierungModel->getReservierungen($start_date, $end_date, $ort_kurzbz);
}
$reservierungen = $this->getDataOrTerminateWithError($reservierungen) ?? [];
$this->expand_object_information($reservierungen);
$this->terminateWithSuccess($reservierungen);
}
public function getLehreinheitStudiensemester($lehreinheit_id){
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$this->LehreinheitModel->addSelect(["studiensemester_kurzbz"]);
$result = $this->LehreinheitModel->load($lehreinheit_id);
$result = current($this->getDataOrTerminateWithError($result))->studiensemester_kurzbz;
$this->terminateWithSuccess($result);
}
// ################# Private Functions
private function expand_object_information($data){
foreach ($data as $item)
{
$lektor_obj_array = array();
$gruppe_obj_array = array();
// load lektor object
foreach ($item->lektor as $lv_lektor)
{
$this->StundenplanModel->addLimit(1);
$lektor_object = $this->StundenplanModel->execReadOnlyQuery("
SELECT mitarbeiter_uid, vorname, nachname, kurzbz
FROM public.tbl_mitarbeiter
JOIN public.tbl_benutzer benutzer ON benutzer.uid = mitarbeiter_uid
JOIN public.tbl_person person ON person.person_id = benutzer.person_id
WHERE kurzbz = ?", [$lv_lektor]);
if (isError($lektor_object)) {
$this->show_error(getError($lektor_object));
}
$lektor_object = $this->getDataOrTerminateWithError($lektor_object);
if(count($lektor_object) == 0)
{
$this->terminateWithError("No lektor object");
}
$lektor_object = current($lektor_object);
// only provide needed information of the mitarbeiter object
$lektor_obj_array[] = $lektor_object;
}
// load gruppe object
foreach ($item->gruppe as $lv_gruppe)
{
$lv_gruppe = strtr($lv_gruppe, ['(' => '', ')' => '', '"' => '']);
$lv_gruppe_array = explode(",", $lv_gruppe);
list($gruppe, $verband, $semester, $studiengang_kz, $gruppen_kuerzel) = $lv_gruppe_array;
$lv_gruppe_object = new stdClass();
$lv_gruppe_object->gruppe = $gruppe;
$lv_gruppe_object->verband = $verband;
$lv_gruppe_object->semester = $semester;
$lv_gruppe_object->studiengang_kz = $studiengang_kz;
$lv_gruppe_object->kuerzel = $gruppen_kuerzel;
$gruppe_obj_array[] = $lv_gruppe_object;
}
if($item->ort_kurzbz) {
$ort_content_object = $this->StundenplanModel->execReadOnlyQuery("
SELECT content_id
FROM public.tbl_ort
WHERE ort_kurzbz = ?", [$item->ort_kurzbz]);
if (isError($ort_content_object)) {
$this->show_error(getError($ort_content_object));
}
$ort_content_object = getData($ort_content_object)[0];
if($ort_content_object) {
$item->ort_content_id = $ort_content_object->content_id;
}
}
$item->gruppe = $gruppe_obj_array;
$item->lektor = $lektor_obj_array;
}
}
// function used to sort an array of studiensemester strings
private function sortStudienSemester(&$semester_range){
usort(
$semester_range,
function($first,$second)
{
$sem_first = null;
$year_first = null;
$match_first = null;
$sem_second = null;
$year_second = null;
$match_second = null;
preg_match('/([WS]+)([0-9]+)/',$first,$match_first);
preg_match('/([WS]+)([0-9]+)/',$second,$match_second);
$sem_first = $match_first[1];
$year_first = intval($match_first[2]);
$sem_second = $match_second[1];
$year_second = intval($match_second[2]);
if($year_first < $year_second)
{
return -1;
}
else if($year_first > $year_second)
{
return 1;
}
else if($year_first == $year_second && $sem_first > $sem_second)
{
return 1;
}
else if($year_first == $year_second && $sem_first < $sem_second)
{
return -1;
}
return 0;
}
);
}
private function fetchBenutzerGruppenFromStudiensemester($semester_range){
$student_uid = getAuthUID();
$benutzer_gruppen = [];
// for each studiensemester fetch the benutzer gruppen and add them to an associate $bentuzer_gruppen array
/*
[
['WS2023'] => [['gruppe1_SS2023','gruppe2_SS2023'],['gruppe1_WS2023','gruppe2_WS2023']],
['SS2024'] => [['gruppe1_WS2023','gruppe2_WS2023'],['gruppe1_SS2024','gruppe2_SS2024']],
['WS2024'] => [['gruppe1_SS2024','gruppe2_SS2024'],['gruppe1_WS2024','gruppe2_WS2024']],
]
*/
foreach($semester_range as $semester_key => $semester_array)
{
$benutzer_gruppen[$semester_key] = [];
// each semester could have ajoint semesters that need to be checked
foreach($semester_array as $semester=>$semester_date_range)
{
// for each active semester query the benutzer_gruppen associated to the semester
$benutzer_query = $this->BenutzergruppeModel->execReadOnlyQuery("
SELECT * FROM tbl_benutzergruppe where uid = ? AND studiensemester_kurzbz = ?",[$student_uid, $semester]);
$benutzer_query_result = $this->getDataOrTerminateWithError($benutzer_query);
array_push(
$benutzer_gruppen[$semester_key],
array_map(
function($item)
{
return "'".$item->gruppe_kurzbz. "'";
},
$benutzer_query_result
)
);
}
}
// merge the gruppen of each studiensemester together for the original studiensemester
/*
[
['WS2023'] => ['gruppe1_SS2023','gruppe2_SS2023','gruppe1_WS2023','gruppe2_WS2023'],
['SS2024'] => ['gruppe1_WS2023','gruppe2_WS2023','gruppe1_SS2024','gruppe2_SS2024'],
['WS2024'] => ['gruppe1_SS2024','gruppe2_SS2024','gruppe1_WS2024','gruppe2_WS2024'],
]
*/
$benutzer_gruppen = array_map(
function($gruppe)
{
$merged_gruppe = [];
foreach($gruppe as $gruppen_array)
{
$merged_gruppe = array_merge($merged_gruppe, $gruppen_array);
}
return $merged_gruppe;
},
$benutzer_gruppen
);
return $benutzer_gruppen;
}
private function fetchStudentlehrverbandFromStudiensemester($semester_range){
$student_uid = getAuthUID();
$student_lehrverband = [];
// for each studiensemester fetch the studentlehrverbaende and add them to an associate $student_lehrverband array
/*
[
['WS2023'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ] ],
['SS2024'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ] ],
['WS2024'] => [ [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ] ],
]
*/
foreach($semester_range as $semester_key => $semester_array)
{
$student_lehrverband[$semester_key] = [];
foreach($semester_array as $semester=>$semester_date_range)
{
// for each active semester query the student_lehrverband associated to the semester
$lehrverband_query = $this->BenutzergruppeModel->execReadOnlyQuery("
SELECT * FROM tbl_studentlehrverband where student_uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]);
$lehrverband_query_result = $this->getDataOrTerminateWithError($lehrverband_query);
array_push($student_lehrverband[$semester_key], array_map(
function ($item)
{
$result = new stdClass();
$result->studiengang_kz = $item->studiengang_kz;
$result->semester = $item->semester;
$result->verband = $item->verband;
$result->gruppe = $item->gruppe;
return $result;
},
$lehrverband_query_result));
}
}
// merge the studentlehrverband of each studiensemester together for the original studiensemester
/*
[
['WS2023'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ],
['SS2024'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ],
['WS2024'] => [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ],
]
*/
$student_lehrverband = array_map(
function($studentlehrverband)
{
$merged_studentlehrverband = [];
foreach($studentlehrverband as $studentlehrverband_array)
{
$merged_studentlehrverband = array_merge($merged_studentlehrverband, $studentlehrverband_array);
}
return $merged_studentlehrverband;
},
$student_lehrverband
);
return $student_lehrverband;
}
private function applyLoadUeberSemesterHaelfte(&$semester_range){
/*
@var($semester_collection)
convert the array of studiensemester into an associative array with the studiensemester as the key
and the values of each key are the studiensemester needed for the query associated to that studiensemester
example:
#INPUT:
['WS2023','SS2024','WS2024']
#OUTPUT:
[
'WS2023' => ['SS2023','WS2023']
'SS2024' => ['WS2023','SS2024']
'WS2024' => ['SS2024','WS2024']
]
*/
$semester_collection = [];
foreach($semester_range as $studiensemester)
{
$previous_studiensemester = $this->StudiensemesterModel->getPreviousFrom($studiensemester);
$previous_studiensemester = $this->getDataOrTerminateWithError($previous_studiensemester);
if (count($previous_studiensemester) == 0) {
$this->terminateWithError("No previous semester");
}
$previous_studiensemester = current($previous_studiensemester)->studiensemester_kurzbz;
$semester_collection[$studiensemester] = [$previous_studiensemester, $studiensemester];
}
/*
@var($studienSemesterDateRanges)
fetches for each studiensemester the start and end date, (SS) summer studiensemester are extended by 1 month to cover the summerbreak
based on the LVPLAN_LOAD_UEBER_SEMESTERHAELFTE constant it will load both the semester and the previous semester with the full date range
or the semester with the full date range and the previous semester with the half date range:
#INPUT:
[
'WS2023' => ['SS2023','WS2023']
'SS2024' => ['WS2023','SS2024']
'WS2024' => ['SS2024','WS2024']
]
#OUTPUT: depends whether LVPLAN_LOAD_UEBER_SEMESTERHAELFTE is true or false
~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == true
[
"SS2024": [
"WS2023": [
"start"=> "2024-02-03",
"ende"=> "2024-08-31"
],
"SS2024": [
"start"=> "2024-02-03",
"ende"=> "2024-08-31"
]
]
]
~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == false
[
"SS2024": [
"WS2023": [
"start"=> "2024-02-03",
"ende"=> "2024-05-17"
],
"SS2024": [
"start"=> "2024-02-03",
"ende"=> "2024-08-31"
]
]
]
*/
$studienSemesterDateRanges=[];
foreach($semester_collection as $semester_original => $semester_adjoint)
{
$semester_start_ende = $this->StudiensemesterModel->getStartEndeFromStudiensemester($semester_original);
$semester_start_ende = current($this->getDataOrTerminateWithError($semester_start_ende));
// initialize empty arrays to add key value pairs
$studienSemesterDateRanges[$semester_original] = [];
// check if the studiensemester is a summer semester and add 1 month to bridge the school summer break
$match = null;
preg_match("/^(SS)([0-9]+)/",$semester_original,$match);
if(count($match) >0)
{
$one_month = new DateInterval('P1M');
$one_day = DateInterval::createFromDateString('1 days');
$summer_studiensemester_end_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->ende);
$summer_studiensemester_end_date->add($one_month);
$summer_studiensemester_end_date->sub($one_day);
$semester_start_ende->ende = date_format($summer_studiensemester_end_date,'Y-m-d');
}
if (defined('LVPLAN_LOAD_UEBER_SEMESTERHAELFTE') && LVPLAN_LOAD_UEBER_SEMESTERHAELFTE === true)
{
foreach($semester_adjoint as $adjoint)
{
$studienSemesterDateRanges[$semester_original][$adjoint]=$semester_start_ende;
}
}
else
{
//TODO: half of a DateInterval might not be correctly calculated
// calculate the half of the studiensemester
$studiensemester_start_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->start);
$studiensemester_end_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->ende);
$studiensemester_time_difference = $studiensemester_start_date->diff($studiensemester_end_date);
$half_dateNumber = ceil($studiensemester_time_difference->d/2)+ceil(($studiensemester_time_difference->m*30)/2);
$half_dateInterval = new DateInterval('P'.strval($half_dateNumber) .'D');
$studiensemester_half = date_format($studiensemester_start_date->add($half_dateInterval),'Y-m-d');
$first_half = new stdClass();
$first_half->start = $semester_start_ende->start;
$first_half->ende = $studiensemester_half;
$studienSemesterDateRanges[$semester_original][$semester_adjoint[0]] = $first_half;
$studienSemesterDateRanges[$semester_original][$semester_adjoint[1]] = $semester_start_ende;
}
$semester_range = $studienSemesterDateRanges;
}
}
private function studienSemesterErmitteln($start_date,$end_date){
// gets all studiensemester from the student from start_date to end_date
$semester_range = $this->StudiensemesterModel->getByDateRange($start_date,$end_date);
$semester_range = array_map(
function($sem)
{
return $sem->studiensemester_kurzbz;
},
$this->getDataOrTerminateWithError($semester_range)
);
// if no studiensemester is found for the given timespan, get the nearest studiensemester
if(count($semester_range) == 0)
{
$aktuelle_studiensemester = $this->StudiensemesterModel->getNearest();
$aktuelle_studiensemester = $this->getDataOrTerminateWithError($aktuelle_studiensemester);
if (count($aktuelle_studiensemester) == 0) {
$this->terminateWithError("No aktuelles semester");
}
$aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz;
// push aktuelles semester in active semester array
array_push($semester_range, $aktuelle_studiensemester);
}
return $semester_range;
}
}
@@ -342,7 +342,7 @@ class BetriebsmittelP extends FHCAPI_Controller
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess(current(getData($result)));
return $this->terminateWithSuccess(current(getData($result)));
}
public function deleteBetriebsmittel($betriebsmittelperson_id)
@@ -358,7 +358,7 @@ class BetriebsmittelP extends FHCAPI_Controller
if (!hasData($result)) {
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(current(getData($result)));
$this->terminateWithSuccess(current(getData($result)));
}
public function getTypenBetriebsmittel()
@@ -0,0 +1,141 @@
<?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');
class CheckPerson extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'updatePersonUnrulyStatus' => array('basis/mitarbeiter:rw', 'student/antragfreigabe:rw', 'student/studierendenantrag:rw'),
'filterPerson' => array('basis/mitarbeiter:rw', 'student/antragfreigabe:rw', 'student/studierendenantrag:rw'),
'checkUnruly' => array('basis/mitarbeiter:r', 'student/antragfreigabe:r', 'student/studierendenantrag:r', 'infocenter:r'),
'checkDuplicate' => array('infocenter:r'),
]);
$this->_ci =& get_instance();
$this->_ci->load->model('person/Person_model', 'PersonModel');
}
public function updatePersonUnrulyStatus()
{
$data = json_decode($this->input->raw_input_stream, true);
$person_id = $data['person_id'];
$unruly = $data['unruly'];
$result = $this->_ci->PersonModel->updateUnruly($person_id, $unruly);
if(isError($result)) {
$this->terminateWithError($result);
} else if (isSuccess($result)) {
$this->terminateWithSuccess($result);
}
}
public function checkDuplicate() {
$person_id = $this->input->post('person_id');
$result = $this->_ci->PersonModel->checkDuplicate($person_id);
if (isSuccess($result))
$this->terminateWithSuccess($result);
else
$this->terminateWithError('Error when searching for person');
}
// performs strict check over vorname, nachname, gebdatum
public function checkUnruly() {
$vorname = $this->input->post('vorname');
$nachname = $this->input->post('nachname');
$gebdatum = $this->input->post('gebdatum');
$result = $this->_ci->PersonModel->checkUnruly($vorname, $nachname, $gebdatum);
if (isSuccess($result))
$this->terminateWithSuccess($result);
else
$this->terminateWithError('Error when searching for person');
}
// filters nachname on similarity and vorname/gebdatum are optional
public function filterPerson() {
$payload = json_decode($this->input->raw_input_stream, TRUE);
$nachnameString = '';
$vornameString = '';
$filterUnruly = true;
$birthdateString = '';
if(array_key_exists( 'nachname', $payload) ) {
$nachnameString = $payload['nachname'];
}
if(array_key_exists('vorname', $payload)) {
$vornameString = $payload['vorname'];
}
if(array_key_exists('unruly', $payload)){
$filterUnruly = $payload['unruly'];
}
if(array_key_exists('gebdatum', $payload)) {
// TODO: enable if gebdatum filter for unrulys is desired
// $birthdateString = $payload['gebdatum'];
}
$parametersArray = array($nachnameString);
$where ="p.nachname~* ? ";
if (mb_strlen($nachnameString) == 2)
{
$where = "p.nachname=? ";
}
if(isset($vornameString) && $vornameString != '')
{
$where.= " AND p.vorname~*?";
$parametersArray[] = $vornameString;
}
if(isset($birthdateString) && $birthdateString != '')
{
$where.=" AND p.gebdatum=?";
$parametersArray[] = $birthdateString;
}
if(isset($filterUnruly))
{
$where.=" AND p.unruly=?";
$parametersArray[] = $filterUnruly;
}
$result = $this->_ci->PersonModel->checkUnrulyWhere($where, $parametersArray);
if (isSuccess($result))
$this->terminateWithSuccess($result);
else
$this->terminateWithError('Error when searching for person');
}
}
@@ -0,0 +1,65 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Lehrveranstaltung extends FHCAPI_Controller
{
/**
* Lehrveranstaltung API constructor.
*/
public function __construct()
{
parent::__construct(array(
'getTemplateLvTree' => array(
'lehre/lehrveranstaltung:rw'
)
));
// Load model LehrveranstaltungModel
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
}
/**
* Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes of given Berechtigung,
* that are assigned to a template. This data structure can be used for nested tabulators' data tree.
*
* @param null|string $studiensemester_kurzbz
* @param null|string $berechtigung
* @return array|stdClass|null
*/
public function getTemplateLvTree()
{
$studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz');
$berechtigung = $this->input->get('berechtigung');
if ($berechtigung)
{
$oe_permissions = $this->permissionlib->getOE_isEntitledFor($berechtigung);
if(!$oe_permissions) $oe_permissions = [];
$result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz, $oe_permissions);
}
else
{
$result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz);
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
}
@@ -0,0 +1,57 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class StudiengangEP extends FHCAPI_Controller
{
/**
* StudiengangEP API constructor.
*/
public function __construct()
{
parent::__construct(
array(
'getStudiengangByKz' => self::PERM_LOGGED
)
);
// Load model StudiengangModel
$this->load->model('organisation/studiengang_model', 'StudiengangModel');
}
/**
* @return void
*/
public function getStudiengangByKz()
{
$studiengang_kz = intval($this->input->get('studiengang_kz'));
$this->StudiengangModel->addSelect('studiengang_kz, kurzbz, kurzbzlang, '
. 'typ, bezeichnung, english, aktiv, orgform_kurzbz, sprache, '
. 'oe_kurzbz');
$result = $this->StudiengangModel->load($studiengang_kz);
if (isError($result))
{
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$stg = null;
if(hasData($result))
{
$stg = (getData($result))[0];
}
$this->terminateWithSuccess($stg);
}
}
@@ -0,0 +1,80 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Studienjahr extends FHCAPI_Controller
{
/**
* Studienjahr API constructor.
*/
public function __construct()
{
parent::__construct(
array(
'getAll' => self::PERM_LOGGED,
'getNext' => self::PERM_LOGGED
)
);
// Load model StudiensemesterModel
$this->load->model('organisation/studienjahr_model', 'StudienjahrModel');
}
/**
* Get all Studienjahre.
*
* @param null|string $order Sorting order for the Studienjahr, 'asc' or 'desc'. Defaults to 'asc'.
* @param null|string $start Starting Studienjahre with given studienjahr_kurzbz
*/
public function getAll()
{
$order = $this->input->get('order');
$start = $this->input->get('studienjahr_kurzbz');
if (strcasecmp($order, 'DESC') == 0) {
$this->StudienjahrModel->addOrder('studienjahr_kurzbz', 'DESC');
} else {
$this->StudienjahrModel->addOrder('studienjahr_kurzbz', 'ASC');
}
if ($start) {
$result = $this->StudienjahrModel->loadWhere([
'studienjahr_kurzbz >= ' => $start
]);
} else {
$result = $this->StudienjahrModel->load();
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
public function getNext()
{
$this->StudienjahrModel->addJoin('public.tbl_studiensemester', 'studienjahr_kurzbz');
$this->StudienjahrModel->addOrder('start');
$this->StudienjahrModel->addLimit(1);
$result = $this->StudienjahrModel->loadWhere(['start >' => 'NOW()']);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess(current(getData($result)));
}
}
@@ -0,0 +1,155 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Studiensemester extends FHCAPI_Controller
{
/**
* Studiensemester API constructor.
*/
public function __construct()
{
parent::__construct(
array(
'getAll' => self::PERM_LOGGED,
'getAktNext' => self::PERM_LOGGED,
'getStudienjahrByStudiensemester' => self::PERM_LOGGED
)
);
// Load model StudiensemesterModel
$this->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
}
/**
* Get all Studiensemester.
*
* @param null|string $order Sorting order for the Studiensemester, 'asc' or 'desc'. Defaults to 'asc'.
* @param null|string $start Start date of the displayed Studiensemester in the format 'YYYY-MM-DD'.
* If provided, only Studiensemester starting from this date onwards will be returned.
* eg. '2020-09-01' will start with WS2020.
*/
public function getAll()
{
$order = $this->input->get('order');
$start = $this->input->get('start');
if (strcasecmp($order, 'DESC') == 0)
{
$this->StudiensemesterModel->addOrder('ende', 'DESC');
}
else
{
$this->StudiensemesterModel->addOrder('ende', 'ASC');
}
if ($start)
{
$result = $this->StudiensemesterModel->loadWhere([
'start >= ' => $start
]);
}
else
{
$result = $this->StudiensemesterModel->load();
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
/**
* @return void
*/
public function getAktNext()
{
$semester = $this->input->get('semester');
$result = null;
if (!is_numeric($semester))
{
$result = $this->StudiensemesterModel->loadWhere(array('start <=' => 'NOW()', 'ende >=' => 'NOW()'));
}
if (!hasData($result))
{
$this->StudiensemesterModel->addOrder('ende');
$this->StudiensemesterModel->addLimit(1);
$whereArray = array('ende >=' => 'NOW()');
if (is_numeric($semester))
{
if ($semester % 2 == 0)
{
$ss = 'SS';
}
else
{
$ss = 'WS';
}
$whereArray['SUBSTRING(studiensemester_kurzbz FROM 1 FOR 2) ='] = $ss;
}
$result = $this->StudiensemesterModel->loadWhere($whereArray);
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: ''));
}
/**
* Get Studienjahr by Studiensemester.
* input param semester: studiensemester_kurzbz
*/
public function getStudienjahrByStudiensemester()
{
$semester = $this->input->get('semester');
$studienjahrObj = null;
if (!is_numeric($semester))
{
$this->StudiensemesterModel->addSelect('studienjahr_kurzbz');
$result = $this->StudiensemesterModel->loadWhere(array('studiensemester_kurzbz =' => $semester));
}
if (hasData($result))
{
$studienjahr = getData($result)[0]->studienjahr_kurzbz;
$startstudienjahr = substr($studienjahr, 0, 4);
$endstudienjahr = substr($studienjahr, 0, 2) . substr($studienjahr, -2);
$studienjahrObj = new StdClass();
$studienjahrObj->studienjahr_kurzbz = $studienjahr;
$studienjahrObj->startstudienjahr = $startstudienjahr;
$studienjahrObj->endstudienjahr= $endstudienjahr;
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData(success($studienjahrObj))));
}
}
@@ -184,4 +184,4 @@ class Abmeldung extends FHCAPI_Controller
$this->terminateWithSuccess($data);
}
}
}
@@ -0,0 +1,420 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Abschlusspruefung extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getAbschlusspruefung' => ['admin:r', 'assistenz:r'],
'loadAbschlusspruefung' => ['admin:r', 'assistenz:r'],
'insertAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'updateAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'deleteAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'getTypenAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'getNoten' => ['admin:rw', 'assistenz:rw'],
'getTypenAntritte' => ['admin:rw', 'assistenz:rw'],
'getBeurteilungen' => ['admin:rw', 'assistenz:rw'],
'getAkadGrade' => ['admin:rw', 'assistenz:rw'],
'getMitarbeiter' => ['admin:rw', 'assistenz:rw'],
'getPruefer' => ['admin:rw', 'assistenz:rw'],
'getTypStudiengang' => ['admin:rw', 'assistenz:rw'],
'checkForExistingExams' => ['admin:rw', 'assistenz:rw'],
]);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
'person',
'abschlusspruefung'
]);
// Load models
$this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel');
}
public function getAbschlusspruefung($student_uid)
{
$result = $this->AbschlusspruefungModel->getAbschlusspruefungForPrestudent($student_uid);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
public function loadAbschlusspruefung()
{
$abschlusspruefung_id = $this->input->post('id');
$this->AbschlusspruefungModel->addSelect('lehre.tbl_abschlusspruefung.*');
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN pruefer1 IS NOT NULL
THEN CONCAT(p1.nachname, ' ', p1.vorname, COALESCE(' ' || p1.titelpre, ''))
ELSE NULL
END AS p1
");
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN pruefer2 IS NOT NULL
THEN CONCAT(p2.nachname, ' ', p2.vorname, COALESCE(' ' || p2.titelpre, ''))
ELSE NULL
END AS p2
");
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN pruefer3 IS NOT NULL
THEN CONCAT(p3.nachname, ' ', p3.vorname, COALESCE(' ' || p3.titelpre, ''))
ELSE NULL
END AS p3
");
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN vorsitz IS NOT NULL
THEN CONCAT(pv.nachname, ' ', pv.vorname, COALESCE(' ' || pv.titelpre, ''), ' (', ben.uid , ')' )
ELSE NULL
END AS pv
");
$this->AbschlusspruefungModel->addJoin('public.tbl_benutzer ben', 'ON (ben.uid = lehre.tbl_abschlusspruefung.vorsitz)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person pv', 'ON (pv.person_id = ben.person_id)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person p1', 'ON (p1.person_id = lehre.tbl_abschlusspruefung.pruefer1)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person p2', 'ON (p2.person_id = lehre.tbl_abschlusspruefung.pruefer2)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person p3', 'ON (p3.person_id = lehre.tbl_abschlusspruefung.pruefer3)', 'LEFT');
$result = $this->AbschlusspruefungModel->loadWhere(
array('abschlusspruefung_id' => $abschlusspruefung_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function getTypenAbschlusspruefung()
{
$this->load->model('education/Pruefungstyp_model', 'PruefungstypModel');
$result = $this->PruefungstypModel->loadWhere(
array('abschluss' => true)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getTypenAntritte()
{
$this->load->model('education/Pruefungsantritt_model', 'PruefungsantrittModel');
$result = $this->PruefungsantrittModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getBeurteilungen()
{
$this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel');
$result = $this->AbschlussbeurteilungModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getAkadGrade()
{
$studiengang_kz= $this->input->post('studiengang_kz');
$this->load->model('education/Akadgrad_model', 'AkadgradModel');
$result = $this->AkadgradModel->loadWhere(
array('studiengang_kz' => $studiengang_kz)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getTypStudiengang()
{
$studiengang_kz= $this->input->post('studiengang_kz');
/* if (!$studiengang_kzs || !is_array($studiengang_kzs)) {
$this->load->library('form_validation');
$this->form_validation->set_rules('studiengang_kzs', '', 'required|is_null', [
'is_null' => $this->p->t('ui', 'error_fieldMustBeArray')
]);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
}*/
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$result = $this->StudiengangModel->loadWhere(
array('studiengang_kz' => $studiengang_kz)
);
$data = $this->getDataOrTerminateWithError($result);
$typStudiengang = current($data)->typ;
$this->terminateWithSuccess($typStudiengang);
}
public function getMitarbeiter($searchString)
{
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$result = $this->MitarbeiterModel->searchMitarbeiter($searchString, 'mitAkadGrad');
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
}
public function getPruefer($searchString)
{
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$result = $this->MitarbeiterModel->searchMitarbeiter($searchString, 'ohneMaUid');
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
}
public function getNoten()
{
$this->load->model('education/Note_model', 'NoteModel');
$this->NoteModel->addOrder('note', 'ASC');
$result = $this->NoteModel->load();
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result) ?: []);
}
public function insertAbschlusspruefung()
{
$this->load->library('form_validation');
$student_uid = $this->input->post('uid');
if(!$student_uid)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$_POST['pruefungstyp_kurzbz'] = $formData['pruefungstyp_kurzbz'];
$_POST['akadgrad_id']= $formData['akadgrad_id'];
$_POST['vorsitz'] = isset($formData['vorsitz']['mitarbeiter_uid']) ? $formData['vorsitz']['mitarbeiter_uid'] : $formData['vorsitz'];
$_POST['pruefer1'] = isset($formData['pruefer1']['person_id']) ? $formData['pruefer1']['person_id'] : $formData['pruefer1'];
$_POST['pruefer2'] = isset($formData['pruefer2']['person_id']) ? $formData['pruefer2']['person_id'] : $formData['pruefer2'];
$_POST['pruefer3'] = isset($formData['pruefer3']['person_id']) ? $formData['pruefer3']['person_id'] : $formData['pruefer3'];
$_POST['pruefungsantritt_kurzbz'] = $formData['pruefungsantritt_kurzbz'];
$_POST['abschlussbeurteilung_kurzbz'] = $formData['abschlussbeurteilung_kurzbz'];
$_POST['datum']= $formData['datum'];
$_POST['sponsion']= $formData['sponsion'];
$_POST['anmerkung'] = $formData['anmerkung'];
$_POST['protokoll']= $formData['protokoll'];
$_POST['note'] = $formData['note'];
$this->form_validation->set_rules('pruefungstyp_kurzbz', 'Typ', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ'])
]);
$this->form_validation->set_rules('akadgrad_id', 'AkadGrad', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'AkadGrad'])
]);
$this->form_validation->set_rules('datum', 'Datum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum'])
]);
$this->form_validation->set_rules('sponsion', 'Sponsion', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Sponsion'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->AbschlusspruefungModel->insert([
'student_uid' => $student_uid,
'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'),
'akadgrad_id' => $this->input->post('akadgrad_id'),
'vorsitz' => $this->input->post('vorsitz'),
'pruefungsantritt_kurzbz' => $this->input->post('pruefungsantritt_kurzbz'),
'abschlussbeurteilung_kurzbz' => $this->input->post('abschlussbeurteilung_kurzbz'),
'datum' => $this->input->post('datum'), //TODO(Manu) check if minute format like FAS
'sponsion' => $this->input->post('sponsion'),
'pruefer1' => $this->input->post('pruefer1'),
'pruefer2' => $this->input->post('pruefer2'),
'pruefer3' => $this->input->post('pruefer3'),
'protokoll' => $this->input->post('protokoll'),
'note' => $this->input->post('note'),
'anmerkung' => $this->input->post('anmerkung'),
'insertamum' => date('c'),
'insertvon' => getAuthUID()
]);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function updateAbschlusspruefung()
{
$this->load->library('form_validation');
$abschlusspruefung_id = $this->input->post('id');
if(!$abschlusspruefung_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Abschlussprüfung ID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$_POST['student_uid'] = $formData['student_uid'];
$_POST['pruefungstyp_kurzbz'] = $formData['pruefungstyp_kurzbz'];
$_POST['akadgrad_id']= $formData['akadgrad_id'];
$_POST['vorsitz'] = isset($formData['vorsitz']['mitarbeiter_uid']) ? $formData['vorsitz']['mitarbeiter_uid'] : $formData['vorsitz'];
$_POST['pruefer1'] = isset($formData['pruefer1']['person_id']) ? $formData['pruefer1']['person_id'] : $formData['pruefer1'];
$_POST['pruefer2'] = isset($formData['pruefer2']['person_id']) ? $formData['pruefer2']['person_id'] : $formData['pruefer2'];
$_POST['pruefer3'] = isset($formData['pruefer3']['person_id']) ? $formData['pruefer3']['person_id'] : $formData['pruefer3'];
$_POST['pruefungsantritt_kurzbz'] = $formData['pruefungsantritt_kurzbz'];
$_POST['abschlussbeurteilung_kurzbz'] = $formData['abschlussbeurteilung_kurzbz'];
$_POST['datum']= $formData['datum'];
$_POST['sponsion']= $formData['sponsion'];
$_POST['anmerkung'] = $formData['anmerkung'];
$_POST['protokoll']= $formData['protokoll'];
$_POST['note'] = $formData['note'];
$this->form_validation->set_rules('pruefungstyp_kurzbz', 'Typ', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ'])
]);
$this->form_validation->set_rules('akadgrad_id', 'AkadGrad', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'AkadGrad'])
]);
$this->form_validation->set_rules('datum', 'Datum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum'])
]);
$this->form_validation->set_rules('sponsion', 'Sponsion', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Sponsion'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->AbschlusspruefungModel->update(
[
'abschlusspruefung_id' => $abschlusspruefung_id
],
[
'student_uid' => $this->input->post('student_uid'),
'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'),
'akadgrad_id' => $this->input->post('akadgrad_id'),
'vorsitz' => $this->input->post('vorsitz'),
'pruefungsantritt_kurzbz' => $this->input->post('pruefungsantritt_kurzbz'),
'abschlussbeurteilung_kurzbz' => $this->input->post('abschlussbeurteilung_kurzbz'),
'datum' => $this->input->post('datum'),
'sponsion' => $this->input->post('sponsion'),
'pruefer1' => $this->input->post('pruefer1'),
'pruefer2' => $this->input->post('pruefer2'),
'pruefer3' => $this->input->post('pruefer3'),
'protokoll' => $this->input->post('protokoll'),
'note' => $this->input->post('note'),
'anmerkung' => $this->input->post('anmerkung'),
'insertamum' => date('c'),
'insertvon' => getAuthUID()
]
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function deleteAbschlusspruefung()
{
$abschlusspruefung_id = $this->input->post('id');
$result = $this->AbschlusspruefungModel->delete(
array('abschlusspruefung_id' => $abschlusspruefung_id)
);
if (isError($result))
{
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
if (!hasData($result))
{
$this->outputJson($result);
}
return $this->terminateWithSuccess(current(getData($result)) ? : null);
}
public function checkForExistingExams()
{
$warning = false;
$output = [];
$student_uids = $this->input->post('uids');
if (empty($student_uids)) {
throw new InvalidArgumentException("Keine UID(s) übergeben.");
}
if( !is_array($student_uids) )
{
$student_uids = array($student_uids);
}
foreach ($student_uids as $uid)
{
$result = $this->AbschlusspruefungModel->loadWhere(
array('student_uid' => $uid)
);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
if (!hasData($result))
{
$warning = true;
$output[] = $uid;
}
}
if($warning)
{
$uids = is_array($output) ? implode(", ", $output) : $output;
return $this->terminateWithError($this->p->t('abschlusspruefung', 'error_studentOhneFinalExam', ['id'=> $uids]), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess('step3');
}
}
@@ -45,7 +45,7 @@ class Address extends FHCAPI_Controller
$this->terminateWithSuccess($data);
}
public function getPlaces($plz)
public function getPlaces($plz = null)
{
$this->load->model('codex/Gemeinde_model', 'GemeindeModel');
@@ -53,7 +53,7 @@ class Address extends FHCAPI_Controller
$this->form_validation->set_data(['address.plz' => $plz]);
$this->form_validation->set_rules('address.plz', 'PLZ', 'numeric|less_than[10000]');
$this->form_validation->set_rules('address.plz', 'PLZ', 'required|numeric|less_than[10000]');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
@@ -44,16 +44,23 @@ class Config extends FHCAPI_Controller
'person',
'lehre',
'stv',
'konto'
'konto',
'abschlusspruefung'
]);
// Load Config
$this->load->config('stv');
}
public function student()
{
$result = [];
$config = $this->config->item('tabs');
$result['details'] = [
'title' => $this->p->t('stv', 'tab_details'),
'component' => './Stv/Studentenverwaltung/Details/Details.js'
'component' => './Stv/Studentenverwaltung/Details/Details.js',
'config' => $config['details']
];
$result['notes'] = [
'title' => $this->p->t('stv', 'tab_notes'),
@@ -69,7 +76,8 @@ class Config extends FHCAPI_Controller
];
$result['prestudent'] = [
'title' => $this->p->t('stv', 'tab_prestudent'),
'component' => './Stv/Studentenverwaltung/Details/Prestudent.js'
'component' => './Stv/Studentenverwaltung/Details/Prestudent.js',
'config' => $config['prestudent']
];
$result['status'] = [
'title' => 'Status',
@@ -91,12 +99,34 @@ class Config extends FHCAPI_Controller
'title' => $this->p->t('stv', 'tab_resources'),
'component' => './Stv/Studentenverwaltung/Details/Betriebsmittel.js'
];
/* TODO(chris): Ausgeblendet für Testing
$result['grades'] = [
'title' => $this->p->t('stv', 'tab_grades'),
'component' => './Stv/Studentenverwaltung/Details/Noten.js'
'component' => './Stv/Studentenverwaltung/Details/Noten.js',
'showOnlyWithUid' => true,
'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()
]
];
$result['exam'] = [
'title' => $this->p->t('stv', 'tab_exam'),
'component' => './Stv/Studentenverwaltung/Details/Pruefung.js'
];
$result['finalexam'] = [
'title' => $this->p->t('stv', 'tab_finalexam'),
'component' => './Stv/Studentenverwaltung/Details/Abschlusspruefung.js',
'config' => $config['finalexam']
];
$result['mobility'] = [
'title' => $this->p->t('stv', 'tab_mobility'),
'component' => './Stv/Studentenverwaltung/Details/Mobility.js'
];
*/
Events::trigger('stv_conf_student', function & () use (&$result) {
return $result;
@@ -108,6 +138,7 @@ class Config extends FHCAPI_Controller
public function students()
{
$result = [];
$config = $this->config->item('tabs');
$result['banking'] = [
'title' => $this->p->t('stv', 'tab_banking'),
'component' => './Stv/Studentenverwaltung/Details/Konto.js',
@@ -131,6 +162,11 @@ class Config extends FHCAPI_Controller
'changeStatusToAbsolvent' => $this->permissionlib->isBerechtigt('admin')
]
];
$result['finalexam'] = [
'title' => $this->p->t('stv', 'tab_finalexam'),
'component' => './Stv/Studentenverwaltung/Details/Abschlusspruefung.js',
'config' => $config['finalexam']
];
Events::trigger('stv_conf_students', function & () use (&$result) {
return $result;
@@ -230,4 +266,186 @@ 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;
}
}
@@ -48,7 +48,7 @@ class Favorites extends FHCAPI_Controller
if (!$data)
$this->terminateWithSuccess(null);
else
$this->terminateWithSuccess($data['stv_favorites']);
$this->terminateWithSuccess($data['stv_favorites'] ?? null);
}
public function set()
@@ -0,0 +1,685 @@
<?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 grades
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Grades extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'list' => 'student/noten:r',
'getCertificate' => 'student/noten:r',
'getTeacherProposal' => 'student/noten:r',
'getRepeaterGrades' => 'student/noten:r',
'updateCertificate' => ['admin:w', 'assistenz:w'],
'deleteCertificate' => ['admin:w', 'assistenz:w'],
'copyTeacherProposalToCertificate' => 'student/noten:w',
'copyRepeaterGradeToCertificate' => 'student/noten:w',
'getGradeFromPoints' => 'student/noten:r'
]);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
// Load Phrases
$this->loadPhrases([
'stv',
'person',
'lehre'
]);
}
/**
* List all possible grades
* (Entries in lehre.tbl_note)
*
* @return void
*/
public function list()
{
$this->load->model('codex/Note_model', 'NoteModel');
$this->NoteModel->addOrder('note');
$result = $this->NoteModel->load();
$grades = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($grades);
}
/**
* List grades for the certificate of a prestudent.
* (Entries in lehre.tbl_zeugnisnote)
*
* @param string $prestudent_id
* @param string|null $all (optional) If null only the current semesters grades will be loaded, otherwise all semesters grades will be loaded.
*
* @return void
*/
public function getCertificate($prestudent_id, $all = null)
{
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$result = $this->StudentModel->loadWhere([
'prestudent_id' => $prestudent_id
]);
$student = $this->getDataOrTerminateWithError($result);
if (!$student)
$this->terminateWithSuccess([]);
$student_uid = current($student)->student_uid;
$studiensemester_kurzbz = ($all === null) ? $this->variablelib->getVar('semester_aktuell') : null;
$result = $this->ZeugnisnoteModel->getZeugnisnoten($student_uid, $studiensemester_kurzbz);
$grades = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($grades);
}
/**
* List grades of a prestudent that teachers gave.
* (Entries in campus.tbl_lvgesamtnote)
*
* @param string $prestudent_id
* @param string|null $all (optional) If null only the current semesters grades will be loaded, otherwise all semesters grades will be loaded.
*
* @return void
*/
public function getTeacherProposal($prestudent_id, $all = null)
{
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('education/Lvgesamtnote_model', 'LvgesamtnoteModel');
$result = $this->StudentModel->loadWhere([
'prestudent_id' => $prestudent_id
]);
$student = $this->getDataOrTerminateWithError($result);
if (!$student)
$this->terminateWithSuccess([]);
$student_uid = current($student)->student_uid;
$studiensemester_kurzbz = ($all === null) ? $this->variablelib->getVar('semester_aktuell') : null;
$result = $this->LvgesamtnoteModel->getLvGesamtNoten(null, $student_uid, $studiensemester_kurzbz);
$grades = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($grades);
}
/**
* List grades of a prestudent that an assistant marked as already done
* or as not allowed because of the repeating of a semester.
*
* @param string $prestudent_id
* @param string|null $all (optional) If null only the current semesters grades will be loaded, otherwise all semesters grades will be loaded.
*
* @return void
*/
public function getRepeaterGrades($prestudent_id, $all = null)
{
$this->load->library('AntragLib');
$studiensemester_kurzbz = ($all === null) ? $this->variablelib->getVar('semester_aktuell') : false;
$result = $this->antraglib->getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz);
$grades = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($grades);
}
/**
* Update or Insert a grade for the certificate of a prestudent.
* (Entry in lehre.tbl_zeugnisnote)
*
* @return void
*/
public function updateCertificate()
{
$this->load->library('form_validation');
$this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer");
$this->form_validation->set_rules("student_uid", $this->p->t('person', 'student'), "required");
$this->form_validation->set_rules("studiensemester_kurzbz", $this->p->t('lehre', 'studiensemester'), "required");
$this->form_validation->set_rules('note', $this->p->t('lehre', 'note'), 'required|numeric');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
$student_uid = $this->input->post('student_uid');
$lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id');
$note = $this->input->post('note');
$authUID = getAuthUID();
$now = date('c');
// NOTE(chris): Stg Permissions
if (!$this->hasPermissionUpdate($lehrveranstaltung_id, $student_uid))
return $this->_outputAuthError([$this->router->method => ['admin', 'assistenz']]);
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$result = $this->ZeugnisnoteModel->load([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $student_uid,
'lehrveranstaltung_id' => $lehrveranstaltung_id
]);
$current = $this->getDataOrTerminateWithError($result);
if ($current) {
$result = $this->ZeugnisnoteModel->update([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $student_uid,
'lehrveranstaltung_id' => $lehrveranstaltung_id
], [
'note' => $note,
'benotungsdatum' => $now,
'updateamum' => $now,
'updatevon' => $authUID
]);
} else {
$result = $this->ZeugnisnoteModel->insert([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $student_uid,
'lehrveranstaltung_id' => $lehrveranstaltung_id,
'note' => $note,
'benotungsdatum' => $now,
'insertamum' => $now,
'insertvon' => $authUID
]);
}
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(true);
}
/**
* Delete a grade from the certificate of a prestudent.
* (Entry in lehre.tbl_zeugnisnote)
*
* @return void
*/
public function deleteCertificate()
{
$this->load->library('form_validation');
$this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer");
$this->form_validation->set_rules("student_uid", $this->p->t('person', 'student'), "required");
$this->form_validation->set_rules("studiensemester_kurzbz", $this->p->t('lehre', 'studiensemester'), "required");
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
$student_uid = $this->input->post('student_uid');
$lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id');
// NOTE(chris): Stg Permissions
if (!$this->hasPermissionDelete($lehrveranstaltung_id, $student_uid))
return $this->_outputAuthError([$this->router->method => ['admin', 'assistenz']]);
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$result = $this->ZeugnisnoteModel->delete([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $student_uid,
'lehrveranstaltung_id' => $lehrveranstaltung_id
]);
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(true);
}
/**
* Copy a grade that teachers gave to the certificate of a prestudent.
* (Entry in campus.tbl_lvgesamtnote to an entry in lehre.tbl_zeugnisnote)
*
* @return void
*/
public function copyTeacherProposalToCertificate()
{
$this->load->library('form_validation');
$this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer");
$this->form_validation->set_rules("student_uid", $this->p->t('person', 'student'), "required");
$this->form_validation->set_rules("studiensemester_kurzbz", $this->p->t('lehre', 'studiensemester'), "required");
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id');
$student_uid = $this->input->post('student_uid');
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
$authUID = getAuthUID();
// NOTE(chris): Stg Permissions
if (!$this->hasPermissionCopy($lehrveranstaltung_id, $student_uid))
return $this->_outputAuthError([$this->router->method => 'student/noten']);
$this->load->model('education/Lvgesamtnote_model', 'LvgesamtnoteModel');
$result = $this->LvgesamtnoteModel->load([
'student_uid' => $student_uid,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'lehrveranstaltung_id' => $lehrveranstaltung_id
]);
$teacherGrade = $this->getDataOrTerminateWithError($result);
if (!$teacherGrade)
show_404();
$teacherGrade = current($teacherGrade);
$data = [
'note' => $teacherGrade->note,
'punkte' => $teacherGrade->punkte,
'uebernahmedatum' => date('c'),
'benotungsdatum' => $teacherGrade->benotungsdatum,
'bemerkung' => $teacherGrade->bemerkung
];
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$this->ZeugnisnoteModel->addJoin('lehre.tbl_note n', 'note');
$result = $this->ZeugnisnoteModel->load([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $student_uid,
'lehrveranstaltung_id' => $lehrveranstaltung_id
]);
$certificateGrade = $this->getDataOrTerminateWithError($result);
if ($certificateGrade) {
$certificateGrade = current($certificateGrade);
if (!$certificateGrade->lkt_ueberschreibbar)
$this->terminateWithError($this->p->t("stv", "grades_error_overwrite"));
// NOTE(chris): update
$data['updateamum'] = $data['uebernahmedatum'];
$data['updatevon'] = $authUID;
$this->ZeugnisnoteModel->update([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $student_uid,
'lehrveranstaltung_id' => $lehrveranstaltung_id
], $data);
} else {
// NOTE(chris): insert
$data['insertamum'] = $data['uebernahmedatum'];
$data['insertvon'] = $authUID;
$data['lehrveranstaltung_id'] = $lehrveranstaltung_id;
$data['student_uid'] = $student_uid;
$data['studiensemester_kurzbz'] = $studiensemester_kurzbz;
$this->ZeugnisnoteModel->insert($data);
if (defined('FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN')
&& FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN) {
$result = $this->addTestsForGrade(
$studiensemester_kurzbz,
$student_uid,
$lehrveranstaltung_id,
$teacherGrade->note,
$teacherGrade->punkte
);
$this->getDataOrTerminateWithError($result);
}
}
$this->terminateWithSuccess(true);
}
/**
* Copy a grade that was marked by an assistant as already done or not
* allowed because of the repeating of a semester to the certificate of a
* prestudent.
*
* @return void
*/
public function copyRepeaterGradeToCertificate()
{
$this->load->library('form_validation');
$this->form_validation->set_rules("studierendenantrag_lehrveranstaltung_id", "studierendenantrag_lehrveranstaltung_id", "required|integer");
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$id = $this->input->post('studierendenantrag_lehrveranstaltung_id');
$authUID = getAuthUID();
$this->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel');
$this->StudierendenantraglehrveranstaltungModel->addSelect("tbl_studierendenantrag_lehrveranstaltung.*");
$this->StudierendenantraglehrveranstaltungModel->addSelect("student_uid");
$this->StudierendenantraglehrveranstaltungModel->addJoin("campus.tbl_studierendenantrag", "studierendenantrag_id");
$this->StudierendenantraglehrveranstaltungModel->addJoin("public.tbl_student", "prestudent_id", "LEFT");
$result = $this->StudierendenantraglehrveranstaltungModel->load($id);
$repeaterGrade = $this->getDataOrTerminateWithError($result);
if (!$repeaterGrade)
show_404();
$repeaterGrade = current($repeaterGrade);
// NOTE(chris): Stg Permissions
if (!$this->hasPermissionCopy($repeaterGrade->lehrveranstaltung_id, $repeaterGrade->student_uid))
return $this->_outputAuthError([$this->router->method => 'student/noten']);
$data = [
'note' => $repeaterGrade->note,
'uebernahmedatum' => date('c'),
'benotungsdatum' => $repeaterGrade->insertamum,
'bemerkung' => $repeaterGrade->anmerkung
];
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$result = $this->ZeugnisnoteModel->load([
$repeaterGrade->studiensemester_kurzbz,
$repeaterGrade->student_uid,
$repeaterGrade->lehrveranstaltung_id
]);
$certificateGrade = $this->getDataOrTerminateWithError($result);
if ($certificateGrade) {
// NOTE(chris): update
$data['updateamum'] = $data['uebernahmedatum'];
$data['updatevon'] = $authUID;
$this->ZeugnisnoteModel->update([
$repeaterGrade->studiensemester_kurzbz,
$repeaterGrade->student_uid,
$repeaterGrade->lehrveranstaltung_id
], $data);
} else {
// NOTE(chris): insert
$data['insertamum'] = $data['uebernahmedatum'];
$data['insertvon'] = $authUID;
$data['lehrveranstaltung_id'] = $repeaterGrade->lehrveranstaltung_id;
$data['student_uid'] = $repeaterGrade->student_uid;
$data['studiensemester_kurzbz'] = $repeaterGrade->studiensemester_kurzbz;
$this->ZeugnisnoteModel->insert($data);
}
$this->terminateWithSuccess(true);
}
/**
* Loads the grade from the points using the gradingkey
*
* @return void
*/
public function getGradeFromPoints()
{
$this->load->library('form_validation');
$this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer");
$this->form_validation->set_rules("points", $this->p->t("stv", "grades_points"), "required|numeric");
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$this->load->model('education/Notenschluesselaufteilung_model', 'NotenschluesselaufteilungModel');
$studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
$result = $this->NotenschluesselaufteilungModel->getNote(
$this->input->post('points'),
$this->input->post('lehrveranstaltung_id'),
$studiensemester_kurzbz
);
$note = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($note);
}
/**
* Helper function that adds tests for a student
* (Entries in lehre.tbl_pruefung)
*
* @param string $studiensemester_kurzbz
* @param string $student_uid
* @param integer $lehrveranstaltung_id
* @param integer $note
* @param numeric $punkte
*
* @return stdClass
*/
protected function addTestsForGrade($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $note, $punkte)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
// Get Lehreinheit
$result = $this->LehrveranstaltungModel->getLeByStudent($student_uid, $studiensemester_kurzbz, $lehrveranstaltung_id);
if (isError($result))
return $result;
if (!hasData($result))
return error($this->p->t("stv", "grades_error_lehreinheit_id"));
$le = current(getData($result));
// Prepare
$this->load->model('education/LePruefung_model', 'LePruefungModel');
$data = [
"student_uid" => $student_uid,
"lehreinheit_id" => $le->lehreinheit_id,
"datum" => date('Y-m-d'),
"pruefungstyp_kurzbz" => "Termin1",
"note" => $note
];
if (defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE)
$data["punkte"] = $punkte;
// Get Anwesenheit
$this->load->model('education/Anwesenheit_model', 'AnwesenheitModel');
$result = $this->AnwesenheitModel->loadAnwesenheitStudiensemester($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id);
if (isError($result))
return $result;
$anwesenheit = getData($result);
if ($anwesenheit && (float)current($anwesenheit)->prozent < FAS_ANWESENHEIT_ROT) {
// Get Anwesenheitsbefreiung
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$result = $this->BenutzerfunktionModel->getBenutzerFunktionByUidInStdsem($student_uid, $studiensemester_kurzbz, 'awbefreit');
if (isError($result))
return $result;
$anwesenheitsbefreit = hasData($result);
// Wenn nicht Anwesenheitsbefreit und Anwesenheit unter einem bestimmten Prozentsatz fällt dann wird ein Pruefungsantritt abgezogen
if (!$anwesenheitsbefreit) {
$data2 = $data;
$data2["note"] = 7;
if (isset($data2["punkte"]))
unset($data2["punkte"]);
$result = $this->LePruefungModel->insert($data2);
if (isError($result))
return $result;
$data["pruefungstyp_kurzbz"] = "Termin2";
}
}
return $this->LePruefungModel->insert($data);
}
/**
* Helper function to check permissions for updateCertificate()
*
* @param integer $lehrveranstaltung_id
* @param string $student_uid
*
* @return boolean
*/
protected function hasPermissionUpdate($lehrveranstaltung_id, $student_uid)
{
if ($lehrveranstaltung_id === null || $student_uid === null)
return true;
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
if (isError($result) || !hasData($result))
return false;
$student = current(getData($result));
if ($this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz))
return true;
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz))
return true;
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
$result = $this->StudienplanModel->getAllOesForLv($lehrveranstaltung_id);
if (isError($result))
return false;
$oes = getData($result) ?: [];
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getStg($lehrveranstaltung_id);
if (isError($result))
return false;
if (hasData($result))
$oes[] = current(getData($result));
foreach ($oes as $oe) {
if ($this->permissionlib->isBerechtigt('admin', 'suid', $oe->oe_kurzbz))
return true;
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $oe->oe_kurzbz))
return true;
}
return false;
}
/**
* Helper function to check permissions for deleteCertificate()
*
* @param integer $lehrveranstaltung_id
* @param string $student_uid
*
* @return boolean
*/
protected function hasPermissionDelete($lehrveranstaltung_id, $student_uid)
{
if ($lehrveranstaltung_id === null || $student_uid === null)
return true;
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
if (isError($result) || !hasData($result))
return false;
$student = current(getData($result));
if ($this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz))
return true;
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz))
return true;
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id);
if (isError($result) || !hasData($result))
return false;
$oe = current(getData($result));
if ($this->permissionlib->isBerechtigt('admin', 'suid', $oe->oe_kurzbz))
return true;
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $oe->oe_kurzbz))
return true;
return false;
}
/**
* Helper function to check permissions for
* copyTeacherProposalToCertificate() and copyRepeaterGradeToCertificate()
*
* @param integer $lehrveranstaltung_id
* @param string $student_uid
*
* @return boolean
*/
protected function hasPermissionCopy($lehrveranstaltung_id, $student_uid)
{
if ($lehrveranstaltung_id === null || $student_uid === null)
return true;
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
if (isError($result) || !hasData($result))
return false;
$student = current(getData($result));
if ($this->permissionlib->isBerechtigt('student/noten', 'suid', $student->studiengang_kz))
return true;
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id);
if (isError($result) || !hasData($result))
return false;
$oe = current(getData($result));
if ($this->permissionlib->isBerechtigt('student/noten', 'suid', $oe->oe_kurzbz))
return true;
return false;
}
}
@@ -97,7 +97,14 @@ class Kontakt extends FHCAPI_Controller
|| $this->router->method == 'deleteContact'
|| $this->router->method == 'deleteBankverbindung'
) {
$id = current(array_slice($this->uri->rsegments, 2));
if($this->input->post('address_id'))
$id = $this->input->post('address_id');
if($this->input->post('adresse_id'))
$id = $this->input->post('adresse_id');
if($this->input->post('bankverbindung_id'))
$id = $this->input->post('bankverbindung_id');
if($this->input->post('kontakt_id'))
$id = $this->input->post('kontakt_id');
$model = 'person/Adresse_model';
if ($this->router->method == 'loadContact'
@@ -125,7 +132,12 @@ class Kontakt extends FHCAPI_Controller
}
public function getAdressen($person_id)
{
$this->AdresseModel->addSelect('public.tbl_adresse.*');
$this->AdresseModel->addSelect("public.tbl_adresse.*,
(CASE
WHEN public.tbl_adresse.updateamum >= public.tbl_adresse.insertamum
THEN public.tbl_adresse.updateamum
ELSE public.tbl_adresse.insertamum
END) AS lastUpdate");
$this->AdresseModel->addSelect('t.*');
$this->AdresseModel->addSelect('f.firma_id');
$this->AdresseModel->addSelect('f.name as firmenname');
@@ -143,15 +155,26 @@ class Kontakt extends FHCAPI_Controller
public function addNewAddress($person_id)
{
$this->form_validation->set_rules('plz', 'PLZ', 'required|numeric', [
$this->form_validation->set_data(['address.plz' => $_POST['plz']]);
$this->form_validation->set_rules('address.plz', 'PLZ', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']),
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ'])
]);
if(isset($_POST['gemeinde']) && isset($_POST['ort']))
$this->form_validation->set_rules('plz', 'Postleitzahl', 'callback_validateLocationCombination', [
'validateLocationCombination' => $this->p->t('ui', 'error_location_combination')
]);
if(isset($_POST['nation']) && $_POST['nation'] == 'A')
{
$this->form_validation->set_rules('address.plz', 'PLZ', 'required|numeric', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']),
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ'])
]);
}
if(isset($_POST['gemeinde']) && isset($_POST['ort']) && isset($_POST['nation']) && $_POST['nation'] == 'A')
{
$this->form_validation->set_rules('address.plz', 'Postleitzahl', 'callback_validateLocationCombination', [
'validateLocationCombination' => $this->p->t('ui', 'error_location_combination')
]);
}
if ($this->form_validation->run() == false)
{
@@ -196,25 +219,37 @@ class Kontakt extends FHCAPI_Controller
]
);
if (isError($result))
{
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(true);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function updateAddress($address_id)
public function updateAddress()
{
$address_id = $this->input->post('adresse_id');
$this->form_validation->set_data(['address.plz' => $_POST['plz']]);
$uid = getAuthUID();
$this->form_validation->set_rules('plz', 'PLZ', 'required|numeric', [
$this->form_validation->set_rules('address.plz', 'PLZ', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']),
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ'])
]);
if(isset($_POST['gemeinde']) && isset($_POST['ort']))
$this->form_validation->set_rules('plz', 'Postleitzahl', 'callback_validateLocationCombination', [
if(isset($_POST['nation']) && $_POST['nation'] == 'A')
{
$this->form_validation->set_rules('address.plz', 'PLZ', 'required|numeric', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']),
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ'])
]);
}
if(isset($_POST['gemeinde']) && isset($_POST['ort']) && isset($_POST['nation']) && $_POST['nation'] == 'A')
{
$this->form_validation->set_rules('address.plz', 'Postleitzahl', 'callback_validateLocationCombination', [
'validateLocationCombination' => $this->p->t('ui', 'error_location_combination')
]);
}
if ($this->form_validation->run() == false)
{
@@ -272,15 +307,15 @@ class Kontakt extends FHCAPI_Controller
]
);
if (isError($result))
{
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(true);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function loadAddress($adresse_id)
public function loadAddress()
{
$adresse_id = $this->input->post('address_id');
$this->load->model('person/Adresse_model', 'AdresseModel');
$this->AdresseModel->addSelect('public.tbl_adresse.*');
@@ -306,8 +341,10 @@ class Kontakt extends FHCAPI_Controller
$this->terminateWithSuccess(current(getData($result)) ? : null);
}
public function deleteAddress($adresse_id)
public function deleteAddress()
{
$adresse_id = $this->input->post('address_id');
$this->load->model('person/Adresse_model', 'AdresseModel');
$result = $this->AdresseModel->load([
'adresse_id'=> $adresse_id,
@@ -366,10 +403,10 @@ class Kontakt extends FHCAPI_Controller
$this->load->model('organisation/standort_model', 'StandortModel');
$result = $this->StandortModel->searchStandorte($searchString);
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getStandorteByFirma($firma_id)
@@ -386,11 +423,11 @@ class Kontakt extends FHCAPI_Controller
public function getKontakte($person_id)
{
$this->KontaktModel->addSelect("public.tbl_kontakt.*,
TO_CHAR (CASE
WHEN public.tbl_kontakt.updateamum >= public.tbl_kontakt.insertamum
THEN public.tbl_kontakt.updateamum
ELSE public.tbl_kontakt.insertamum
END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate, st.bezeichnung, f.name");
(CASE
WHEN public.tbl_kontakt.updateamum >= public.tbl_kontakt.insertamum
THEN public.tbl_kontakt.updateamum
ELSE public.tbl_kontakt.insertamum
END) AS lastUpdate, st.bezeichnung, f.name");
$this->StandortModel->addJoin('public.tbl_standort st', 'ON (public.tbl_kontakt.standort_id = st.standort_id)', 'LEFT');
$this->FirmaModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = st.firma_id)', 'LEFT');
$result = $this->KontaktModel->loadWhere(
@@ -418,8 +455,9 @@ class Kontakt extends FHCAPI_Controller
}
}
public function loadContact($kontakt_id)
public function loadContact()
{
$kontakt_id = $this->input->post('kontakt_id');
$this->load->model('person/Kontakt_model', 'KontaktModel');
$this->KontaktModel->addSelect('*, public.tbl_kontakt.*');
@@ -439,7 +477,6 @@ class Kontakt extends FHCAPI_Controller
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Kontakt_id']), self::ERROR_TYPE_GENERAL);
}
// $this->outputJsonSuccess(current(getData($result)));
$this->terminateWithSuccess(current(getData($result)));
}
@@ -492,11 +529,12 @@ class Kontakt extends FHCAPI_Controller
{
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(true);
$this->terminateWithSuccess($result);
}
public function updateContact($kontakt_id)
public function updateContact()
{
$kontakt_id = $this->input->post('kontakt_id');
$this->load->model('person/Kontakt_model', 'KontaktModel');
if(!$kontakt_id)
@@ -523,13 +561,6 @@ class Kontakt extends FHCAPI_Controller
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
/* if(isset($_POST['standort']))
{
$standort_id = $_POST['standort']['standort_id'];
}
else
$standort_id = null;*/
$uid = getAuthUID();
$kontakttyp = $this->input->post('kontakttyp');
$anmerkung = $this->input->post('anmerkung');
@@ -538,8 +569,6 @@ class Kontakt extends FHCAPI_Controller
$person_id = $this->input->post('person_id');
$standort_id = $this->input->post('standort_id');
//return $this->terminateWithError("in update " . $standort_id, self::ERROR_TYPE_GENERAL);
$result = $this->KontaktModel->update(
[
'kontakt_id' => $kontakt_id
@@ -557,15 +586,14 @@ class Kontakt extends FHCAPI_Controller
]
);
if (isError($result))
{
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(true);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function deleteContact($kontakt_id)
public function deleteContact()
{
$kontakt_id = $this->input->post('kontakt_id');
$this->load->model('person/Kontakt_model', 'KontaktModel');
$result = $this->KontaktModel->delete(
@@ -643,15 +671,15 @@ class Kontakt extends FHCAPI_Controller
'orgform_kurzbz' => $orgform_kurzbz
]
);
if (isError($result))
{
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(true);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function loadBankverbindung($bankverbindung_id)
public function loadBankverbindung()
{
$bankverbindung_id = $this->input->post('bankverbindung_id');
$this->load->model('person/Bankverbindung_model', 'BankverbindungModel');
$this->BankverbindungModel->addSelect('*');
@@ -719,15 +747,15 @@ class Kontakt extends FHCAPI_Controller
]
);
if (isError($result))
{
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(true);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function deleteBankverbindung($bankverbindung_id)
public function deleteBankverbindung()
{
$bankverbindung_id = $this->input->post('bankverbindung_id');
$this->load->model('person/Bankverbindung_model', 'BankverbindungModel');
$result = $this->BankverbindungModel->delete(
@@ -740,7 +768,7 @@ class Kontakt extends FHCAPI_Controller
}
if (!hasData($result))
{
$this->outputJson($result);
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Bankverbindung_id']), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(current(getData($result)) ? : null);
}
@@ -0,0 +1,528 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Mobility extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getMobilitaeten' => ['admin:r', 'assistenz:r'],
'loadMobility' => ['admin:r', 'assistenz:r'],
'insertMobility' => ['admin:rw', 'assistenz:rw'],
'updateMobility' => ['admin:rw', 'assistenz:rw'],
'deleteMobility' => ['admin:rw', 'assistenz:rw'],
'getProgramsMobility' => ['admin:r', 'assistenz:r'],
'getLVList' => ['admin:r', 'assistenz:r'],
'getAllLehreinheiten' => ['admin:r', 'assistenz:r'],
'getLvsandLesByStudent' => ['admin:r', 'assistenz:r'],
'getPurposes' => ['admin:r', 'assistenz:r'],
'getSupports' => ['admin:r', 'assistenz:r'],
'getListPurposes' => ['admin:r', 'assistenz:r'],
'getListSupports' => ['admin:r', 'assistenz:r'],
'deleteMobilityPurpose' => ['admin:r', 'assistenz:r'],
'addMobilityPurpose' => ['admin:r', 'assistenz:r'],
'deleteMobilitySupport' => ['admin:r', 'assistenz:r'],
'addMobilitySupport' => ['admin:r', 'assistenz:r'],
]);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
'mobility'
]);
// Load models
$this->load->model('codex/Bisio_model', 'BisioModel');
}
public function getMobilitaeten($student_uid)
{
$this->BisioModel->addSelect("*");
$this->BisioModel->addJoin('bis.tbl_mobilitaetsprogramm mp', 'ON (mp.mobilitaetsprogramm_code = bis.tbl_bisio.mobilitaetsprogramm_code)', 'LEFT');
$this->BisioModel->addJoin('lehre.tbl_lehreinheit le', 'ON (le.lehreinheit_id = bis.tbl_bisio.lehreinheit_id)','LEFT');
$this->BisioModel->addOrder('von', 'DESC');
$this->BisioModel->addOrder('bis', 'DESC');
$this->BisioModel->addOrder('bisio_id', 'DESC');
$result = $this->BisioModel->loadWhere(
array('student_uid' => $student_uid)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getProgramsMobility()
{
$this->load->model('codex/Mobilitaetsprogramm_model', 'MobilitaetsprogrammModel');
$result = $this->MobilitaetsprogrammModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function insertMobility()
{
$this->load->library('form_validation');
$authUID = getAuthUID();
$student_uid = $this->input->post('uid');
if(!$student_uid)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$_POST['von'] = (isset($formData['von']) && !empty($formData['von'])) ? $formData['von'] : null;
$_POST['bis'] = (isset($formData['bis']) && !empty($formData['bis'])) ? $formData['bis'] : null;
$_POST['nation_code'] = (isset($formData['nation_code']) && !empty($formData['nation_code'])) ? $formData['nation_code'] : 'A';
$_POST['mobilitaetsprogramm_code'] = (isset($formData['mobilitaetsprogramm_code']) && !empty($formData['mobilitaetsprogramm_code'])) ? $formData['mobilitaetsprogramm_code'] : null;
$_POST['herkunftsland_code'] = (isset($formData['herkunftsland_code']) && !empty($formData['herkunftsland_code'])) ? $formData['herkunftsland_code'] : 'A';
$_POST['ects_erworben'] = (isset($formData['ects_erworben']) && !empty($formData['ects_erworben'])) ? $formData['ects_erworben'] : null;
$_POST['ects_angerechnet'] = (isset($formData['ects_angerechnet']) && !empty($formData['ects_angerechnet'])) ? $formData['ects_angerechnet'] : null;
$_POST['lehreinheit_id'] = (isset($formData['lehreinheit_id']) && !empty($formData['lehreinheit_id'])) ? $formData['lehreinheit_id'] : null;
$this->form_validation->set_rules('nation_code', 'Nation_code', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Nation_code'])
]);
$this->form_validation->set_rules('herkunftsland_code', 'Herkunftsland_code', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Herkunftsland_code'])
]);
$this->form_validation->set_rules('mobilitaetsprogramm_code', 'Mobilitaetsprogramm_code', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Mobilitaetsprogramm_code'])
]);
$this->form_validation->set_rules('von', 'VonDatum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum'])
]);
$this->form_validation->set_rules('bis', 'VBisDatum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VBisDatum'])
]);
$this->form_validation->set_rules('ects_erworben', 'Ects_erworben', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_erworben'])
]);
$this->form_validation->set_rules('ects_angerechnet', 'Ects_angerechnet', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_angerechnet'])
]);
$this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$ort = (isset($formData['ort']) && !empty($formData['ort'])) ? $formData['ort'] : null;
$universitaet = (isset($formData['universitaet']) && !empty($formData['universitaet'])) ? $formData['universitaet'] : null;
$localPurposes = (isset($formData['localPurposes']) && !empty($formData['localPurposes'])) ? $formData['localPurposes'] : null;
$localSupports = (isset($formData['localSupports']) && !empty($formData['localSupports'])) ? $formData['localSupports'] : null;
$result = $this->BisioModel->insert([
'student_uid' => $student_uid,
'von' => $_POST['von'],
'bis' => $_POST['bis'],
'mobilitaetsprogramm_code' => $_POST['mobilitaetsprogramm_code'],
'nation_code' => $_POST['nation_code'],
'herkunftsland_code' => $_POST['herkunftsland_code'],
'lehreinheit_id' => $_POST['lehreinheit_id'],
'ort' => $ort,
'universitaet' => $universitaet,
'ects_erworben' => $_POST['ects_erworben'] ,
'ects_angerechnet' => $_POST['ects_angerechnet'],
'insertamum' => date('c'),
'insertvon' => $authUID,
]);
$bisio_id = $this->getDataOrTerminateWithError($result);
//check if localData (purposes)
if(count($localPurposes) > 0){
foreach ($localPurposes as $zweck){
$zweck = (int)$zweck;
$this->addMobilityPurpose($bisio_id, $zweck);
}
}
//check if localData (supports)
if(count($localSupports) > 0){
foreach ($localSupports as $support){
$this->addMobilitySupport($bisio_id, $support);
}
}
$this->terminateWithSuccess($bisio_id);
}
public function loadMobility($bisio_id)
{
$this->BisioModel->addSelect("*");
$this->BisioModel->addJoin('bis.tbl_mobilitaetsprogramm mp', 'ON (mp.mobilitaetsprogramm_code = bis.tbl_bisio.mobilitaetsprogramm_code)', 'LEFT');
$this->BisioModel->addJoin('lehre.tbl_lehreinheit le', 'ON (le.lehreinheit_id = bis.tbl_bisio.lehreinheit_id)','LEFT');
$result = $this->BisioModel->loadWhere(
array('bisio_id' => $bisio_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function updateMobility()
{
$this->load->library('form_validation');
$authUID = getAuthUID();
$student_uid = $this->input->post('uid');
if(!$student_uid)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$_POST['von'] = (isset($formData['von']) && !empty($formData['von'])) ? $formData['von'] : null;
$_POST['bis'] = (isset($formData['bis']) && !empty($formData['bis'])) ? $formData['bis'] : null;
$_POST['nation_code'] = (isset($formData['nation_code']) && !empty($formData['nation_code'])) ? $formData['nation_code'] : 'A';
$_POST['mobilitaetsprogramm_code'] = (isset($formData['mobilitaetsprogramm_code']) && !empty($formData['mobilitaetsprogramm_code'])) ? $formData['mobilitaetsprogramm_code'] : null;
$_POST['herkunftsland_code'] = (isset($formData['herkunftsland_code']) && !empty($formData['herkunftsland_code'])) ? $formData['herkunftsland_code'] : 'A';
$_POST['ects_erworben'] = (isset($formData['ects_erworben']) && !empty($formData['ects_erworben'])) ? $formData['ects_erworben'] : null;
$_POST['ects_angerechnet'] = (isset($formData['ects_angerechnet']) && !empty($formData['ects_angerechnet'])) ? $formData['ects_angerechnet'] : null;
$_POST['lehreinheit_id'] = (isset($formData['lehreinheit_id']) && !empty($formData['lehreinheit_id'])) ? $formData['lehreinheit_id'] : null;
$this->form_validation->set_rules('nation_code', 'Nation_code', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Nation_code'])
]);
$this->form_validation->set_rules('herkunftsland_code', 'Herkunftsland_code', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Herkunftsland_code'])
]);
$this->form_validation->set_rules('mobilitaetsprogramm_code', 'Mobilitaetsprogramm_code', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Mobilitaetsprogramm_code'])
]);
$this->form_validation->set_rules('von', 'VonDatum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum'])
]);
$this->form_validation->set_rules('bis', 'VBisDatum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VBisDatum'])
]);
$this->form_validation->set_rules('ects_erworben', 'Ects_erworben', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_erworben'])
]);
$this->form_validation->set_rules('ects_angerechnet', 'Ects_angerechnet', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_angerechnet'])
]);
$this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->BisioModel->update(
[
'bisio_id' => $formData['bisio_id']
],
[
'student_uid' => $student_uid,
'von' => $_POST['von'],
'bis' => $_POST['bis'],
'mobilitaetsprogramm_code' => $_POST['mobilitaetsprogramm_code'],
'nation_code' => $_POST['nation_code'],
'herkunftsland_code' => $_POST['herkunftsland_code'],
'lehreinheit_id' => $_POST['lehreinheit_id'],
'ort' => $formData['ort'],
'universitaet' => $formData['universitaet'],
'ects_erworben' => $_POST['ects_erworben'] ,
'ects_angerechnet' => $_POST['ects_angerechnet'],
'updateamum' => date('c'),
'updatevon' => $authUID,
]
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function deleteMobility($bisio_id)
{
//check if extension table exists
$result = $this->BisioModel->tableExists('extension', 'tbl_mo_bisioidzuordnung');
$data = $this->getDataOrTerminateWithError($result);
//if table exists check if existing entry
if(!empty($data))
{
$this->BisioModel->addSelect("count(*)");
$this->BisioModel->addJoin('extension.tbl_mo_bisioidzuordnung mo', 'ON (mo.bisio_id = bis.tbl_bisio.bisio_id)', 'LEFT');
$resultCheckMo = $this->BisioModel->loadWhere(
array('mo.bisio_id' => $bisio_id)
);
$resultCheckMo = $this->getDataOrTerminateWithError($resultCheckMo);
$count = current($resultCheckMo)->count;
$existsInExtension = $count > 0 ? true : false;
if($existsInExtension)
$this->terminateWithError($this->p->t('mobility', 'error_existingEntryInExtension'), self::ERROR_TYPE_GENERAL);
}
$result = $this->BisioModel->delete(
array('bisio_id' => $bisio_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getLVList($studiengang_kz)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudiengangkz($studiengang_kz);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getAllLehreinheiten()
{
$lv_id = $this->input->post('lv_id');
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$result = $this->LehreinheitModel->getLesFromLvIds($lv_id, $studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getLvsandLesByStudent($student_uid)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid);
$data = $this->getDataOrTerminateWithError($result);
$lv_ids = array();
$allData = array();
foreach ($data as $lehrveranstaltung) {
$lv_ids[] = $lehrveranstaltung->lehrveranstaltung_id;
}
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
foreach ($lv_ids as $id)
{
$result = $this->LehreinheitModel->getLesFromLvIds($id);
$data = $this->getDataOrTerminateWithError($result);
if (is_array($data)) {
$allData = array_merge($allData, $data);
}
}
return $this->terminateWithSuccess($allData);
}
public function getPurposes($bisio_id)
{
$bisio_id = (int)$bisio_id;
$this->load->model('codex/Bisiozweck_model', 'BisiozweckModel');
$this->BisiozweckModel->addSelect("*");
$this->BisiozweckModel->addJoin('bis.tbl_zweck zw', 'ON (zw.zweck_code = bis.tbl_bisio_zweck.zweck_code)');
$result = $this->BisiozweckModel->loadWhere(
array('bisio_id' => $bisio_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getSupports($bisio_id)
{
$bisio_id = (int)$bisio_id;
$this->load->model('codex/Bisioaufenthaltfoerderung_model', 'BisioaufenthaltfoerderungModel');
$this->BisioaufenthaltfoerderungModel->addSelect("*");
$this->BisioaufenthaltfoerderungModel->addJoin('bis.tbl_aufenthaltfoerderung af', 'ON (af.aufenthaltfoerderung_code = bis.tbl_bisio_aufenthaltfoerderung.aufenthaltfoerderung_code)');
$result = $this->BisioaufenthaltfoerderungModel->loadWhere(
array('bisio_id' => $bisio_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getListPurposes()
{
$this->load->model('codex/Zweck_model', 'ZweckModel');
$result = $this->ZweckModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getListSupports()
{
$this->load->model('codex/Aufenthaltfoerderung_model', 'AufenthaltfoerderungModel');
$result = $this->AufenthaltfoerderungModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function addMobilityPurpose($bisio_id, $local_purpose = null)
{
$zweck_code = $this->input->post('zweck_code');
if($local_purpose){
$zweck_code = $local_purpose;
}
$this->load->model('codex/Bisiozweck_model', 'BisiozweckModel');
if(!$local_purpose)
{
$check = $this->BisiozweckModel->loadWhere(
[
'bisio_id' => $bisio_id,
'zweck_code' => $zweck_code,
]
);
if (hasData($check))
{
$this->terminateWithError($this->p->t('ui', 'error_entryExisting'), self::ERROR_TYPE_GENERAL);
}
}
$result = $this->BisiozweckModel->insert(
array(
'bisio_id' => $bisio_id,
'zweck_code' => $zweck_code
)
);
$data = $this->getDataOrTerminateWithError($result);
if($local_purpose)
{
return $data;
}
return $this->terminateWithSuccess(current($data));
}
public function deleteMobilityPurpose($bisio_id)
{
$zweck_code = $this->input->post('zweck_code');
$this->load->model('codex/Bisiozweck_model', 'BisiozweckModel');
$result = $this->BisiozweckModel->delete(
array(
'bisio_id' => $bisio_id,
'zweck_code' => $zweck_code
)
);
$data = $this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess(current($data));
}
public function addMobilitySupport($bisio_id, $local_support = null)
{
$aufenthaltfoerderung_code = $this->input->post('aufenthaltfoerderung_code');
if($local_support){
$aufenthaltfoerderung_code = $local_support;
}
$this->load->model('codex/Bisioaufenthaltfoerderung_model', 'BisioaufenthaltfoerderungModel');
if(!$local_support)
{
$check = $this->BisioaufenthaltfoerderungModel->loadWhere(
[
'bisio_id' => $bisio_id,
'aufenthaltfoerderung_code' => $aufenthaltfoerderung_code,
]
);
if (hasData($check))
{
$this->terminateWithError($this->p->t('ui', 'error_entryExisting'), self::ERROR_TYPE_GENERAL);
}
}
$result = $this->BisioaufenthaltfoerderungModel->insert(
array(
'bisio_id' => $bisio_id,
'aufenthaltfoerderung_code' => $aufenthaltfoerderung_code
)
);
$data = $this->getDataOrTerminateWithError($result);
if($local_support)
{
return $data;
}
return $this->terminateWithSuccess(current($data));
}
public function deleteMobilitySupport($bisio_id)
{
$aufenthaltfoerderung_code = $this->input->post('aufenthaltfoerderung_code');
$this->load->model('codex/Bisioaufenthaltfoerderung_model', 'BisioaufenthaltfoerderungModel');
$result = $this->BisioaufenthaltfoerderungModel->delete(
array(
'bisio_id' => $bisio_id,
'aufenthaltfoerderung_code' => $aufenthaltfoerderung_code
)
);
$data = $this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess(current($data));
}
}
@@ -19,6 +19,7 @@ class Prestudent extends FHCAPI_Controller
'getAufmerksamdurch' => ['admin:r', 'assistenz:r'],
'getBerufstaetigkeit' => ['admin:r', 'assistenz:r'],
'getTypenStg' => ['admin:r', 'assistenz:r'],
'getBisstandort' => ['admin:r', 'assistenz:r'],
'getStudienplaene' => ['admin:r', 'assistenz:r'],
'getStudiengang' => ['admin:r', 'assistenz:r']
]);
@@ -265,6 +266,17 @@ class Prestudent extends FHCAPI_Controller
return $this->terminateWithSuccess(getData($result) ?: []);
}
public function getBisstandort()
{
$this->load->model('codex/Bisstandort_model', 'BisstandortModel');
$result = $this->BisstandortModel->load();
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result) ?: []);
}
public function getStudienplaene($prestudent_id)
{
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
@@ -0,0 +1,577 @@
<?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 addresses
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Pruefung extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getPruefungen' => ['admin:r', 'assistenz:r'],
'loadPruefung' => ['admin:r', 'assistenz:r'],
'getTypenPruefungen' => ['admin:r', 'assistenz:r'],
'getLehreinheiten' => ['admin:r', 'assistenz:r'],
'getAllLehreinheiten' => ['admin:r', 'assistenz:r'],
'getLvsByStudent' => ['admin:r', 'assistenz:r'],
'getLvsandLesByStudent' => ['admin:r', 'assistenz:r'],
'getLvsAndMas' => ['admin:r', 'assistenz:r'],
'getMitarbeiterLv' => ['admin:r', 'assistenz:r'],
'getNoten' => ['admin:r', 'assistenz:r'],
'checkZeugnisnoteLv' => ['admin:r', 'assistenz:r'],
'checkTermin1' => ['admin:r', 'assistenz:r'],
'insertPruefung' => self::PERM_LOGGED,
'updatePruefung' =>self::PERM_LOGGED,
'deletePruefung' =>self::PERM_LOGGED,
]);
//Load Models
$this->load->model('education/LePruefung_model', 'PruefungModel');
//version with postParameter
if ($this->router->method == 'insertPruefung')
{
$student_uid = $this->input->post('student_uid');
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
$student = $this->getDataOrTerminateWithError($result);
$prestudent_id = current($student)->prestudent_id;
$this->checkPermissionsForPrestudent($prestudent_id, ['admin:w', 'assistenz:w']);
}
// parameter from uri
if ($this->router->method == 'updatePruefung' || $this->router->method == 'deletePruefung')
{
$pruefung_id = current(array_slice($this->uri->rsegments, 2));
$result = $this->PruefungModel->load($pruefung_id);
$pruefung = $this->getDataOrTerminateWithError($result);
$student_uid = current($pruefung)->student_uid;
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
$student = $this->getDataOrTerminateWithError($result);
$prestudent_id = current($student)->prestudent_id;
$this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']);
}
if ($this->router->method == 'loadPruefung')
{
$pruefung_id = current(array_slice($this->uri->rsegments, 2));
$result = $this->PruefungModel->load($pruefung_id);
$pruefung = $this->getDataOrTerminateWithError($result);
$student_uid = current($pruefung)->student_uid;
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
$student = $this->getDataOrTerminateWithError($result);
$prestudent_id = current($student)->prestudent_id;
$this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']);
}
if ($this->router->method == 'getPruefungen')
{
$student_uid = current(array_slice($this->uri->rsegments, 2));
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
$student = $this->getDataOrTerminateWithError($result);
$prestudent_id = current($student)->prestudent_id;
$this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']);
}
// Load language phrases
$this->loadPhrases([
'global', 'ui','lehre'
]);
}
public function getPruefungen($student_uid, $studiensemester_kurzbz = null)
{
$result = $this->PruefungModel->getPruefungenByStudentuid($student_uid);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function loadPruefung($pruefung_id)
{
$this->PruefungModel->addSelect('tbl_pruefung.datum');
$this->PruefungModel->addSelect("TO_CHAR(tbl_pruefung.datum::timestamp, 'DD.MM.YYYY') AS format_datum");
$this->PruefungModel->addSelect('tbl_pruefung.anmerkung');
$this->PruefungModel->addSelect('tbl_pruefung.pruefungstyp_kurzbz');
$this->PruefungModel->addSelect('tbl_pruefung.pruefung_id');
$this->PruefungModel->addSelect('tbl_pruefung.lehreinheit_id');
$this->PruefungModel->addSelect('tbl_pruefung.student_uid');
$this->PruefungModel->addSelect('tbl_pruefung.mitarbeiter_uid');
$this->PruefungModel->addSelect('tbl_pruefung.punkte');
$this->PruefungModel->addSelect('tbl_pruefung.note');
$this->PruefungModel->addSelect('tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung');
$this->PruefungModel->addSelect('tbl_lehrveranstaltung.lehrveranstaltung_id');
$this->PruefungModel->addSelect('tbl_lehrveranstaltung.semester');
$this->PruefungModel->addSelect('tbl_lehrveranstaltung.lehrform_kurzbz');
$this->PruefungModel->addSelect('tbl_note.bezeichnung as note_bezeichnung');
$this->PruefungModel->addSelect('tbl_pruefungstyp.beschreibung as typ_beschreibung');
$this->PruefungModel->addSelect('tbl_lehreinheit.studiensemester_kurzbz as studiensemester_kurzbz');
$this->PruefungModel->addJoin('lehre.tbl_lehreinheit', 'lehre.tbl_pruefung.lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id');
$this->PruefungModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id');
$this->PruefungModel->addJoin('lehre.tbl_note', 'note');
$this->PruefungModel->addJoin('lehre.tbl_pruefungstyp', 'pruefungstyp_kurzbz');
$this->PruefungModel->addLimit(1);
$result = $this->PruefungModel->loadWhere(
array('pruefung_id' => $pruefung_id)
);
if (isError($result)) {
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
if (!hasData($result))
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Pruefung_id']), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess(current(getData($result)) ? : null);
}
/**
* Inserts a pruefung
*
* @param lehrveranstaltung_id, student_uid, lehreinheit_id
*
* @return values on success
* retval 0: pruefung inserted
* reval 1: pruefung and zeugnisnote inserted
* retval 2: pruefung inserted, no insert Zeugnisnote
* (change after date of examination)
* retval 3: pruefung of type Termin2 inserted
* and pruefung of type Termin1 as well
* retval 5: prueufungen Termin 2 and 1 inserted
* and no insert Zeugnisnote (change after date of examination)
*/
public function insertPruefung()
{
$authUID = getAuthUID();
$this->load->library('form_validation');
$this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung'), 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehrveranstaltung')]),
]);
$this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]),
]);
$this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]),
]);
$this->form_validation->set_rules(
'datum',
$this->p->t('global', 'datum'),
['is_valid_date']
);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
//calculate studiensemester_kurzbz this from lehreinheit (case newPruefung)
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
if (!$studiensemester_kurzbz)
{
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$result = $this->LehreinheitModel->load($this->input->post('lehreinheit_id'));
$lehreinheit = $this->getDataOrTerminateWithError($result);
$studiensemester_kurzbz = current($lehreinheit)->studiensemester_kurzbz;
if (isError($result))
{
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
}
$result = $this->PruefungModel->insert([
'lehreinheit_id' => $this->input->post('lehreinheit_id'),
'student_uid' => $this->input->post('student_uid'),
'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'),
'datum' => $this->input->post('datum'),
'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'),
'note' => $this->input->post('note'),
'anmerkung' => $this->input->post('anmerkung'),
'insertamum' => date('c'),
'insertvon' => $authUID,
]);
$this->getDataOrTerminateWithError($result);
//check if existing zeugnisnote
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$result = $this->ZeugnisnoteModel->loadWhere(array(
'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'),
'student_uid' => $this->input->post('student_uid'),
'studiensemester_kurzbz' => $studiensemester_kurzbz));
if (isError($result))
{
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
if (!hasData($result))
{
//insert zeugnisnote, if not existing
$result = $this->ZeugnisnoteModel->insert(array(
'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'),
'student_uid' => $this->input->post('student_uid'),
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'note' => $this->input->post('note'),
'uebernahmedatum' => date('c'),
'benotungsdatum' => $this->input->post('datum'),
'insertamum' => date('c'),
'insertvon' => $authUID
));
if (isError($result))
{
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess(1);
}
$return_code = 0;
//handling Termin1 if not existing
if($this->input->post('pruefungstyp_kurzbz') == "Termin2")
{
$resultP = $this->PruefungModel->loadWhere(array(
'lehreinheit_id' => $this->input->post('lehreinheit_id'),
'student_uid' => $this->input->post('student_uid'),
'pruefungstyp_kurzbz' => 'Termin1'));
if (isError($resultP))
{
$this->terminateWithError(getError($resultP), self::ERROR_TYPE_GENERAL);
}
if(!hasData($resultP))
{
//check if existing Zeugnisnote
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$this->ZeugnisnoteModel->addJoin('lehre.tbl_lehreinheit', 'lehrveranstaltung_id');
$resultP = $this->ZeugnisnoteModel->loadWhere(array(
'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'),
'student_uid' => $this->input->input->post('student_uid'),
'lehre.tbl_zeugnisnote.studiensemester_kurzbz' => $studiensemester_kurzbz));
if (isError($resultP))
{
$this->terminateWithError(getError($resultP), self::ERROR_TYPE_GENERAL);
}
if (!hasData($resultP))
{
$this->terminateWithError("Zeugnisnote existiert nicht", self::ERROR_TYPE_GENERAL);
}
$dataNote = current(getData($resultP));
$resultN = $this->PruefungModel->insert([
'lehreinheit_id' => $this->input->post('lehreinheit_id'),
'student_uid' => $this->input->post('student_uid'),
'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'),
'datum' => $dataNote->benotungsdatum,
'pruefungstyp_kurzbz' => 'Termin1',
'note' => $dataNote->note,
'punkte' => $dataNote->punkte,
'anmerkung' => 'automatisiert aus Zeugnisnote erstellt',
'insertamum' => date('c'),
'insertvon' => $authUID,
]);
if (isError($resultN)) {
$this->terminateWithError(getError($resultN), self::ERROR_TYPE_GENERAL);
}
$return_code = 3;
}
}
$note = current(getData($result));
$uebernahmedatum = new DateTime($note->uebernahmedatum);
$benotungsdatum = new DateTime($note->benotungsdatum);
$checkDate = $uebernahmedatum === '' || $benotungsdatum > $uebernahmedatum
? $benotungsdatum
: $uebernahmedatum;
if ($checkDate >= $this->input->post('datum') && $note !== $note->note)
{
$this->terminateWithSuccess($return_code + 2);
}
$this->terminateWithSuccess($return_code + 2);
}
/**
* Updates a pruefung
*
* @param pruefung_id
*
* @return success or error
*
* no impact on lehre.tbl_zeugnisnote
*/
public function updatePruefung($pruefung_id)
{
$result = $this->PruefungModel->load($pruefung_id);
$oldpruefung = $this->getDataOrTerminateWithError($result);
if (!$oldpruefung)
show_404(); // Pruefung that should be updated does not exist
$authUID = getAuthUID();
$this->load->library('form_validation');
$this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung'), 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehrveranstaltung')]),
]);
$this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]),
]);
$this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]),
]);
$this->form_validation->set_rules(
'datum',
$this->p->t('global', 'datum'),
['is_valid_date']
);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->PruefungModel->update(
[
'pruefung_id' => $pruefung_id
],
[ 'lehreinheit_id' => $this->input->post('lehreinheit_id'),
'student_uid' => $this->input->post('student_uid'),
'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'),
'note' => $this->input->post('note'),
'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'),
'datum' => $this->input->post('datum'),
'anmerkung' => $this->input->post('anmerkung'),
'updatevon' => $authUID,
'updateamum' => date('c'),
]
);
$this->getDataOrTerminateWithError($result);
return $this->outputJsonSuccess(true);
}
/**
* Deletes a pruefung
*
* @param pruefung_id
*
* @return success or error
*
* no impact on lehre.tbl_zeugnisnote
*/
public function deletePruefung($pruefung_id)
{
$result = $this->PruefungModel->load($pruefung_id);
$oldpruefung = $this->getDataOrTerminateWithError($result);
if (!$oldpruefung)
show_404(); // Pruefung that should be deleted does not exist
$result = $this->PruefungModel->delete(
[
'pruefung_id' => $pruefung_id
]
);
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess(true);
}
public function getTypenPruefungen()
{
$this->load->model('education/Pruefungstyp_model', 'PruefungtypModel');
//TODO(Manu) sort Termin3
$this->PruefungtypModel->addOrder('sort', 'ASC');
$result = $this->PruefungtypModel->loadWhere(
array('abschluss' => 'false')
);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result) ?: []);
}
public function getAllLehreinheiten()
{
$lv_id = $this->input->post('lv_id');
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$result = $this->LehreinheitModel->getLesFromLvIds($lv_id, $studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getLvsandLesByStudent($student_uid, $semester_kurzbz=null)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid, $semester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
$lv_ids = array();
$allData = array();
foreach ($data as $lehrveranstaltung) {
$lv_ids[] = $lehrveranstaltung->lehrveranstaltung_id;
}
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
foreach ($lv_ids as $id)
{
$result = $this->LehreinheitModel->getLesFromLvIds($id, $semester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
if (is_array($data)) {
$allData = array_merge($allData, $data);
}
}
return $this->terminateWithSuccess($allData);
}
public function getLvsAndMas($student_uid)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid);
$data = $this->getDataOrTerminateWithError($result);
$lv_ids = array();
$allDataMa = array();
foreach ($data as $lehrveranstaltung)
{
$lv_ids[] = $lehrveranstaltung->lehrveranstaltung_id;
}
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
foreach ($lv_ids as $id)
{
$resultMa = $this->MitarbeiterModel->getMitarbeiterFromLV($id);
$dataMa = $this->getDataOrTerminateWithError($resultMa);
if (is_array($dataMa))
{
$allDataMa = array_merge($allDataMa, $dataMa);
}
}
return $this->terminateWithSuccess($allDataMa);
}
public function getLvsByStudent($student_uid, $studiensemester_kurzbz = null)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid, $studiensemester_kurzbz);
$data = $this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($data);
}
public function getMitarbeiterLv($lv_id)
{
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$result = $this->MitarbeiterModel->getMitarbeiterFromLV($lv_id);
$data = $this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($data);
}
public function getNoten()
{
$this->load->model('education/Note_model', 'NoteModel');
$this->NoteModel->addOrder('note', 'ASC');
$result = $this->NoteModel->load();
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result) ?: []);
}
public function checkZeugnisnoteLv()
{
$student_uid = $this->input->post('student_uid');
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
$lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id');
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$result = $this->ZeugnisnoteModel->loadWhere(array(
'lehrveranstaltung_id' => $lehrveranstaltung_id,
'student_uid' => $student_uid,
'studiensemester_kurzbz' => $studiensemester_kurzbz));
$data = $this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($data);
}
}
@@ -647,15 +647,8 @@ class Status extends FHCAPI_Controller
return $this->outputJsonSuccess(true);
}
public function loadStatus()
public function loadStatus($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester)
{
$_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
$prestudent_id = $this->input->post('prestudent_id');
$status_kurzbz = $this->input->post('status_kurzbz');
$ausbildungssemester = $this->input->post('ausbildungssemester');
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
$result = $this->PrestudentstatusModel->loadWhere(
array(
'prestudent_id' => $prestudent_id,
@@ -1344,13 +1337,13 @@ class Status extends FHCAPI_Controller
'updatevon' => $authUID
];
foreach ([
'orgform_kurzbz',
'anmerkung',
'bewerbung_abgeschicktamum',
'studienplan_id',
'rt_stufe',
'statusgrund_id'
] as $key)
'orgform_kurzbz',
'anmerkung',
'bewerbung_abgeschicktamum',
'studienplan_id',
'rt_stufe',
'statusgrund_id'
] as $key)
if ($this->input->post($key))
$updateData[$key] = $this->input->post($key);
@@ -55,7 +55,7 @@ class Student extends FHCAPI_Controller
// Load language phrases
$this->loadPhrases([
'ui'
'ui', 'lehre'
]);
}
@@ -156,6 +156,8 @@ class Student extends FHCAPI_Controller
$uid = $student ? current($student)->student_uid : null;
$studiengang_kz = $student ? current($student)->studiengang_kz : null;
$result = $this->PrestudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
$person = $this->getDataOrTerminateWithError($result);
@@ -223,20 +225,35 @@ class Student extends FHCAPI_Controller
// Check PKs
if (count($update_lehrverband) + count($update_student) && $uid === null) {
// TODO(chris): phrase
$this->terminateWithValidationErrors(['' => "Kein/e StudentIn vorhanden!"]);
$this->terminateWithValidationErrors(['' => $this->p->t('lehre', 'error_no_student')]);
}
if (count($update_person) && $person_id === null) {
// TODO(chris): phrase
$this->terminateWithValidationErrors(['' => "Keine Person vorhanden!"]);
$this->terminateWithValidationErrors(['' => $this->p->t('lehre', 'error_no_person')]);
}
// Do Updates
if (count($update_lehrverband)) {
$result = $this->StudentlehrverbandModel->update([
$curstudlvb = $this->StudentlehrverbandModel->load([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $uid
], $update_lehrverband);
]);
if(hasData($curstudlvb) && count(getData($curstudlvb)) > 0 )
{
$result = $this->StudentlehrverbandModel->update([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $uid
], $update_lehrverband);
}
else
{
$result = $this->StudentlehrverbandModel->insert(array_merge([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'student_uid' => $uid,
'studiengang_kz' => $studiengang_kz
], $update_lehrverband));
}
$this->getDataOrTerminateWithError($result);
}
@@ -264,4 +264,4 @@ class Person extends API_Controller
return success('Input data are valid');
}
}
}
+21 -5
View File
@@ -5,8 +5,12 @@ if (! defined("BASEPATH")) exit("No direct script access allowed");
class UHSTAT1 extends FHC_Controller
{
const BERECHTIGUNG_UHSTAT_VERWALTEN = 'student/uhstat1daten_verwalten';
const LOGIN_SESSION_INDEX = 'bewerbung/user';
const PERSON_ID_SESSION_INDEX = 'bewerbung/personId';
const CODEX_OESTERREICH = 'A';
const CODEX_UNKNOWN_YEAR = 9999;
const CODEX_UNKNOWN_NATION = 'XXX';
const CODEX_UNKNOWN_BILDUNGMAX = 999;
const LOWER_BOUNDARY_YEARS = 160;
const UPPER_BOUNDARY_YEARS = 20;
@@ -210,7 +214,9 @@ class UHSTAT1 extends FHC_Controller
else
return true;
if (!isset($bildungsstaat)) return true;
// if no Bildungsstaat or Bildungmax unknown - valid
if (!isset($bildungsstaat) || $bildungmax == self::CODEX_UNKNOWN_BILDUNGMAX) return true;
// find out if abschluss is in Austria
$this->AbschlussModel->addSelect("in_oesterreich");
@@ -219,8 +225,11 @@ class UHSTAT1 extends FHC_Controller
if (hasData($abschlussRes))
{
$in_oesterreich = getData($abschlussRes)[0]->in_oesterreich;
// invalid if abschluss in Austria, but not Bildungsstaat, or abschluss not in Austria, but Bildungsstaat in Austria
return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH) || (!$in_oesterreich && $bildungsstaat != self::CODEX_OESTERREICH);
// valid if Bildungsstaat and Abschluss in Austria, or Bildungsstaat and Abschluss not in Austria
// (or Abschluss not in Austria and Bildungsstaat unknown)
return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH)
|| (!$in_oesterreich && ($bildungsstaat != self::CODEX_OESTERREICH || $bildungsstaat == self::CODEX_UNKNOWN_NATION));
}
return false;
@@ -363,7 +372,11 @@ class UHSTAT1 extends FHC_Controller
// get realistic birth years, dated back from current year
$currYear = date("Y");
$formMetaData['jahre'] = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS);
$yearRange = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS);
$formMetaData['jahre'] = array_combine($yearRange, $yearRange);
// add "unknown" option
$formMetaData['jahre'][self::CODEX_UNKNOWN_YEAR] = 'unbekannt';
return success($formMetaData);
}
@@ -411,7 +424,10 @@ class UHSTAT1 extends FHC_Controller
private function _getValidPersonId($berechtigungsArt)
{
// if coming from bewerbungstool - person id is in session (person must be logged in bewerbungstool)
if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX]) && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX]))
if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX])
&& is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX])
&& isset($_SESSION[self::LOGIN_SESSION_INDEX])
)
return $_SESSION[self::PERSON_ID_SESSION_INDEX];
// if person id passed directly...
@@ -0,0 +1,213 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Mylv extends Auth_Controller
{
/**
* Object initialization
*/
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?
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
*/
public function Student()
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID());
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result));
}
/**
*/
public function Studiensemester()
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->StudiensemesterModel->getWhereStudentHasLvs(getAuthUID());
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result));
}
/**
*/
public function Lvs($studiensemester_kurzbz)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage());
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result));
}
/**
*/
public function Info($studiensemester_kurzbz, $lehrveranstaltung_id)
{
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id);
if (isError($result))
return $this->outputJsonError(getError($result));
$lv = current(getData($result) ?: []);
if (!$lv)
return $this->outputJsonError('Could\'t find Lehrveranstaltung with id: ' . $lehrveranstaltung_id);
$this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel');
$result = $this->LehreinheitmitarbeiterModel->getForLv($lehrveranstaltung_id, $studiensemester_kurzbz);
if (isError($result))
return $this->outputJsonError(getError($result));
$lvinfo = [];
$lvinfo['lektoren'] = getData($result) ?: [];
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$lvinfo['lektoren'] = array_values(array_filter($lvinfo['lektoren'], function ($v) use ($kollisionsfreie_user) {
return !in_array($v->uid, $kollisionsfreie_user);
}));
$lvinfo['lvLeitung'] = array_values(array_filter($lvinfo['lektoren'], function ($v) {
return $v->lehrfunktion_kurzbz == 'LV-Leitung';
}));
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$result = $this->OrganisationseinheitModel->getWithType($lv->oe_kurzbz);
if (isError($result))
return $this->outputJsonError(getError($result));
$lvinfo['oe'] = current(getData($result) ?: []);
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$result = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('Leitung', $lv->oe_kurzbz);
if (isError($result))
return $this->outputJsonError(getError($result));
$lvinfo['oeLeitung'] = getData($result) ?: [];
$result = $this->LehrveranstaltungModel->getKoordinator($lehrveranstaltung_id, $studiensemester_kurzbz);
if (isError($result))
return $this->outputJsonError(getError($result));
$lvinfo['koordinator'] = getData($result) ?: [];
if (defined('ACTIVE_ADDONS') && in_array('lvinfo', explode(';', ACTIVE_ADDONS)) && file_exists(FHCPATH . 'addons/lvinfo/include/lvinfo.class.php'))
{
require_once(FHCPATH . 'addons/lvinfo/include/lvinfo.class.php');
$lvinfoObj = new lvinfo();
$lvinfoObj->loadLVinfo($lehrveranstaltung_id, $studiensemester_kurzbz, null, true);
if (is_array($lvinfoObj->result))
{
$oldP = property_exists($this, 'p') ? $this->p : null;
$result = [];
$lvinfos = $lvinfoObj->result;
$lvinfoSet = new lvinfo();
$lvinfoSet->load_lvinfo_set($studiensemester_kurzbz);
foreach ($lvinfos as $lvi)
{
$this->p = null;
$this->loadPhrases('ui', $lvi->sprache);
$result[$lvi->sprache] = [];
foreach ($lvinfoSet->result as $set)
{
$key = $set->lvinfo_set_kurzbz;
if (!isset($lvi->data[$key]))
continue;
$info = [
'header' => $set->lvinfo_set_bezeichnung[$lvi->sprache]
];
if (isset($set->einleitungstext[$lvi->sprache]))
$info['subheader'] = $set->einleitungstext[$lvi->sprache];
switch ($set->lvinfo_set_typ)
{
case 'boolean':
$info['body'] = $this->p->t('ui', $lvi->data[$key] === true ? 'ja' : 'nein');
break;
case 'array':
$info['body'] = array_map('htmlspecialchars', $lvi->data[$key]);
break;
case 'editor':
$info['body'] = $lvi->data[$key];
break;
default:
$info['body'] = htmlspecialchars($lvi->data[$key]);
}
if ($info['body'])
$result[$lvi->sprache][] = $info;
}
}
if ($result)
{
$lvinfo['lvinfo'] = $result;
$lvinfo['lvinfoDefaultLang'] = getUserLanguage();
$this->load->model('system/Sprache_model', 'SpracheModel');
$result = $this->SpracheModel->loadMultiple(array_keys($result));
if (!isError($result))
{
$result = getData($result);
$lvinfo['sprachen'] = [];
foreach ($result as $sprache) {
$lvinfo['sprachen'][$sprache->sprache] = $sprache;
}
}
}
$this->p = $oldP;
}
}
$this->outputJsonSuccess($lvinfo);
}
/**
*/
public function Pruefungen($lehrveranstaltung_id)
{
$this->load->model('education/Pruefung_model', 'PruefungModel');
$result = $this->PruefungModel->getByStudentAndLv(getAuthUID(), $lehrveranstaltung_id, getUserLanguage());
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result));
}
}
@@ -0,0 +1,73 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Stundenplan extends Auth_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'index' => ['basis/cis'],
'Reservierungen' => ['basis/cis'],
'Stunden' => ['basis/cis'],
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
*/
public function index()
{
$this->load->model('ressource/Stundenplan_model', 'StundenplanModel');
/* $result = $this->StundenplanModel->loadForUid(getAuthUID());
if (isError($result))
return $this->outputJsonError(getError($result));
*/
$res = $this->StundenplanModel->stundenplanGruppierung($this->StundenplanModel->getStundenplanQuery(getAuthUID()));
$res = getData($res);
$this->outputJsonSuccess($res);
}
/**
*/
public function Reservierungen()
{
$this->load->model('ressource/Reservierung_model', 'ReservierungModel');
$result = $this->ReservierungModel->loadForUid(getAuthUID());
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result));
}
/**
*/
public function Stunden()
{
$this->load->model('ressource/Stunde_model', 'StundeModel');
$result = $this->StundeModel->load();
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result));
}
}
@@ -1,168 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Noten extends Auth_Controller
{
public function __construct()
{
parent::__construct([
'get' => 'student/noten:r',
'getZeugnis' => 'student/noten:r',
'update' => ['admin:w', 'assistenz:w']
]);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
}
public function get()
{
$this->load->model('codex/Note_model', 'NoteModel');
$result = $this->NoteModel->addOrder('note');
$result = $this->NoteModel->load();
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->outputJson($result);
}
public function getZeugnis($prestudent_id, $all = null)
{
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$result = $this->StudentModel->loadWhere([
'prestudent_id' => $prestudent_id
]);
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
return $this->outputJson($result);
}
if (!hasData($result))
return $this->outputJsonSuccess(null);
$student_uid = current(getData($result))->student_uid;
$studiensemester_kurzbz = ($all === null) ? $this->variablelib->getVar('semester_aktuell') : null;
$result = $this->ZeugnisnoteModel->getZeugnisnoten($student_uid, $studiensemester_kurzbz);
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->outputJson($result);
}
public function update()
{
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$this->load->library('form_validation');
$_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
if (empty($_POST) || !is_array(current($_POST))) {
$result = $this->hasPermissionUpdate($this->input->post('lehrveranstaltung_id'), $this->input->post('student_uid'));
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
return $this->outputJson($result);
}
$this->form_validation->set_rules('lehrveranstaltung_id', 'Lehrverantaltung ID', 'required|numeric');
$this->form_validation->set_rules('student_uid', 'Student UID', 'required');
$this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester Kurzbezeichnung', 'required');
$this->form_validation->set_rules('note', 'Note', 'required|numeric');
$post = [$_POST];
} else {
foreach ($_POST as $i => $data) {
$lvid = isset($data['lehrveranstaltung_id']) ? $data['lehrveranstaltung_id'] : null;
$uid = isset($data['student_uid']) ? $data['student_uid'] : null;
$result = $this->hasPermissionUpdate($lvid, $uid);
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
return $this->outputJson($result);
}
$this->form_validation->set_rules($i . '[lehrveranstaltung_id]', '#' . $i . ' Lehrverantaltung ID', 'required|numeric');
$this->form_validation->set_rules($i . '[student_uid]', '#' . $i . ' Student UID', 'required');
$this->form_validation->set_rules($i . '[studiensemester_kurzbz]', '#' . $i . ' Studiensemester Kurzbezeichnung', 'required');
$this->form_validation->set_rules($i . '[note]', '#' . $i . ' Note', 'required|numeric');
}
$post = $_POST;
}
if ($this->form_validation->run() == false) {
$this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
return $this->outputJsonError($this->form_validation->error_array());
}
$final_result = success();
$this->ZeugnisnoteModel->db->trans_start();
foreach ($post as $i => $data) {
$note = $data['note'];
unset($data['note']);
$result = $this->ZeugnisnoteModel->update($data, [
'note' => $note,
'benotungsdatum' => date('c'),
'updateamum' => date('c'),
'updatevon' => getAuthUID()
]);
if (isError($result)) {
$final_result = $result;
break;
}
}
$this->ZeugnisnoteModel->db->trans_complete();
if (isError($final_result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
}
$this->outputJson($final_result);
}
protected function hasPermissionUpdate($lehrveranstaltung_id, $student_uid)
{
// TODO(chris): error phrases!
if ($lehrveranstaltung_id === null || $student_uid === null)
return success();
$result = $this->StudentModel->load([$student_uid]);
if (isError($result))
return $result;
if (!hasData($result))
return error('Fehler beim Ermitteln des Studenten');
$student = current(getData($result));
if ($this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz))
return success();
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz))
return success();
$result = $this->StudienplanModel->getAllOesForLv($lehrveranstaltung_id);
if (isError($result))
return $result;
$oes = getData($result) ?: [];
$result = $this->LehrveranstaltungModel->getStg($lehrveranstaltung_id);
if (isError($result))
return $result;
if (hasData($result))
$oes[] = current(getData($result));
foreach ($oes as $oe) {
if ($this->permissionlib->isBerechtigt('admin', 'suid', $oe->oe_kurzbz))
return success();
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $oe->oe_kurzbz))
return success();
}
return error('Forbidden');
}
}
+76
View File
@@ -0,0 +1,76 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
class Api extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => 'dashboard/admin:rw',
'getNews' => 'dashboard/benutzer:r',
'getAmpeln' => 'dashboard/benutzer:r',
)
);
$this->load->library('AuthLib', null, 'AuthLib');
$this->_setAuthUID();
}
public function index()
{
echo 'Dashboard API Controller';
}
/**
* Get News.
*/
public function getNews()
{
$limit = $this->input->get('limit');
$this->load->model('content/News_model', 'NewsModel');
$result = $this->NewsModel->getAll($limit);
if (hasData($result))
{
$this->outputJson(getData($result), REST_Controller::HTTP_OK);
}
else
{
$this->terminateWithJsonError('fehler entdeckt');
}
}
/**
* Get Ampeln.
*/
public function getAmpeln()
{
$this->load->model('content/Ampel_model', 'AmpelModel');
$result = $this->AmpelModel->getByUser($this->_uid);
if (hasData($result))
{
$this->outputJson(getData($result), REST_Controller::HTTP_OK);
}
else
{
$this->terminateWithJsonError('fehler entdeckt');
}
}
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
}
@@ -0,0 +1,216 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
/**
* Description of Config
*
* @author bambi
*/
class Config extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => 'dashboard/benutzer:r',
'dummy' => 'dashboard/benutzer:r',
'genWidgetId' => 'dashboard/benutzer:rw',
'addWidgetsToPreset' => 'dashboard/admin:rw',
'removeWidgetFromPreset' => 'dashboard/admin:rw',
'addWidgetsToUserOverride' => 'dashboard/benutzer:rw',
'removeWidgetFromUserOverride' => 'dashboard/benutzer:rw',
'funktionen' => 'dashboard/admin:r',
'preset' => 'dashboard/admin:r',
'presetBatch' => 'dashboard/admin:r'
)
);
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
$this->load->library('AuthLib', null, 'AuthLib');
$this->load->model('ressource/Funktion_model', 'FunktionModel');
}
public function index()
{
$dashboard_kurzbz = $this->input->get('db');
$uid = $this->AuthLib->getAuthObj()->username;
$dashboard = $this->DashboardLib->getDashboardByKurzbz($dashboard_kurzbz);
if(!$dashboard) {
http_response_code(404);
$this->terminateWithJsonError(array(
'error' => 'Dashboard ' . $dashboard_kurzbz . ' not found.'
));
}
$mergedconfig = $this->DashboardLib->getMergedConfig($dashboard->dashboard_id, $uid);
$this->outputJsonSuccess($mergedconfig);
}
public function genWidgetId()
{
$dashboard_kurzbz = $this->input->get('db');
$widgetid = $this->DashboardLib->generateWidgetId($dashboard_kurzbz);
$this->outputJsonSuccess(array(
'widgetid' => $widgetid
));
}
public function addWidgetsToPreset()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$preset = $this->DashboardLib->getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz);
$preset_decoded = json_decode($preset->preset, true);
$this->DashboardLib->addWidgetsToWidgets($preset_decoded['widgets'], $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
$preset->preset = json_encode($preset_decoded);
$result = $this->DashboardLib->insertOrUpdatePreset($preset);
if (isError($result)) {
http_response_code(500);
$this->terminateWithJsonError('preset could not be saved');
}
$this->outputJsonSuccess(array('msg' => 'preset successfully stored.', 'data' => $preset_decoded));
}
public function removeWidgetFromPreset()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$widgetid = $input->widgetid;
$preset = $this->DashboardLib->getPreset($dashboard_kurzbz, $funktion_kurzbz);
if ($preset === null) {
http_response_code(404);
$this->terminateWithJsonError('preset for dashboard ' . $dashboard_kurzbz . ' and funktion ' . $funktion_kurzbz . ' not found.');
}
$preset_decoded = json_decode($preset->preset, true);
if (!$this->DashboardLib->removeWidgetFromWidgets($preset_decoded['widgets'], $funktion_kurzbz, $widgetid))
{
http_response_code(404);
$this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
}
$preset->preset = json_encode($preset_decoded);
$result = $this->DashboardLib->insertOrUpdatePreset($preset);
if (isError($result))
{
http_response_code(500);
$this->terminateWithJsonError('failed to remove widget');
}
$this->outputJsonSuccess(array('msg' => 'preset successfully updated.'));
}
public function addWidgetsToUserOverride()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$uid = $this->AuthLib->getAuthObj()->username;
$override = $this->DashboardLib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid);
$override_decoded = json_decode($override->override, true);
$this->DashboardLib->addWidgetsToWidgets($override_decoded['widgets'], $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
$override->override = json_encode($override_decoded);
$result = $this->DashboardLib->insertOrUpdateOverride($override);
if (isError($result)) {
http_response_code(500);
$this->terminateWithJsonError('override could not be saved');
}
$this->outputJsonSuccess(array('msg' => 'override successfully stored.', 'data' => $override_decoded));
}
public function removeWidgetFromUserOverride()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$uid = $this->AuthLib->getAuthObj()->username;
$widgetid = $input->widgetid;
$override = $this->DashboardLib->getOverride($dashboard_kurzbz, $uid);
if (empty($override)) {
http_response_code(404);
$this->terminateWithJsonError('userconfig for dashboard ' . $dashboard_kurzbz . ' not found.');
}
$override_decoded = json_decode($override->override, true);
if (!$this->DashboardLib->removeWidgetFromWidgets($override_decoded['widgets'], $funktion_kurzbz, $widgetid))
{
http_response_code(404);
$this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
}
$override->override = json_encode($override_decoded);
$result = $this->DashboardLib->insertOrUpdateOverride($override, $uid);
if (isError($result))
{
http_response_code(500);
$this->terminateWithJsonError('failed to remove widget');
}
$this->outputJsonSuccess(array('msg' => 'override successfully updated.'));
}
public function funktionen()
{
$funktionen = $this->FunktionModel->load();
if (isError($funktionen)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($funktionen)
]);
}
return $this->outputJsonSuccess(getData($funktionen) ?: []);
}
public function preset()
{
$db = $this->input->get('db');
$funktion = $this->input->get('funktion');
$conf = $this->DashboardLib->getPreset($db, $funktion);
if (!$conf)
return $this->outputJsonSuccess(['widgets' => [$funktion => []]]);
return $this->outputJsonSuccess(json_decode($conf->preset, true));
}
public function presetBatch()
{
$db = $this->input->get('db');
$funktionen = $this->input->get('funktionen');
$result = [];
foreach ($funktionen as $funktion) {
$conf = $this->DashboardLib->getPreset($db, $funktion);
if ($conf)
{
$preset = json_decode($conf->preset, true);
if (!isset($preset['widgets']) || !isset($preset['widgets'][$funktion]))
$result[$funktion] = [];
else
$result[$funktion] = $preset['widgets'][$funktion];
}
else
$result[$funktion] = [];
}
return $this->outputJsonSuccess($result);
}
}
@@ -0,0 +1,86 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
/**
* Description of Widget
*
* @author chris
*/
class Dashboard extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => 'dashboard/admin:r',
'create' => 'dashboard/admin:rw',
'update' => 'dashboard/admin:rw',
'delete' => 'dashboard/admin:rw'
)
);
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
$this->load->model('dashboard/Dashboard_model', 'DashboardModel');
}
public function index()
{
$result = $this->DashboardModel->load();
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
public function create()
{
$input = $this->getPostJSON();
$result = $this->DashboardModel->insert($input);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
public function update()
{
$input = $this->getPostJSON();
$result = $this->DashboardModel->update($input->dashboard_id, $input);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
public function delete()
{
$input = $this->getPostJSON();
$result = $this->DashboardModel->delete($input->dashboard_id);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
}
@@ -0,0 +1,58 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*/
class DashboardDemo extends Auth_Controller
{
private $_uid; // uid of the logged user
/**
* Constructor
*/
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'dashboard/benutzer:r',
'admin' => 'dashboard/admin:rw'
)
);
$this->load->library('AuthLib');
$this->load->library('WidgetLib');
$this->_setAuthUID(); // sets property uid
$this->setControllerId(); // sets the controller id
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function index()
{
$this->load->view('dashboard/dashboard_demo.php', []);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function admin()
{
$this->load->view('dashboard/dashboard_demo_admin.php', []);
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
}
@@ -0,0 +1,109 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
/**
* Description of Widget
*
* @author chris
*/
class Widget extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => ['dashboard/benutzer:r', 'dashboard/admin:r'],
'getAll' => 'dashboard/admin:r',
'getWidgetsForDashboard' => ['dashboard/benutzer:rw', 'dashboard/admin:r'],
'setAllowed' => 'dashboard/admin:rw'
)
);
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
$this->load->model('dashboard/Widget_model', 'WidgetModel');
$this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel');
}
public function index()
{
$widget_id = $this->input->get('id');
$widget = $this->WidgetModel->load($widget_id);
if (isError($widget) || !getData($widget))
return $this->outputJsonSuccess([
"widget_id" => 0,
"widget_kurzbz" => "notfound",
"arguments" => json_encode([
"className" => 'alert-danger',
"title" => 'Widget Not Found',
"msg" => 'The widget with the id ' . $widget_id . ' could not be found'
]),
"setup" => json_encode([
"name" => 'Widget Not Found',
"file" => 'DashboardWidget/Default.js',
"width" => 1,
"height" => 1
])
]);
return $this->outputJsonSuccess(current(getData($widget)));
}
public function getAll()
{
$dashboard_id = $this->input->get('dashboard_id');
$result = $this->WidgetModel->getWithAllowedForDashboard($dashboard_id);
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result) ?: []);
}
public function getWidgetsForDashboard()
{
$db = $this->input->get('db');
$result = $this->WidgetModel->getForDashboard($db);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
$this->outputJsonSuccess(getData($result) ?: []);
}
public function setAllowed()
{
$input = $this->getPostJSON();
$dashboard_id = $input->dashboard_id;
$widget_id = $input->widget_id;
$action = $input->action;
if ($action == 'add') {
$result = $this->DashboardWidgetModel->insert([
'dashboard_id' => $dashboard_id,
'widget_id' => $widget_id
]);
} elseif ($action == 'delete') {
$result = $this->DashboardWidgetModel->delete([
'dashboard_id' => $dashboard_id,
'widget_id' => $widget_id
]);
} else {
http_response_code(404); // TODO(chris): 400?
$this->terminateWithJsonError([
'error' => 'action value invalid'
]);
}
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result));
}
}
@@ -195,10 +195,10 @@ class AnrechnungJob extends JOB_Controller
$studiengang_bezeichnung = $this->StudiengangModel->load($studiengang_kz)->retval[0]->stg_bezeichnung;
// Get STGL mail address
$stglMailReceiver_arr = self::_getSTGLMailAddress($studiengang_kz);
$stglMailReceiver_arr = $this->_getSTGLMailAddress($studiengang_kz);
// Get HTML table with new Anrechnungen of that STG plus amount of them
list ($anrechnungen_amount, $anrechnungen_table) = self::_getSTGLMailDataTable($studiengang_kz, $anrechnungen);
list ($anrechnungen_amount, $anrechnungen_table) = $this->_getSTGLMailDataTable($studiengang_kz, $anrechnungen);
// Link to Antrag genehmigen dashboard
$url =
@@ -514,8 +514,6 @@ html;
'vorname' => $stgl->vorname
);
}
return $stglMailAdress_arr;
}
// If not available, get assistance mail address
else
@@ -524,12 +522,13 @@ html;
if (hasData($result))
{
return array(
$result->retval[0]->email,
''
$stglMailAdress_arr[]= array(
'to' => $result->retval[0]->email,
'vorname' => ''
);
}
}
return $stglMailAdress_arr;
}
// Build HTML table with yesterdays new Anrechnungen of the given STG
+2 -2
View File
@@ -183,8 +183,8 @@ class AntragJob extends JOB_Controller
$data,
$to,
'Anträge - Aktion(en) erforderlich',
DEFAULT_SANCHO_HEADER_IMG,
DEFAULT_SANCHO_FOOTER_IMG,
'',
'',
'',
$cc
))
@@ -9,8 +9,8 @@ class IssueResolver extends IssueResolver_Controller
{
parent::__construct();
// set fehler codes which can be resolved by the job
// structure: fehlercode => class (library) name for resolving
// set fehler codes which can be resolved by the job, with own resolver defined
// structure: fehlercode => class (library) name for resolving in "resolvers" folder
$this->_codeLibMappings = array(
'CORE_ZGV_0001' => 'CORE_ZGV_0001',
'CORE_ZGV_0002' => 'CORE_ZGV_0002',
@@ -30,7 +30,6 @@ class IssueResolver extends IssueResolver_Controller
'CORE_STG_0002' => 'CORE_STG_0002',
'CORE_STG_0003' => 'CORE_STG_0003',
'CORE_STG_0004' => 'CORE_STG_0004',
'CORE_STUDENTSTATUS_0001' => 'CORE_STUDENTSTATUS_0001',
'CORE_STUDENTSTATUS_0002' => 'CORE_STUDENTSTATUS_0002',
'CORE_STUDENTSTATUS_0003' => 'CORE_STUDENTSTATUS_0003',
'CORE_STUDENTSTATUS_0004' => 'CORE_STUDENTSTATUS_0004',
@@ -51,5 +50,11 @@ class IssueResolver extends IssueResolver_Controller
'CORE_PERSON_0003' => 'CORE_PERSON_0003',
'CORE_PERSON_0004' => 'CORE_PERSON_0004'
);
// fehler which are resolved by the job the same way as they are produced
// structure: fehlercode => class (library) name for resolving in "plausichecks" folder
$this->_codeProducerLibMappings = array(
'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv',
);
}
}
@@ -51,7 +51,8 @@ class OneTimeMessages extends JOB_Controller
FROM public.tbl_prestudent p
JOIN public.tbl_prestudentstatus ps USING (prestudent_id)
JOIN public.tbl_studiengang s USING (studiengang_kz)
WHERE ps.status_kurzbz = \'Wartender\'
WHERE get_rolle_prestudent(ps.prestudent_id, NULL) = \'Wartender\'
AND ps.status_kurzbz = \'Wartender\'
AND ps.studiensemester_kurzbz = ?
AND ps.datum <= NOW() - \''.$days.' days\'::interval
AND s.typ = ?
@@ -431,8 +431,8 @@ class ReihungstestJob extends JOB_Controller
$mailcontent_data_arr,
$applicant->email,
'Ihre Anmeldung zum Reihungstest - Reminder / Your registration for the placement test - Reminder',
DEFAULT_SANCHO_HEADER_IMG,
DEFAULT_SANCHO_FOOTER_IMG,
'',
'',
$from,
'',
$bcc);
@@ -821,7 +821,7 @@ class ReihungstestJob extends JOB_Controller
JOIN lehre.tbl_studienordnung USING (studienordnung_id)
JOIN PUBLIC.tbl_studiengang ON (tbl_studienordnung.studiengang_kz = tbl_studiengang.studiengang_kz)
WHERE get_rolle_prestudent (tbl_prestudent.prestudent_id, ?) IN ('Aufgenommener','Bewerber','Wartender','Abgewiesener')
AND studiensemester_kurzbz = ?
AND studiensemester_kurzbz = ?
AND tbl_studiengang.typ IN ('b', 'm')
)
SELECT * FROM prst
@@ -861,7 +861,7 @@ class ReihungstestJob extends JOB_Controller
{
// Alle niedrigeren Prios laden
$qryNiedrPrios = "
SELECT DISTINCT
SELECT DISTINCT ON(prestudent_id)
get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') AS laststatus,
tbl_studienplan.orgform_kurzbz,
tbl_person.nachname,
@@ -876,11 +876,11 @@ class ReihungstestJob extends JOB_Controller
JOIN PUBLIC.tbl_studiengang ON (tbl_prestudent.studiengang_kz = tbl_studiengang.studiengang_kz)
WHERE tbl_prestudent.person_id = ".$row_ps->person_id."
AND tbl_prestudent.prestudent_id != ".$row_ps->prestudent_id."
AND get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') IN ('Aufgenommener','Bewerber','Wartender')
AND get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') IN ('Aufgenommener','Bewerber','Wartender', 'Student')
AND studiensemester_kurzbz = '".$row_ps->studiensemester_kurzbz."'
AND tbl_studiengang.typ IN ('b', 'm')
AND priorisierung > ".$row_ps->priorisierung."
ORDER BY studiengang_kz, laststatus
ORDER BY prestudent_id, studiengang_kz, laststatus, tbl_prestudentstatus.datum DESC
";
// Wenn der letzte Status "Aufgenommener" ist, alle niedrigeren Prios auf "Abgewiesen" setzen
@@ -894,12 +894,22 @@ class ReihungstestJob extends JOB_Controller
{
foreach ($resultNiedrPrios->retval as $rowNiedrPrios)
{
// nur Info wenn aufgenommen oder master
if ($rowNiedrPrios->laststatus == 'Aufgenommener' || $rowNiedrPrios->studiengang_typ == 'm')
// nur Info wenn aufgenommen/student oder master
if ($rowNiedrPrios->laststatus == 'Aufgenommener' || $rowNiedrPrios->laststatus == 'Student' || $rowNiedrPrios->studiengang_typ == 'm')
{
// Mail zur Info an Assistenz schicken, dass in höherer Prio aufgenommen wurde
$mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['AufnahmeHoeherePrio'][]
= $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')';
if ($rowNiedrPrios->laststatus == 'Aufgenommener')
{
// Mail zur Info an Assistenz schicken, dass in höherer Prio aufgenommen wurde
$mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['AufnahmeHoeherePrio'][]
= $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')';
}
else if ($rowNiedrPrios->laststatus == 'Student')
{
$mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['StudentHoeherePrio'][]
= $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')';
}
}
elseif ($rowNiedrPrios->laststatus == 'Bewerber' && $row_ps->prestudenstatus_datum > $rowNiedrPrios->datum)
{
@@ -966,7 +976,7 @@ class ReihungstestJob extends JOB_Controller
FROM public.tbl_konto
WHERE person_id = " . $row_ps->person_id . "
AND studiensemester_kurzbz = '" . $row_ps->studiensemester_kurzbz . "'
AND buchungstyp_kurzbz = 'StudiengebuehrAnzahlung'";
AND buchungstyp_kurzbz IN ('StudiengebuehrAnzahlung','KautionDrittStaat')";
$resultKautionExists = $db->execReadOnlyQuery($qryKautionExists);
if (hasdata($resultKautionExists))
@@ -1061,6 +1071,20 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '</tbody></table>';
$content = true;
}
if (isset($value['StudentHoeherePrio']) && !isEmptyArray($value['StudentHoeherePrio']))
{
$mailcontent .= '<p style="font-family: verdana, sans-serif;">
Folgende Studenten wurden in einem höher priorisierten Studiengang aufgenommen:</p>';
$mailcontent .= '<table style="border-collapse: collapse; border: 1px solid grey;">';
$mailcontent .= ' <tbody>';
sort($value['StudentHoeherePrio']);
foreach ($value['StudentHoeherePrio'] AS $key=>$bewerber)
{
$mailcontent .= '<tr><td style="font-family: verdana, sans-serif; border: 1px solid grey; padding: 3px">'.$bewerber.'</td></tr>';
}
$mailcontent .= '</tbody></table>';
$content = true;
}
if (isset($value['AbgewiesenHoeherePrio']) && !isEmptyArray($value['AbgewiesenHoeherePrio']))
{
$mailcontent .= '<p style="font-family: verdana, sans-serif;">
@@ -1,114 +0,0 @@
<?php
if (!defined("BASEPATH")) exit("No direct script access allowed");
use vertragsbestandteil\VertragsbestandteilFactory;
/**
* Description of VertragsbestandteilTest
*
* @author bambi
*/
class VertragsbestandteilTest extends JOB_Controller
{
public function __construct()
{
parent::__construct();
$this->load->library('vertragsbestandteil/VertragsbestandteilLib',
null, 'VertragsbestandteilLib');
$this->load->library('vertragsbestandteil/GehaltsbestandteilLib',
null, 'GehaltsbestandteilLib');
}
public function testFetch()
{
$dienstverhaeltnis_id = 1;
$stichtag = null;
foreach($this->VertragsbestandteilLib->fetchVertragsbestandteile(
$dienstverhaeltnis_id, $stichtag) as $vertragsbestandteil)
{
//print_r($vertragsbestandteil);
echo $vertragsbestandteil . "\n";
}
}
public function testUpdate()
{
$now = new DateTime();
$data = new stdClass();
$data->vertragsbestandteil_id = 32;
$data->von = '2022-12-05';
$data->wochenstunden = 45.0;
$data->vertragsbestandteiltyp_kurzbz = VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_STUNDEN;
$vb = VertragsbestandteilFactory::getVertragsbestandteil($data);
try
{
$this->VertragsbestandteilLib->storeVertragsbestandteil($vb);
echo "Update successful.\n";
}
catch( Exception $ex )
{
echo "Update failed.\n";
}
}
public function testInsert()
{
$now = new DateTime();
$data = new stdClass();
$data->dienstverhaeltnis_id = 1;
$data->von = '2022-12-01';
$data->insertamum = $now->format(DateTime::ATOM);
$data->insertvon = 'ma0080';
$data->vertragsbestandteiltyp_kurzbz = VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FUNKTION;
$data->benutzerfunktion_id = 112667;
$data->anmerkung = 'test funkton';
$data->kuendigungsrelevant = false;
$vb = VertragsbestandteilFactory::getVertragsbestandteil($data);
try
{
$this->VertragsbestandteilLib->storeVertragsbestandteil($vb);
echo "Insert successful.\n";
}
catch( Exception $ex )
{
echo "Insert failed.\n";
}
}
public function testGehaltsbestandteilInsert()
{
$data = new stdClass();
$data->gehaltsbestandteil_id = 2;
/*
$data->dienstverhaeltnis_id = 39;
$data->vertragsbestandteil_id = 123;
$data->gehaltstyp_kurzbz = 'zulage';
$data->von = '2023-04-01';
$data->bis = '2023-08-31';
$data->anmerkung = 'test anmerkung';
$data->grundbetrag = 100;
$data->betrag_valorisiert = 100;
$data->valorisierung = true;
*/
$data->auszahlungen = 12;
$gb = new \vertragsbestandteil\Gehaltsbestandteil();
$gb->hydrateByStdClass($data);
print_r($gb->toStdClass());
$this->GehaltsbestandteilLib->storeGehaltsbestandteil($gb);
}
}
@@ -6,58 +6,59 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
*/
class Pruefungsprotokoll extends Auth_Controller
{
private $_uid; // uid of the logged user
private $_uid; // uid of the logged user
/**
* Constructor
*/
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'lehre/pruefungsbeurteilung:r',
'Protokoll' => 'lehre/pruefungsbeurteilung:r',
'saveProtokoll' => 'lehre/pruefungsbeurteilung:rw',
)
);
/**
* Constructor
*/
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'lehre/pruefungsbeurteilung:r',
'Protokoll' => 'lehre/pruefungsbeurteilung:r',
'showProtokoll' => 'lehre/pruefungsbeurteilung:r',
'saveProtokoll' => 'lehre/pruefungsbeurteilung:rw',
)
);
// Load models
$this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel');
$this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel');
// Load models
$this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel');
$this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel');
$this->load->library('PermissionLib');
$this->load->library('AuthLib');
$this->load->library('PermissionLib');
$this->load->library('AuthLib');
// Load language phrases
$this->loadPhrases(
array(
'ui',
'global',
'person',
'abschlusspruefung',
// Load language phrases
$this->loadPhrases(
array(
'ui',
'global',
'person',
'abschlusspruefung',
'password',
'lehre'
)
);
)
);
$this->_setAuthUID(); // sets property uid
$this->_setAuthUID(); // sets property uid
$this->setControllerId(); // sets the controller id
}
$this->setControllerId(); // sets the controller id
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function index()
{
$this->load->library('WidgetLib');
// Protokolle anzeigen seit heute / letzte Woche / alle
$period = $this->input->post('period');
$period = (!is_null($period)) ? $period : 'today';
$data = array('period' => $period);
$this->load->view('lehre/pruefungsprotokollUebersicht.php', $data);
}
@@ -66,47 +67,15 @@ class Pruefungsprotokoll extends Auth_Controller
*/
public function Protokoll()
{
$abschlusspruefung_id = $this->input->get('abschlusspruefung_id');
$this->load->view('lehre/pruefungsprotokoll.php', $this->_getPruefungsprotokollData());
}
if (!is_numeric($abschlusspruefung_id))
show_error('invalid abschlusspruefung');
$abschlusspruefung_saved = false;
$abschlusspruefung = $this->_getAbschlusspruefungBerechtigt($abschlusspruefung_id);
if (isError($abschlusspruefung))
show_error(getError($abschlusspruefung));
else
{
$abschlusspruefung = getData($abschlusspruefung);
$abschlusspruefung_saved = isset($abschlusspruefung->protokoll) && isset($abschlusspruefung->abschlussbeurteilung_kurzbz);
}
$this->AbschlussbeurteilungModel->addOrder("sort", "ASC");
$this->AbschlussbeurteilungModel->addOrder("(CASE WHEN abschlussbeurteilung_kurzbz = 'ausgezeichnet' THEN 1
WHEN abschlussbeurteilung_kurzbz = 'gut' THEN 2
WHEN abschlussbeurteilung_kurzbz = 'bestanden' THEN 3
WHEN abschlussbeurteilung_kurzbz = 'angerechnet' THEN 4
ELSE 5
END
)");
$abschlussbeurteilung = $this->AbschlussbeurteilungModel->load();
if (isError($abschlussbeurteilung))
show_error(getError($abschlussbeurteilung));
else
$abschlussbeurteilung = getData($abschlussbeurteilung);
$language = getUserLanguage();
$data = array(
'abschlusspruefung' => $abschlusspruefung,
'abschlussbeurteilung' => $abschlussbeurteilung,
'abschlusspruefung_saved' => $abschlusspruefung_saved,
'language' => $language
);
$this->load->view('lehre/pruefungsprotokoll.php', $data);
/**
* Show Pruefungsprotokoll.
*/
public function showProtokoll()
{
$this->load->view('lehre/pruefungsprotokoll.php', array_merge($this->_getPruefungsprotokollData(), array('readonly' => true)));
}
/**
@@ -168,18 +137,66 @@ class Pruefungsprotokoll extends Auth_Controller
$this->outputJsonError($this->p->t('ui', 'ungueltigeParameter'));
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
// -----------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
if (!$this->_uid) show_error('User authentification failed');
}
/**
*
* @param
* @return object success or error
*/
private function _getPruefungsprotokollData()
{
$abschlusspruefung_id = $this->input->get('abschlusspruefung_id');
if (!is_numeric($abschlusspruefung_id))
show_error('invalid abschlusspruefung');
$abschlusspruefung_saved = false;
$abschlusspruefung = $this->_getAbschlusspruefungBerechtigt($abschlusspruefung_id);
if (isError($abschlusspruefung))
show_error(getError($abschlusspruefung));
else
{
$abschlusspruefung = getData($abschlusspruefung);
$abschlusspruefung_saved = isset($abschlusspruefung->protokoll) && isset($abschlusspruefung->abschlussbeurteilung_kurzbz);
}
$this->AbschlussbeurteilungModel->addOrder("sort", "ASC");
$this->AbschlussbeurteilungModel->addOrder("(CASE WHEN abschlussbeurteilung_kurzbz = 'ausgezeichnet' THEN 1
WHEN abschlussbeurteilung_kurzbz = 'gut' THEN 2
WHEN abschlussbeurteilung_kurzbz = 'bestanden' THEN 3
WHEN abschlussbeurteilung_kurzbz = 'angerechnet' THEN 4
ELSE 5
END
)");
$abschlussbeurteilung = $this->AbschlussbeurteilungModel->load();
if (isError($abschlussbeurteilung))
show_error(getError($abschlussbeurteilung));
else
$abschlussbeurteilung = getData($abschlussbeurteilung);
$language = getUserLanguage();
return array(
'abschlusspruefung' => $abschlusspruefung,
'abschlussbeurteilung' => $abschlussbeurteilung,
'abschlusspruefung_saved' => $abschlusspruefung_saved,
'language' => $language
);
}
/**
* Retrieves an Abschlussprüfung, with permission check
@@ -187,7 +204,7 @@ class Pruefungsprotokoll extends Auth_Controller
* @param $abschlusspruefung_id
* @return object success or error
*/
private function _getAbschlusspruefungBerechtigt($abschlusspruefung_id)
private function _getAbschlusspruefungBerechtigt($abschlusspruefung_id)
{
$result = error('Error when getting Abschlusspruefung');
@@ -21,6 +21,7 @@ class Studierendenantrag extends FHC_Controller
// Load Models
$this->load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
$this->load->model('person/Person_model', 'PersonModel');
// Load language phrases
$this->loadPhrases([
@@ -102,6 +103,7 @@ class Studierendenantrag extends FHC_Controller
public function abmeldungstgl($prestudent_id, $studierendenantrag_id = null)
{
$this->load->view('lehre/Antrag/Create', [
'prestudent_id' => $prestudent_id,
'studierendenantrag_id' => $studierendenantrag_id,
@@ -185,4 +187,4 @@ class Studierendenantrag extends FHC_Controller
return $strRequiredPermissions;
}
}
}
@@ -0,0 +1,45 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class LvTemplateUebersicht extends Auth_Controller
{
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'lehre/lehrveranstaltung:rw',
)
);
// Load libraries
$this->load->library('AuthLib');
// Load language phrases
$this->loadPhrases(
array(
'global',
'lehre'
)
);
$this->_setAuthUID();
}
public function index()
{
$this->load->view('lehre/lvplanung/lvTemplateUebersicht.php');
}
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
}
@@ -29,6 +29,7 @@ class Gruppenmanagement extends Auth_Controller
$this->load->model('person/benutzer_model', 'BenutzerModel');
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('person/benutzergruppe_model', 'BenutzergruppeModel');
$this->load->model('person/gruppe_manager_model', 'GruppemanagerModel');
$this->load->model('system/Log_model', 'LogModel');
$this->load->library('WidgetLib');
@@ -117,6 +118,27 @@ class Gruppenmanagement extends Auth_Controller
$result = error('Uid missing');
else
{
$this->GruppemanagerModel->addSelect('1');
$isManagerRes = $this->GruppemanagerModel->loadWhere(
array(
'uid' => $this->_uid,
'gruppe_kurzbz' => $gruppe_kurzbz
)
);
if (isError($isManagerRes))
{
$this->outputJsonError(getError($isManagerRes));
return;
}
if (!hasData($isManagerRes))
{
$this->outputJsonError($this->p->t('gruppenmanagement', 'nichtZumEditierenDerGruppeBerechtigt'));
return;
}
$this->BenutzergruppeModel->addSelect('1');
$benutzerExistsRes = $this->BenutzergruppeModel->loadWhere(
array(
'uid' => $uid,
@@ -170,6 +192,26 @@ class Gruppenmanagement extends Auth_Controller
$result = error('Uid missing');
else
{
$this->GruppemanagerModel->addSelect('1');
$isManagerRes = $this->GruppemanagerModel->loadWhere(
array(
'uid' => $this->_uid,
'gruppe_kurzbz' => $gruppe_kurzbz
)
);
if (isError($isManagerRes))
{
$this->outputJsonError(getError($isManagerRes));
return;
}
if (!hasData($isManagerRes))
{
$this->outputJsonError($this->p->t('gruppenmanagement', 'nichtZumEditierenDerGruppeBerechtigt'));
return;
}
$result = $this->BenutzergruppeModel->delete(
array(
'uid' => $uid,
@@ -1,44 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Test Search Vue Component
*/
class TestSearch extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'system/developer:r'
)
);
// Loads WidgetLib
$this->load->library('WidgetLib');
// Loads phrases system
$this->loadPhrases(
array(
'global',
'ui',
'filter'
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Everything has a beginning
*/
public function index()
{
$this->load->view('system/logs/testSearch.php');
}
}
@@ -337,10 +337,13 @@ class InfoCenter extends Auth_Controller
$persondata = $this->_loadPersonData($person_id);
$checkPerson = $this->PersonModel->checkDuplicate($person_id);
if (isError($checkPerson)) show_error(getError($checkPerson));
$duplicate = array('duplicated' => getData($checkPerson));
$checkUnruly = $this->PersonModel->checkUnruly($persondata['stammdaten']->vorname, $persondata['stammdaten']->nachname, $persondata['stammdaten']->gebdatum);
if (isError($checkUnruly)) show_error(getError($checkUnruly));
$duplicate = array('duplicate' => getData($checkPerson));
$unruly = array('unruly' => getData($checkUnruly));
$prestudentdata = $this->_loadPrestudentData($person_id);
@@ -351,7 +354,8 @@ class InfoCenter extends Auth_Controller
$persondata,
$prestudentdata,
$dokumentdata,
$duplicate
$duplicate,
$unruly
);
$data[self::FHC_CONTROLLER_ID] = $this->getControllerId();
@@ -1285,67 +1289,28 @@ class InfoCenter extends Auth_Controller
$this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
$kontakte = $this->input->post('kontakt');
foreach ($kontakte as $kontakt)
{
$kontaktExists = $this->KontaktModel->loadWhere(array(
'kontakt_id' => $kontakt['id'],
'person_id' => $person_id,
));
if($kontakte) {
if (hasData($kontaktExists))
{
$kontaktExists = getData($kontaktExists)[0];
foreach ($kontakte as $kontakt) {
$kontaktExists = $this->KontaktModel->loadWhere(array(
'kontakt_id' => $kontakt['id'],
'person_id' => $person_id,
));
if ($kontaktExists->kontakt === $kontakt['value'])
continue;
if (hasData($kontaktExists)) {
$kontaktExists = getData($kontaktExists)[0];
$update = $this->KontaktModel->update(
array
(
'kontakt_id' => $kontakt['id']
),
array
(
'kontakt' => isEmptyString($kontakt['value']) ? null : $kontakt['value'],
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => $this->_uid
)
);
if ($kontaktExists->kontakt === $kontakt['value'])
continue;
if (isError($update))
$this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
}
}
$adressen = $this->input->post('adresse');
foreach ($adressen as $adresse)
{
$adresseExists = $this->AdresseModel->loadWhere(array(
'adresse_id' => $adresse['id'],
'person_id' => $person_id,
));
if (hasData($adresseExists))
{
$adresse = $adresse['value'];
$adresseExists = getData($adresseExists)[0];
if ($adresseExists->strasse !== $adresse['strasse'] ||
$adresseExists->plz !== $adresse['plz'] ||
$adresseExists->ort !== $adresse['ort'] ||
$adresseExists->nation !== $adresse['nation'])
{
$update = $this->AdresseModel->update(
$update = $this->KontaktModel->update(
array
(
'adresse_id' => $adresseExists->adresse_id
'kontakt_id' => $kontakt['id']
),
array
(
'strasse' => isEmptyString($adresse['strasse']) ? null : $adresse['strasse'],
'plz' => isEmptyString($adresse['plz']) ? null : $adresse['plz'],
'ort' => isEmptyString($adresse['ort']) ? null : $adresse['ort'],
'nation' => isEmptyString($adresse['nation']) ? null : $adresse['nation'],
'kontakt' => isEmptyString($kontakt['value']) ? null : $kontakt['value'],
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => $this->_uid
)
@@ -1354,7 +1319,48 @@ class InfoCenter extends Auth_Controller
if (isError($update))
$this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
}
}
}
$adressen = $this->input->post('adresse');
if($adressen) {
foreach ($adressen as $adresse) {
$adresseExists = $this->AdresseModel->loadWhere(array(
'adresse_id' => $adresse['id'],
'person_id' => $person_id,
));
if (hasData($adresseExists)) {
$adresse = $adresse['value'];
$adresseExists = getData($adresseExists)[0];
if ($adresseExists->strasse !== $adresse['strasse'] ||
$adresseExists->plz !== $adresse['plz'] ||
$adresseExists->ort !== $adresse['ort'] ||
$adresseExists->nation !== $adresse['nation']) {
$update = $this->AdresseModel->update(
array
(
'adresse_id' => $adresseExists->adresse_id
),
array
(
'strasse' => isEmptyString($adresse['strasse']) ? null : $adresse['strasse'],
'plz' => isEmptyString($adresse['plz']) ? null : $adresse['plz'],
'ort' => isEmptyString($adresse['ort']) ? null : $adresse['ort'],
'nation' => isEmptyString($adresse['nation']) ? null : $adresse['nation'],
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => $this->_uid
)
);
if (isError($update))
$this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
}
}
}
}
@@ -2383,4 +2389,4 @@ class InfoCenter extends Auth_Controller
$this->outputJsonSuccess("Success");
}
}
}
+14
View File
@@ -46,6 +46,20 @@ class CI3_Events
* NOTE(chris): Autoload Events config
*/
require_once(APPPATH.'config/Events.php');
$active_addons_array = explode(";", ACTIVE_ADDONS);
foreach (scandir(APPPATH.'config/extensions') as $dir)
if ($dir[0] != '.' && file_exists(APPPATH.'config/extensions/'.$dir.'/Events.php'))
require_once APPPATH.'config/extensions/'.$dir.'/Events.php';
foreach (scandir(FHCPATH.'addons') as $dir)
if ($dir[0] != '.' && file_exists(FHCPATH.'addons/'.$dir.'/Events.php'))
{
// only includes the Events of the addon if the addon is one of the active addons in the cis config
if(in_array($dir,$active_addons_array))
{
require_once FHCPATH . 'addons/' . $dir . '/Events.php';
}
}
+72 -17
View File
@@ -60,6 +60,9 @@ class DB_Model extends CI_Model
protected $pk; // Name of the PrimaryKey for DB-Update, Load, ...
protected $hasSequence; // False if this table has a composite primary key that is not using a sequence
// True if this table has a primary key that uses a sequence
//protected $paginationOptions; // $page and $page_size together in an associative array
protected $page;
protected $page_size;
private $executedQueryMetaData;
private $executedQueryListFields;
@@ -531,7 +534,7 @@ class DB_Model extends CI_Model
if (!is_numeric($start) || (is_numeric($start) && $start <= 0))
return error('The start parameter is not valid', EXIT_MODEL);
if (is_numeric($end) && $end > $start)
if (is_numeric($end))
{
$this->db->limit($start, $end);
}
@@ -988,14 +991,17 @@ class DB_Model extends CI_Model
// Find and replace all the occurrences of the provided encrypted columns
// with the postgresql decryption function
$query = str_replace(
$encryptedColumn,
sprintf(
self::CRYPT_WHERE_TEMPLATE,
$encryptedColumn,
$decryptionPassword,
$definition[self::CRYPT_CAST]
),
$query = preg_replace_callback(
'/(?<! (as|AS) )\b(\w+\.)?(' . $encryptedColumn . ')\b/',
function($matches) use (&$decryptionPassword, &$definition) {
$aliased_column = $matches[2] . $matches[3];
return sprintf(
self::CRYPT_WHERE_TEMPLATE,
$aliased_column,
$decryptionPassword,
$definition[self::CRYPT_CAST]
);
},
$query
);
}
@@ -1103,14 +1109,17 @@ class DB_Model extends CI_Model
{
// Find and replace all the occurrences of the provided encrypted columns
// with the postgresql decryption function
$where = str_replace(
$encryptedColumn,
sprintf(
self::CRYPT_WHERE_TEMPLATE,
$encryptedColumn,
$decryptionPassword,
$definition[self::CRYPT_CAST]
),
$where = preg_replace_callback(
'/(?<! (as|AS) )\b(\w+\.)?(' . $encryptedColumn . ')\b/',
function($matches) use (&$decryptionPassword, &$definition) {
$aliased_column = $matches[2] . $matches[3];
return sprintf(
self::CRYPT_WHERE_TEMPLATE,
$aliased_column,
$decryptionPassword,
$definition[self::CRYPT_CAST]
);
},
$where
);
}
@@ -1359,5 +1368,51 @@ class DB_Model extends CI_Model
return $udfs;
}
/**
* addPagination
* adds a limit and an optional offset depending on the arguments passed to the function
* @param int $page page to be queried
* @param int $page_size page_size used to calculate the offset of the pagination
* @param int | null $num_rows used to calculate the total amout of pages that are available with the $page and $page_size arguments
*
* @return void
*/
function addPagination( $page, $page_size, $num_rows=null)
{
if (isset($page) && is_numeric($page) && isset($page_size) && is_numeric($page_size) && $page > 0 && $page_size > 0) {
if (isset($num_rows) && is_numeric($num_rows) && $num_rows > 0) {
$floatMaxPageCount = $num_rows / $page_size;
$maxPageCount = ceil($floatMaxPageCount);
if($page > $maxPageCount){
$page = $maxPageCount;
}
}
$offset = (($page-1) * $page_size);
$this->addLimit($page_size, $offset);
} else {
$this->addLimit($page_size);
}
}
/**
* getQueryNumRows
* returns the number of rows of the current build query of the codeigniter query builder instance
* @param bool $reset resets the select of the query
*
* @return Result_object $num_rows
*/
function getNumRows($reset=false)
{
// returns the number of rows when executing the current query without reseting the select statement of the query
$num_rows = $this->db->count_all_results($this->dbTable,$reset);
if($num_rows){
return success($num_rows);
}else{
return error($this->db->error(), EXIT_DATABASE);
}
}
}
+15 -2
View File
@@ -146,6 +146,19 @@ class FHCAPI_Controller extends Auth_Controller
$this->returnObj['meta'][$key] = $value;
}
/**
* @param string $key
* @return mixed
*/
public function getMeta($key)
{
if (!isset($this->returnObj['meta']))
return null;
if (!isset($this->returnObj['meta'][$key]))
return null;
return $this->returnObj['meta'][$key];
}
/**
* @param string $status
* @return void
@@ -184,7 +197,7 @@ class FHCAPI_Controller extends Auth_Controller
}
/**
* @param array $error
* @param string|array|object $error
* @param string $type (optional)
* @param integer $status (optional)
* @return void
@@ -200,7 +213,7 @@ class FHCAPI_Controller extends Auth_Controller
/**
* @param stdclass $result
* @param string $errortype
* @return void
* @return mixed
*/
protected function getDataOrTerminateWithError($result, $errortype = self::ERROR_TYPE_GENERAL)
{
+22 -93
View File
@@ -5,21 +5,18 @@
*/
abstract class IssueResolver_Controller extends JOB_Controller
{
const CI_PATH = 'application';
const CI_LIBRARY_FOLDER = 'libraries';
const EXTENSIONS_FOLDER = 'extensions';
const ISSUE_RESOLVERS_FOLDER = 'issues/resolvers';
const CHECK_ISSUE_RESOLVED_METHOD_NAME = 'checkIfIssueIsResolved';
// mappings in form fehlercode -> resolverlibrary name, fehler which have explicit resolver class defined
protected $_codeLibMappings = [];
protected $_codeLibMappings;
// mappings in form fehlercode -> producer library name, fehler which are resolved the same way they are produced
protected $_codeProducerLibMappings = [];
public function __construct()
{
parent::__construct();
// pass extension name if calling from extension
$this->load->model('system/Issue_model', 'IssueModel');
$this->load->library('IssuesLib');
}
/**
@@ -27,97 +24,29 @@ abstract class IssueResolver_Controller extends JOB_Controller
*/
public function run()
{
$this->load->library(
'issues/PlausicheckResolverLib',
[
'extensionName' => $this->_extensionName ?? null,
'codeLibMappings' => $this->_codeLibMappings,
'codeProducerLibMappings' => $this->_codeProducerLibMappings
]
);
$this->logInfo("Issue resolve job started");
// load open issues with given errorcodes
$openIssuesRes = $this->IssueModel->getOpenIssues(array_keys($this->_codeLibMappings));
$openIssuesRes = $this->IssueModel->getOpenIssues(
array_merge(array_keys($this->_codeLibMappings), array_keys($this->_codeProducerLibMappings))
);
// log error if occured
if (isError($openIssuesRes))
{
$this->logError(getError($openIssuesRes));
}
else
{
// log info if no data found
if (!hasData($openIssuesRes))
{
$this->logInfo("No open issues found");
}
else
{
$openIssues = getData($openIssuesRes);
$openIssues = hasData($openIssuesRes) ? getData($openIssuesRes) : [];
foreach ($openIssues as $issue)
{
// ignore if Fehlercode is not in libmappings (shouldn't be checked)
if (!isset($this->_codeLibMappings[$issue->fehlercode])) continue;
$result = $this->plausicheckresolverlib->resolvePlausicheckIssues($openIssues);
$libName = $this->_codeLibMappings[$issue->fehlercode];
// add person id and oe kurzbz automatically as params, merge it with additional params
// decode bewerbung_parameter into assoc array
$params = array_merge(
array('issue_id' => $issue->issue_id, 'issue_person_id' => $issue->person_id, 'issue_oe_kurzbz' => $issue->oe_kurzbz),
isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array()
);
// if called from extension (extension name set), path includes extension names
$libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : '';
// path for loading issue library
$issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/';
// file path of library for check if file exists
$issuesLibFilePath = DOC_ROOT . self::CI_PATH
. '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php';
// check if library file exists
if (!file_exists($issuesLibFilePath))
{
// log error and continue with next issue if not
$this->logError("Issue library file " . $issuesLibFilePath . " does not exist");
continue;
}
// load library connected to fehlercode
$this->load->library($issuesLibPath . $libName);
$lowercaseLibName = mb_strtolower($libName);
// check if method is defined in library class
if (!is_callable(array($this->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME)))
{
// log error and continue with next issue if not
$this->logError("Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName");
continue;
}
// call the function for checking for issue resolution
$issueResolvedRes = $this->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params);
if (isError($issueResolvedRes))
{
$this->logError(getError($issueResolvedRes));
}
else
{
$issueResolvedData = getData($issueResolvedRes);
if ($issueResolvedData === true)
{
// set issue to resolved if needed
$behobenRes = $this->issueslib->setBehoben($issue->issue_id, null);
if (isError($behobenRes))
$this->logError(getError($behobenRes));
else
$this->logInfo("Issue " . $issue->issue_id . " successfully resolved");
}
}
}
}
}
// log if error, or log info if inserted new issue
foreach ($result->errors as $error) $this->logError($error);
foreach ($result->infos as $info) $this->logInfo($info);
$this->logInfo("Issue resolve job ended");
}
+1
View File
@@ -309,6 +309,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
}
//update(1) loading all dms-entries with this notiz_id
$dms_id_arr = [];
$this->load->model('person/Notizdokument_model', 'NotizdokumentModel');
$this->NotizdokumentModel->addJoin('campus.tbl_dms_version', 'dms_id');
@@ -5,61 +5,23 @@
*/
abstract class PlausiIssueProducer_Controller extends JOB_Controller
{
protected $_fehlerLibMappings;
protected $_fehlerLibMappings = [];
protected $_app;
public function __construct($app = null)
{
parent::__construct();
// pass extension name if calling from extension
$extensionName = isset($this->_extensionName) ? $this->_extensionName : null;
// load libraries
$this->load->library('issues/PlausicheckProducerLib', array('extensionName' => $extensionName, 'app' => $this->_app));
$this->load->library('IssuesLib');
}
protected function producePlausicheckIssues($params)
{
$this->load->library(
'issues/PlausicheckProducerLib',
['extensionName' => $this->_extensionName ?? null, 'app' => $this->_app, 'fehlerLibMappings' => $this->_fehlerLibMappings]
);
$this->logInfo("Plausicheck issue producer job started");
// get the data returned by Plausicheck
foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName)
{
// execute the check
$this->logInfo("Checking " . $fehler_kurzbz . "...");
$plausicheckRes = $this->plausicheckproducerlib->producePlausicheckIssue(
$libName,
$fehler_kurzbz,
$params
);
$result = $this->plausicheckproducerlib->producePlausicheckIssues($params);
if (isError($plausicheckRes)) $this->logError(getError($plausicheckRes));
if (hasData($plausicheckRes))
{
$plausicheckData = getData($plausicheckRes);
foreach ($plausicheckData as $plausiData)
{
// get the data needed for issue production
$person_id = isset($plausiData['person_id']) ? $plausiData['person_id'] : null;
$oe_kurzbz = isset($plausiData['oe_kurzbz']) ? $plausiData['oe_kurzbz'] : null;
$fehlertext_params = isset($plausiData['fehlertext_params']) ? $plausiData['fehlertext_params'] : null;
$resolution_params = isset($plausiData['resolution_params']) ? $plausiData['resolution_params'] : null;
// write the issue
$addIssueRes = $this->issueslib->addFhcIssue($fehler_kurzbz, $person_id, $oe_kurzbz, $fehlertext_params, $resolution_params);
// log if error, or log info if inserted new issue
if (isError($addIssueRes))
$this->logError(getError($addIssueRes));
elseif (hasData($addIssueRes) && is_integer(getData($addIssueRes)))
$this->logInfo("Plausicheck issue " . $fehler_kurzbz . " successfully produced, person_id: " . $person_id);
}
}
}
// log if error, or log info if inserted new issue
foreach ($result->errors as $error) $this->logError($error);
foreach ($result->infos as $info) $this->logInfo($info);
$this->logInfo("Plausicheck issue producer job stopped");
}
+212
View File
@@ -0,0 +1,212 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Tag_Controller extends FHCAPI_Controller
{
private $_uid;
const BERECHTIGUNG_KURZBZ = 'admin:rw';
public function __construct($permissions)
{
$default_permissions = [
'getTag' => self::BERECHTIGUNG_KURZBZ,
'getTags' => self::BERECHTIGUNG_KURZBZ,
'addTag' => self::BERECHTIGUNG_KURZBZ,
'updateTag' => self::BERECHTIGUNG_KURZBZ,
'doneTag' => self::BERECHTIGUNG_KURZBZ,
'deleteTag' => self::BERECHTIGUNG_KURZBZ,
];
$merged_permissions = array_merge($default_permissions, $permissions);
parent::__construct($merged_permissions);
$this->_setAuthUID();
$this->load->model('person/Notiz_model', 'NotizModel');
$this->load->model('system/Notiztyp_model', 'NotiztypModel');
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
}
public function getTag()
{
$language = $this->_getLanguageIndex();
$id = $this->input->get('id');
$this->NotizModel->addSelect(
"tbl_notiz.titel,
tbl_notiz.text,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $language. " as bezeichnung,
tbl_notiz.notiz_id,
tbl_notiz_typ.style,
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
"
);
$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.verfasser_uid = bearbeiterbenutzer.uid', 'LEFT');
$this->NotizModel->addJoin('public.tbl_person bearbeiterperson', 'bearbeiterbenutzer.person_id = bearbeiterperson.person_id', 'LEFT');
$notiz = $this->NotizModel->loadWhere(array('notiz_id' => $id));
$this->terminateWithSuccess(hasData($notiz) ? getData($notiz)[0] : array());
}
public function getTags()
{
$this->NotiztypModel->addSelect(
'typ_kurzbz as tag_typ_kurzbz,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung,
style,
beschreibung,
tag
'
);
$this->NotiztypModel->addOrder('prioritaet');
$notiztypen = $this->NotiztypModel->loadWhere(array('aktiv' => true));
$this->terminateWithSuccess(hasData($notiztypen) ? getData($notiztypen) : array());
}
public function addTag($withZuordnung = true)
{
$postData = $this->getPostJson();
$checkTyp = $this->NotiztypModel->loadWhere(array('typ_kurzbz' => $postData->tag_typ_kurzbz));
if (!hasData($checkTyp))
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
if ($withZuordnung)
{
$return = array();
$checkZuordnungType = $this->NotizzuordnungModel->isValidType($postData->zuordnung_typ);
if (!isSuccess($checkZuordnungType))
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$values = array_unique($postData->values);
foreach ($values as $value)
{
$insertResult = $this->addNotiz($postData);
if (isError($insertResult))
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$insertZuordnung = $this->NotizzuordnungModel->insert(array(
'notiz_id' => $insertResult->retval,
$postData->zuordnung_typ => $value
));
if (isError($insertZuordnung))
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$return[] = [$postData->zuordnung_typ => $value, 'id' => $insertResult->retval];
}
$this->terminateWithSuccess($return);
}
else
{
$insertResult = $this->addNotiz($postData);
if (isError($insertResult))
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
return $insertResult->retval;
}
}
private function addNotiz($postData)
{
return $this->NotizModel->insert(array(
'titel' => 'TAG', //TODO klären
'text' => $postData->notiz,
'verfasser_uid' => $this->_uid,
'erledigt' => false,
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => $this->_uid,
'typ' => $postData->tag_typ_kurzbz
));
}
public function updateTag()
{
$postData = $this->getPostJson();
$updateData = $this->NotizModel->update(array('notiz_id' => $postData->id),
array('text' => $postData->notiz,
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => $this->_uid,
'bearbeiter_uid' => $this->_uid,
)
);
$this->terminateWithSuccess($updateData);
}
public function doneTag()
{
$postData = $this->getPostJson();
$updateData = $this->NotizModel->update(array('notiz_id' => $postData->id),
array('erledigt' => !$postData->done,
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => $this->_uid,
'bearbeiter_uid' => $this->_uid,
)
);
$this->terminateWithSuccess($updateData);
}
public function deleteTag($withZuordnung = true)
{
$postData = $this->getPostJson();
$deleteNotiz = "";
if ($withZuordnung)
{
$deleteZuordnung = $this->NotizzuordnungModel->delete(array(
'notiz_id' => $postData->id
));
if (isSuccess($deleteZuordnung))
{
$deleteNotiz = $this->NotizModel->delete(array(
'notiz_id' => $postData->id
));
}
}
else
{
$deleteNotiz = $this->NotizModel->delete(array(
'notiz_id' => $postData->id
));
}
$this->terminateWithSuccess($deleteNotiz);
}
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid)
show_error('User authentification failed');
}
private function _getLanguageIndex()
{
$this->load->model('system/Sprache_model', 'SpracheModel');
$this->SpracheModel->addSelect('index');
$result = $this->SpracheModel->loadWhere(array('sprache' => getUserLanguage()));
return hasData($result) ? getData($result)[0]->index : 1;
}
}
+17 -7
View File
@@ -87,18 +87,28 @@ function generateCSSsInclude($CSSs)
*/
function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod)
{
$ci =& get_instance();
$ci->load->model('system/Sprache_model','SpracheModel');
$server_language = getData($ci->SpracheModel->loadWhere(['content' => true]));
$server_language = array_map(function($language){
return ['sprache'=>$language->sprache, 'LC_Time'=>$language->locale, 'bezeichnung'=>$language->bezeichnung[$language->index-1]];
}, $server_language);
$user_language = getUserLanguage();
$FHC_JS_DATA_STORAGE_OBJECT = array(
'app_root' => APP_ROOT,
'ci_router' => $indexPage,
'called_path' => $calledPath,
'called_method' => $calledMethod,
'server_languages' => $server_language,
'user_language' => $user_language,
'timezone' => date_default_timezone_get(),
);
$toPrint = "\n";
$toPrint .= '<script type="text/javascript">';
$toPrint .= '
var FHC_JS_DATA_STORAGE_OBJECT = {
app_root: "'.APP_ROOT.'",
ci_router: "'.$indexPage.'",
called_path: "'.$calledPath.'",
called_method: "'.$calledMethod.'",
user_language: "'.$user_language.'"
};';
var FHC_JS_DATA_STORAGE_OBJECT = '.json_encode($FHC_JS_DATA_STORAGE_OBJECT).';';
$toPrint .= "\n";
$toPrint .= '</script>';
$toPrint .= "\n\n";
@@ -25,6 +25,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Used to create a return object, should not be used directly
* @return stdClass
*/
function _createReturnObject($code, $error, $retval)
{
@@ -39,7 +40,7 @@ function _createReturnObject($code, $error, $retval)
/**
* Success
*
* @return array
* @return stdClass
*/
function success($retval = null, $code = null)
{
@@ -49,7 +50,7 @@ function success($retval = null, $code = null)
/**
* Error
*
* @return array
* @return stdClass
*/
function error($retval = null, $code = null)
{
+81 -12
View File
@@ -23,9 +23,6 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
// Functions needed in the view FHC-Header
// ------------------------------------------------------------------------
const DEFAULT_SANCHO_HEADER_IMG = 'sancho_header_DEFAULT.jpg';
const DEFAULT_SANCHO_FOOTER_IMG = 'sancho_footer_DEFAULT.jpg';
/**
* Send single Mail with Sancho Design and Layout.
* @param string $vorlage_kurzbz Name of the template for specific mail content.
@@ -38,27 +35,88 @@ const DEFAULT_SANCHO_FOOTER_IMG = 'sancho_footer_DEFAULT.jpg';
* @param string $bcc Sets BCC of mail.
* @return void
*/
function sendSanchoMail($vorlage_kurzbz, $vorlage_data, $to, $subject, $headerImg = DEFAULT_SANCHO_HEADER_IMG, $footerImg = DEFAULT_SANCHO_FOOTER_IMG, $from = null, $cc = null, $bcc = null)
function sendSanchoMail(
$vorlage_kurzbz,
$vorlage_data,
$to,
$subject,
$headerImg = '',
$footerImg = '',
$from = null,
$cc = null,
$bcc = null
)
{
$ci =& get_instance();
$ci->load->library('email');
$ci->load->library('MailLib');
$sanchoHeader_img = 'skin/images/sancho/'. $headerImg;
$sanchoFooter_img = 'skin/images/sancho/'. $footerImg;
$sancho_mail_config = $ci->config->item('mail');
if ($from == '')
{
$from = 'sancho@'.DOMAIN;
$from = ((isset($sancho_mail_config['sancho_mail_default_sender'])
&& $sancho_mail_config['sancho_mail_default_sender'])
? $sancho_mail_config['sancho_mail_default_sender']
: 'noreply')
. '@' . DOMAIN;
}
// Embed sancho header and footer image
// reset important to ensure embedding of images when called in a loop
$ci->email->clear(true); // clear vars and attachments
$ci->email->attach($sanchoHeader_img);
$ci->email->attach($sanchoFooter_img);
$cid_header = $ci->email->attachment_cid($sanchoHeader_img); // sets unique content id for embedding
$cid_footer = $ci->email->attachment_cid($sanchoFooter_img); // sets unique content id for embedding
$cid_header = '';
$cid_footer = '';
if (isset($sancho_mail_config['sancho_mail_use_images']) && $sancho_mail_config['sancho_mail_use_images'])
{
$sanchoHeader_img = '';
$sanchoFooter_img = '';
if (isset($headerImg) && $headerImg != '')
{
// use provided header image
$sanchoHeader_img = $headerImg;
}
elseif (isset($sancho_mail_config['sancho_mail_header_img']) && $sancho_mail_config['sancho_mail_header_img'])
{
// use default header image
$sanchoHeader_img = $sancho_mail_config['sancho_mail_header_img'];
}
if (isset($footerImg) && $footerImg != '')
{
// use provided footer image
$sanchoFooter_img = $footerImg;
}
elseif (isset($sancho_mail_config['sancho_mail_footer_img']) && $sancho_mail_config['sancho_mail_footer_img'])
{
// use default footer image
$sanchoFooter_img = $sancho_mail_config['sancho_mail_footer_img'];
}
// add image file paths
if (isset($sancho_mail_config['sancho_mail_img_path']))
{
if ($sanchoHeader_img != '')
{
$sanchoHeader_img = $sancho_mail_config['sancho_mail_img_path'].$sanchoHeader_img;
}
if ($sanchoFooter_img != '')
{
$sanchoFooter_img = $sancho_mail_config['sancho_mail_img_path'].$sanchoFooter_img;
}
}
// attach header and footer
$ci->email->attach($sanchoHeader_img, 'inline');
$ci->email->attach($sanchoFooter_img, 'inline');
$cid_header = $ci->email->attachment_cid($sanchoHeader_img); // sets unique content id for embedding
$cid_footer = $ci->email->attachment_cid($sanchoFooter_img); // sets unique content id for embedding
}
// Set specific mail content into specific content template
$content = _parseMailContent($vorlage_kurzbz, $vorlage_data);
@@ -74,7 +132,18 @@ function sendSanchoMail($vorlage_kurzbz, $vorlage_data, $to, $subject, $headerIm
$body = _parseMailContent('Sancho_Mail_Template', $layout);
// Send mail
return $ci->maillib->send($from, $to, $subject, $body, $alias = '', $cc, $bcc, $altMessage = '', $bulk = true, $autogenerated = true);
return $ci->maillib->send(
$from,
$to,
$subject,
$body,
'', // alias
$cc,
$bcc,
'', // altMessage
true, // bulk
true // autogenerated
);
}
/**
+11 -17
View File
@@ -930,7 +930,7 @@ class AntragLib
public function createWiederholung($prestudent_id, $studiensemester_kurzbz, $insertvon, $repeat)
{
$result = $this->_ci->StudierendenantragModel->loadIdAndStatusWhere([
'prestudent_id' => $prestudent_id,
'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
'studiensemester_kurzbz'=> $studiensemester_kurzbz,
'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG
]);
@@ -1360,7 +1360,7 @@ class AntragLib
if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist_abmeldung'))) {
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
'prestudent_id' => $prestudent_id,
'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED
], [
Studierendenantrag_model::TYP_ABMELDUNG,
@@ -1372,7 +1372,7 @@ class AntragLib
return success(-1);
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
'prestudent_id' => $prestudent_id,
'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE
], [
Studierendenantrag_model::TYP_ABMELDUNG,
@@ -1386,7 +1386,7 @@ class AntragLib
return success(0);
}
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['prestudent_id' => $prestudent_id]);
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]);
if (isError($result))
return $result;
if (!hasData($result))
@@ -1447,7 +1447,7 @@ class AntragLib
&& $result->status_kurzbz != 'Unterbrecher') {
return success(0);
}
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['prestudent_id' => $prestudent_id]);
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]);
if (isError($result))
return $result;
if (!hasData($result))
@@ -1463,12 +1463,6 @@ class AntragLib
elseif($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus)
return success(-2);
}
if ($antrag->typ == Studierendenantrag_model::TYP_UNTERBRECHUNG)
{
// NOTE(chris): Ignore canceled ones
if ($antrag->status == Studierendenantragstatus_model::STATUS_CANCELLED)
continue;
}
if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG)
{
if($antrag->status == Studierendenantragstatus_model::STATUS_PASS)
@@ -1529,7 +1523,7 @@ class AntragLib
$datumStatus = $result->datum;
if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist'))) {
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
'prestudent_id' => $prestudent_id,
'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED
]);
@@ -1539,7 +1533,7 @@ class AntragLib
return success(-1);
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
'prestudent_id' => $prestudent_id,
'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED
]);
@@ -1549,7 +1543,7 @@ class AntragLib
return success(-1);
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
'prestudent_id' => $prestudent_id,
'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE
]);
@@ -1560,7 +1554,7 @@ class AntragLib
return success(0);
}
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['prestudent_id' => $prestudent_id]);
$result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]);
if (isError($result))
return $result;
if (!hasData($result))
@@ -1613,7 +1607,7 @@ class AntragLib
public function getDetailsForLastAntrag($prestudent_id, $typ = null)
{
$where = [
'prestudent_id' => $prestudent_id
'tbl_studierendenantrag.prestudent_id' => $prestudent_id
];
$types = null;
if ($typ) {
@@ -2199,4 +2193,4 @@ class AntragLib
$result = $this->_ci->StudierendenantraglehrveranstaltungModel->getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz);
return $result;
}
}
}
+309
View File
@@ -0,0 +1,309 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
use \DateTime as DateTime;
use \DOMDocument as DOMDocument;
use \XSLTProcessor as XSLTProcessor;
/**
* TODO(chris): NEWS: edit & delete button links and confirm
* TODO(chris): NEWS: news_infoscreen xlst
*/
class CmsLib
{
/**
* @var object
*/
protected $ci;
/**
* Constructor
*/
public function __construct()
{
$this->ci =& get_instance();
// Load Models
$this->ci->load->model('content/Content_model', 'ContentModel');
$this->ci->load->model('content/Contentgruppe_model', 'ContentgruppeModel');
$this->ci->load->model('content/Template_model', 'TemplateModel');
if (defined('LOG_CONTENT') && LOG_CONTENT)
$this->ci->load->model('system/Webservicelog_model', 'WebservicelogModel');
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @param int $content_id
* @param int $version
* @param string $sprache
* @param boolean $sichtbar
*
* @return stdClass
*/
public function getContent($content_id, $version = null, $sprache = null, $sichtbar = true)
{
if (!is_numeric($content_id))
return error('ContentID ist ungueltig');
if ($sprache === null)
$sprache = getUserLanguage();
$islocked = $this->ci->ContentgruppeModel->loadWhere(['content_id' => $content_id]);
if (isError($islocked))
return $islocked;
if (getData($islocked)) {
$uid = getAuthUID();
$isberechtigt = $this->ci->ContentgruppeModel->berechtigt($content_id, $uid);
if (isError($isberechtigt))
return $isberechtigt;
if (!getData($isberechtigt))
return error('global/keineBerechtigungFuerDieseSeite');
}
$content = $this->ci->ContentModel->getContent($content_id, $sprache, $version, $sichtbar, true);
if (isError($content))
return $content;
// Legt einen Logeintrag für die Klickstatistik an
if (defined('LOG_CONTENT') && LOG_CONTENT) {
// Nur eingeloggte User werden geloggt, das sonst auch alle Infoscreenaufrufe und dgl. mitgeloggt werden
if (isLogged()) {
$request_data = 'content_id=' . $content_id;
if ($version !== null)
$request_data .= '&version=' . $version;
if ($sichtbar !== true)
$request_data .= '&sichtbar=' . $sichtbar;
$this->ci->WebservicelogModel->insert([
'webservicetyp_kurzbz' => 'content',
'request_id' => $content_id,
'beschreibung' => 'content',
'request_data' => $request_data . '&sprache=' . $sprache,
'execute_time' => 'now()',
'execute_user' => getAuthUID()
]);
}
}
$content = getData($content);
//XSLT Vorlage laden
$template = $this->ci->TemplateModel->load($content->template_kurzbz);
if (isError($template))
return $template;
$template = current(getData($template));
$XML = new DOMDocument();
$XML->loadXML($content->content);
if($content->titel){
$betreff = $content->titel;
}else{
//DomDocument getElementsByTagName returns a DomNodeList
$betreff = $XML->getElementsByTagName('betreff');
//check if any betreff was found and if it is not empty
if($betreff->length > 0 && !empty($betreff->item(0)->nodeValue))
{
//DomNodeList item() return a DomNode, property nodeValue contains the value of the node
$betreff = $betreff->item(0)->nodeValue;
}
else
{
return error('no betreff found for the content');
}
}
$xsltemplate = new DOMDocument();
$xsltemplate->loadXML($template->xslt_xhtml_c4);
//Transformation
$processor = new XSLTProcessor();
$processor->importStylesheet($xsltemplate);
$transformed_content = $processor->transformToXML($XML);
//replaces all the dms.php with the new CIS4 Controller
$transformed_content = str_replace('dms.php', APP_ROOT . 'cms/dms.php', $transformed_content);
//replaces all the cms.php with the new CIS4 Controller
$transformed_content = preg_replace('/content\.php\?content\_id\=([0-9]+)/', APP_ROOT.'cis.php/CisVue/Cms/content/$1', $transformed_content);
return success([
"betreff"=>$betreff,
"type"=>$content->template_kurzbz,
"content"=>$transformed_content
]);
}
/**
* @param stdClass $stg_obj
*
* @return stdClass
*/
protected function getNewsExtras($stg_obj, $semester)
{
$this->ci->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$stg_ltg = $this->ci->StudiengangModel->getLeitungDetailed($stg_obj->studiengang_kz);
if (isError($stg_ltg))
return $stg_ltg;
$stg_ltg = getData($stg_ltg) ?: [];
$gf_ltg = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('gLtg', $stg_obj->oe_kurzbz);
if (isError($gf_ltg))
return $gf_ltg;
$gf_ltg = getData($gf_ltg) ?: [];
$stv_ltg = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stvLtg', $stg_obj->oe_kurzbz);
if (isError($stv_ltg))
return $stv_ltg;
$stv_ltg = getData($stv_ltg) ?: [];
$ass = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('ass', $stg_obj->oe_kurzbz);
if (isError($ass))
return $ass;
$ass = getData($ass) ?: [];
$hochschulvertr = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('hsv');
if (isError($hochschulvertr))
return $hochschulvertr;
$hochschulvertr = getData($hochschulvertr) ?: [];
$stdv = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stdv', $stg_obj->oe_kurzbz);
if (isError($stdv))
return $stdv;
$stdv = getData($stdv) ?: [];
$jahrgangsvertr = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('jgv', $stg_obj->oe_kurzbz, $semester);
if (isError($jahrgangsvertr))
return $jahrgangsvertr;
$jahrgangsvertr = getData($jahrgangsvertr) ?: [];
return success($this->ci->load->view('Cis/Cms/News/Xml/NewsExtras', [
'studiengang' => $stg_obj,
'semester' => $semester,
'stg_ltg' => $stg_ltg,
'gf_ltg' => $gf_ltg,
'stv_ltg' => $stv_ltg,
'ass' => $ass,
'hochschulvertr' => $hochschulvertr,
'stdv' => $stdv,
'jahrgangsvertr' => $jahrgangsvertr
], true));
}
/**
* @param string $studiengang_kz
* @param string $semester
*
* @return array queried studiengang_kz and semester
*/
public function getStgAndSem($studiengang_kz, $semester)
{
$this->ci->load->model('crm/Student_model', 'StudentModel');
//Zum anzeigen der Studiengang-Details neben den News
$student = $this->ci->StudentModel->loadWhere(['student_uid' => getAuthUID()]);
if (isError($student))
return $student;
if (getData($student)) {
$student = current(getData($student));
if ($studiengang_kz === null)
$studiengang_kz = $student->studiengang_kz;
if ($semester === null)
$semester = $student->semester;
}
return [$studiengang_kz, $semester];
}
/**
* @param boolean $infoscreen
* @param string | null $studiengang_kz
* @param int | null $semester
* @param boolean $mischen
* @param string $titel
* @param boolean $edit
* @param boolean $sichtbar
*
* @return void
*/
public function getNews($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true, $page = 1, $page_size = 10, $sprache)
{
$this->ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
list($studiengang_kz, $semester) = $this->getStgAndSem($studiengang_kz, $semester);
$all = $edit;
$xml = '<?xml version="1.0" encoding="UTF-8"?><content>';
$this->ci->load->model('content/News_model', 'NewsModel');
$news = $this->ci->NewsModel->getNewsWithContent($sprache, $studiengang_kz, $semester, null, $sichtbar, 0, $page, $page_size, $all, $mischen);
if (isError($news))
return $news;
$news = getData($news);
foreach ($news as $newsobj) {
if ($studiengang_kz && $edit && !$newsobj->studiengang_kz)
continue;
$date = new DateTime($newsobj->datum);
$datum = '<datum><![CDATA[' . $date->format('d.m.Y') . ']]></datum>';
$datum .= '<datumdetail><![CDATA[' . $date->format('Y-m-d H:i') . ']]></datumdetail>';
$id = $edit ? '<news_id><![CDATA[' . $newsobj->news_id . ']]></news_id>' : '';
$xml .= "<newswrapper>" . $newsobj->content . $datum . $id . "</newswrapper>";
}
/* if ($studiengang_kz != 0) {
$stg_obj = $this->ci->StudiengangModel->load($studiengang_kz);
if (isError($stg_obj))
return $stg_obj;
$stg_obj = current(getData($stg_obj) ?: []);
if ($stg_obj) {
if (!$edit && !$infoscreen) {
$extras = $this->getNewsExtras($stg_obj, $semester);
if (isError($extras))
return $extras;
$xml .= getData($extras);
}
$xml .= '<studiengang_bezeichnung><![CDATA[' . $stg_obj->bezeichnung . ']]></studiengang_bezeichnung>';
}
} */
if ($titel != '') {
$xml .= '<news_titel>' . $titel . '</news_titel>';
}
$xml .= '</content>';
//XSLT Vorlage laden
$template = $this->ci->TemplateModel->load($infoscreen ? 'news_infoscreen' : 'news');
if (isError($template))
return $template;
$template = current(getData($template));
$XML = new DOMDocument();
$XML->loadXML($xml);
$xsltemplate = new DOMDocument();
$xsltemplate->loadXML($template->xslt_xhtml_c4);
//Transformation
$processor = new XSLTProcessor();
$processor->importStylesheet($xsltemplate);
$content = $processor->transformToDoc($XML);
$content->formatOutput = true;
$content = $content->saveHTML();
$content = str_replace('dms.php', APP_ROOT . 'cms/dms.php', $content);
return success($content);
}
}
+714
View File
@@ -0,0 +1,714 @@
<?php
/* Copyright (C) 2024 fhcomplete.net
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
use stdClass as stdClass;
use DOMDocument as DOMDocument;
use XSLTProcessor as XSLTProcessor;
use SimpleXMLElement as SimpleXMLElement;
/**
* This library replaces the old document_export.class except for the convert
* function which is located in the DocumentLib library.
*
* The usage differs a little bit from the old library:
* In the old library you had to call create() then some optional function
* for adding data (addDataArray()/addDataXML()/addDataURL()/setFilename()),
* modifiing said data (sign()/setXMLTag_archivierbar()) or adding
* images (addImage()) and then call output() and close().
* Now the create, output and close functions are combined into one function and adding data and images is done via parameters.
* There are now two functions getContent() and showContent() where showContent() equals to output(false) and getContent equals to output(true)
* Instead of calling addDataArray, addDataXML or addDataURL just call
* getDataArray, getDataXML or getDataURL respectevily and use the return
* value as $xml_data parameter in the showContent and getContent calls.
* Instead of calling addImages just create an array and pass it as $images
* parameter to the showContent/getContent function.
* The old setFilename() function is now a parameter in showContent(). It is
* not needed in getContent() since that function does not do anything that
* requires a filename.
* To get/show a signed document just pass a valid uid as $sign_user
* parameter.
*
* Example:
* Old:
* $doc = new document_export($vorlage->vorlage_kurzbz, $oe_kurzbz, $version);
* $doc->setFilename($filename);
* $doc->addDataXML($data);
* $doc->addImage($imagepath, $imagename, $imagecontenttype);
* $doc->create($outputformat);
* $doc->output(true);
* $doc->close();
*
* New:
* $xml_data = $this->documentexportlib->getDataXML($data);
* $images = [[
* 'path' => $imagepath,
* 'name' => $imagename,
* 'contenttype' => $imagecontenttype
* ]];
* $this->documentexportlib->showContent(
* $filename,
* $vorlage,
* $xml_data,
* $oe_kurzbz,
* $version,
* $outputformat,
* null,
* null,
* $images
* );
*/
class DocumentExportLib
{
private $unoconv_version;
/**
* Constructor
*/
public function __construct()
{
// Gets CI instance
$this->ci =& get_instance();
// Load Phrases
$this->ci->load->library('PhrasesLib', ['document_export', null], 'documentExportPhrases');
// Which document converter has to be used
if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true)
{
// Use docsbox!!
}
else
{
exec('unoconv --version', $ret_arr);
if(isset($ret_arr[0]))
{
$hlp = explode(' ', $ret_arr[0]);
if(isset($hlp[1]))
{
$this->unoconv_version = $hlp[1];
}
else
show_error($this->ci->documentExportPhrases->t("document_export", "error_unoconv_version"));
}
else
show_error($this->ci->documentExportPhrases->t("document_export", "error_unoconv"));
}
}
/**
* Laedt die XML Daten fuer die XSL Transformation anhand eines Arrays
*
* @param array $data Array mit Daten
* @param string $root Bezeichnung des Root Nodes
*
* @return DOMDocument
*/
public function getDataArray($data, $root)
{
$xml_data = new DOMDocument();
$xml_data->loadXML($this->convertArrayToXML($data, $root));
return $xml_data;
}
/**
* XML Daten fuer die XSL Transformation
*
* @param string $xml
*
* @return DOMDocument
*/
public function getDataXML($xml)
{
$xml_data = new DOMDocument();
$xml_data->loadXML($xml);
return $xml_data;
}
/**
* URL zu XML Datei die fuer XSLTransformation verwendet werden soll
*
* @param string $xml URL to XML
* @param string $params GET parameter
*
* @return stdClass
*/
public function getDataURL($xml, $params)
{
$xml_found = false;
$aktive_addons = array_filter(array_map('trim', explode(";", ACTIVE_ADDONS)));
foreach($aktive_addons as $addon) {
$xmlfile = DOC_ROOT . 'addons/' . $addon . '/rdf/' . $xml;
if (file_exists($xmlfile)) {
$xml_found = true;
$xml_url = XML_ROOT . '../addons/' . $addon . '/rdf/' . $xml . '?' . $params;
break;
}
}
if (!$xml_found)
$xml_url = XML_ROOT . $xml . '?' . $params;
// Load the XML source
$xml_data = new DOMDocument;
if (!$xml_data->load($xml_url))
return error($this->ci->documentExportPhrases->t("document_export", "error_xml_load", [
"url" => $xml_url,
"xml" => $xml,
"params" => $params
]));
return success($xml_data);
}
/**
* Adds a XML Tag for signatur to the document
*
* @param DomDocument $xml_data
*
* @return void
*/
protected function addSignToData($xml_data)
{
$signblock = $xml_data->createElement("signed", "true");
$xml_data->documentElement->appendChild($signblock);
}
/**
* Adds a XML Tag for archive to the document
*
* @param DomDocument $xml_data
*
* @return void
*/
public function addArchiveToData($xml_data)
{
$archiv = $xml_data->createElement("archivierbar", "true");
$xml_data->documentElement->appendChild($archiv);
}
/**
* Get the contents of a Document
*
* @param stdClass $vorlage A db entry from tbl_vorlage
* @param DomDocument $xml_data
* @param string $oe_kurzbz
* @param integer|null $version (optional)
* @param string $outputformat (optional)
* @param string $sign_user (optional) Must be a valid uid
* @param string $sign_profile (optional) Signatureprofile for signing
* @param array $images (optional) Each element should have a property path, name & contenttype which are all strings
*
* @return stdClass
*/
public function getContent(
$vorlage,
$xml_data,
$oe_kurzbz,
$version = null,
$outputformat = null,
$sign_user = null,
$sign_profile = null,
$images = []
) {
$source_folder = getcwd();
$temp_folder = sys_get_temp_dir() . '/fhcunoconv-' . uniqid();
$outputformat = $this->getDefaultOutputFormat($outputformat, $vorlage->mimetype);
$result = $this->createAndSignContent(
$temp_folder,
$outputformat,
$vorlage,
$oe_kurzbz,
$version,
$xml_data,
$images,
$sign_user,
$sign_profile
);
if (isError($result)) {
$this->close($temp_folder, $source_folder);
return $result;
}
$temp_filename = getData($result);
$fsize = filesize($temp_filename);
$handle = fopen($temp_filename, 'r');
if (!$handle)
return error($this->ci->documentExportPhrases->t("document_export", "error_file_load"));
$result = fread($handle, $fsize);
fclose($handle);
$this->close($temp_folder, $source_folder);
return success($result);
}
/**
* Sets the headers and displays the Document.
* On failure the exit() function will be called
*
* @param string $filename
* @param stdClass $vorlage A db entry from tbl_vorlage
* @param DomDocument $xml_data
* @param string $oe_kurzbz
* @param integer|null $version (optional)
* @param string $outputformat (optional)
* @param string $sign_user (optional) Must be a valid uid
* @param string $sign_profile (optional) Signatureprofile for signing
* @param array $images (optional) Each element should have a property path, name & contenttype which are all strings
*
* @return void
*/
public function showContent(
$filename,
$vorlage,
$xml_data,
$oe_kurzbz,
$version = null,
$outputformat = null,
$sign_user = null,
$sign_profile = null,
$images = []
) {
$source_folder = getcwd();
$temp_folder = sys_get_temp_dir() . '/fhcunoconv-' . uniqid();
$outputformat = $this->getDefaultOutputFormat($outputformat, $vorlage->mimetype);
$result = $this->createAndSignContent(
$temp_folder,
$outputformat,
$vorlage,
$oe_kurzbz,
$version,
$xml_data,
$images,
$sign_user,
$sign_profile
);
if (isError($result)) {
$this->close($temp_folder, $source_folder);
exit(getError($result));
}
$temp_filename = getData($result);
$fsize = filesize($temp_filename);
$handle = fopen($temp_filename, 'r');
if (!$handle) {
$this->close($temp_folder, $source_folder);
exit($this->ci->documentExportPhrases->t("document_export", "error_file_load"));
}
if (headers_sent()) {
$this->close($temp_folder, $source_folder);
exit($this->ci->documentExportPhrases->t("document_export", "error_headers"));
}
switch ($outputformat) {
case 'pdf':
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="' . $filename . '.pdf"');
header('Content-Length: ' . $fsize);
break;
case 'doc':
header('Content-type: application/vnd.ms-word');
header('Content-Disposition: attachment; filename="' . $filename . '.doc"');
header('Content-Length: ' . $fsize);
break;
case 'odt':
header('Content-type: application/vnd.oasis.opendocument.text');
header('Content-Disposition: attachment; filename="' . $filename . '.odt"');
header('Content-Length: ' . $fsize);
break;
default:
$this->close($temp_folder, $source_folder);
exit($this->ci->documentExportPhrases->t("document_export", "error_outputformat_missing"));
}
while (!feof($handle)) {
echo fread($handle, 8192);
}
fclose($handle);
$this->close($temp_folder, $source_folder);
}
/**
* Helper function for getContent and showContent.
* Creates the temp folder and calls create and sign functions.
*
* @param string $temp_folder
* @param string $outputformat
* @param stdClass $vorlage
* @param string $oe_kurzbz
* @param integer $version
* @param DomDocument $xml_data
* @param array $images Each element should have a property path, name and contenttype which are all strings
* @param string $sign_user Must be a valid uid
* @param string $sign_profile Signatureprofile for signing
*
* @return stdClass
*/
protected function createAndSignContent(
$temp_folder,
$outputformat,
$vorlage,
$oe_kurzbz,
$version,
$xml_data,
$images,
$sign_user,
$sign_profile
) {
mkdir($temp_folder);
chdir($temp_folder);
$this->ci->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel');
$result = $this->ci->VorlagestudiengangModel->getCurrent($vorlage->vorlage_kurzbz, $oe_kurzbz, $version);
if (isError($result))
return $result;
if (!hasData($result))
return error($this->ci->documentExportPhrases->t("document_export", "error_template_missing"));
$vorlage_stg = current(getData($result));
foreach ($vorlage_stg as $k => $v)
$vorlage->$k = $v;
$result = $this->create($temp_folder, $outputformat, $vorlage, $xml_data, $images);
if (isError($result))
return $result;
$temp_filename = getData($result);
if ($sign_user) {
$this->addSignToData($xml_data);
$result = $this->sign($temp_folder, $temp_filename, $outputformat, $sign_user, $sign_profile);
if (isError($result))
return $result;
$temp_filename = getData($result);
}
return success($temp_filename);
}
/**
* Helper function for createAndSignContent.
* Creates the files in the temp folder.
*
* @param string $temp_folder
* @param string $outputformat
* @param stdClass $vorlage
* @param DomDocument $xml_data
* @param array $images Each element should have a property path, name and contenttype which are all strings
*
* @return stdClass
*/
protected function create($temp_folder, $outputformat, $vorlage, $xml_data, $images)
{
$content_xsl = new DOMDocument();
if (!$content_xsl->loadXML($vorlage->text))
return error($this->ci->documentExportPhrases->t("document_export", "error_xsl_load"));
$proc = new XSLTProcessor();
$proc->importStyleSheet($content_xsl);
$contentbuffer = $proc->transformToXml($xml_data);
file_put_contents($temp_folder . '/content.xml', $contentbuffer);
if ($xml_data->firstChild->tagName == 'error')
return error($xml_data->firstChild->textContent);
// styles.xml erstellen
if ($vorlage->style) {
$styles_xsl = new DOMDocument();
if (!$styles_xsl->loadXML($vorlage->style))
return error($this->ci->documentExportPhrases->t("document_export", "error_styles_load"));
$style_proc = new XSLTProcessor();
$style_proc->importStyleSheet($styles_xsl);
$stylesbuffer = $style_proc->transformToXml($xml_data);
file_put_contents($temp_folder . '/styles.xml', $stylesbuffer);
}
// Template holen
$vorlage_found = false;
$vorlage_filename = $vorlage->vorlage_kurzbz . ($vorlage->mimetype == 'application/vnd.oasis.opendocument.spreadsheet' ? '.ods' : '.odt');
$aktive_addons = array_filter(array_map('trim', explode(";", ACTIVE_ADDONS)));
foreach($aktive_addons as $addon) {
$zipfile = DOC_ROOT . 'addons/' . $addon . '/system/vorlage_zip/' . $vorlage_filename;
if (file_exists($zipfile)) {
$vorlage_found = true;
break;
}
}
if (!$vorlage_found)
$zipfile = DOC_ROOT . 'system/vorlage_zip/' . $vorlage_filename;
$tempname_zip = $temp_folder . '/out.zip';
if (!copy($zipfile, $tempname_zip))
return error($this->ci->documentExportPhrases->t("document_export", "error_file_copy"));
exec("zip $tempname_zip content.xml");
if (!is_null($styles_xsl))
exec("zip $tempname_zip styles.xml");
// bilder hinzufuegen
if (count($images) > 0)
{
// Unterordner fuer die Bilder erstellen
mkdir('Pictures');
// Manifest Datei holen
exec('unzip ' . $tempname_zip . ' META-INF/manifest.xml');
// Bild zur Manifest Datei hinzufuegen
$manifest = file_get_contents('META-INF/manifest.xml');
$manifest_xml = new DOMDocument;
if (!$manifest_xml->loadXML($manifest))
return error($this->ci->documentExportPhrases->t("document_export", "error_manifest"));
//root-node holen
$root = $manifest_xml->getElementsByTagName('manifest')->item(0);
foreach ($images as $bild) {
copy($bild['path'], 'Pictures/' . $bild['name']);
//Neues Element unterhalb des Root Nodes anlegen
$node = $manifest_xml->createElement("manifest:file-entry");
$node->setAttribute("manifest:full-path", 'Pictures/' . $bild['name']);
$node->setAttribute("manifest:media-type", $bild['contenttype']);
$root->appendChild($node);
}
$out = $manifest_xml->saveXML();
//geaenderte Manifest Datei speichern und wieder ins Zip packen
file_put_contents('META-INF/manifest.xml', $out);
exec('zip ' . $tempname_zip . ' META-INF/*');
// Bilder zum ZIP-File hinzufuegen
exec('zip ' . $tempname_zip . ' Pictures/*');
}
clearstatcache();
switch ($outputformat) {
case 'pdf':
case 'doc':
$ret = 0;
$temp_filename = $temp_folder . '/out.' . $outputformat;
if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) {
// Use docsbox
$this->ci->load->library("DocsboxLib");
$docboxlib = get_class($this->ci->docboxlib);
$ret = $docboxlib::convert($tempname_zip, $temp_filename, $outputformat);
} else {
// Use unoconv
// Unoconv Version 0.6 hat eine Bug wodurch die Berechtigungen des PDF/Doc nicht korrekt gesetzt
// werden. Deshalb wird dies hier speziell behandelt.
// Die 2. Variante hat den Vorteil dass hier eine bessere Fehlerbehandlung moeglich ist
if ($this->unoconv_version == '0.6')
$command = 'unoconv -e IsSkipEmptyPages=false -f ' . $outputformat . ' %2$s > %1$s';
else
$command = 'unoconv -e IsSkipEmptyPages=false -f ' . $outputformat . ' --output %s %s 2>&1';
$command = sprintf($command, $temp_filename, $tempname_zip);
exec($command, $out, $ret);
}
if ($ret)
return error($this->ci->documentExportPhrases->t("document_export", "error_conv_timeout"));
break;
case 'odt':
default:
$temp_filename = $tempname_zip;
}
return success($temp_filename);
}
/**
* Helper function for createAndSignContent.
* Signs the main file in the temp folder.
*
* @param string $temp_folder
* @param string $temp_filename
* @param string $outputformat
* @param string $user Must be a valid uid
* @param string $profile Signatureprofile for signing
*
* @return stdClass
*/
protected function sign($temp_folder, $temp_filename, $outputformat, $user, $profile)
{
if ($outputformat != 'pdf')
return error($this->ci->documentExportPhrases->t("document_export", "error_sign_pdf"));
// Load the File
$file_data = file_get_contents($temp_filename);
$data = new stdClass();
$data->document = base64_encode($file_data);
// Signatur Profil
if (!is_null($profile))
$data->profile = $profile;
else
$data->profile = SIGNATUR_DEFAULT_PROFILE;
// Username des Endusers der die Signatur angefordert hat
$data->user = $user;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, SIGNATUR_URL . '/' . SIGNATUR_SIGN_API);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_USERAGENT, "FH-Complete");
// SSL Zertifikatsprüfung deaktivieren
// Besser ist es das Zertifikat am Server zu installieren!
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$data_string = json_encode($data, JSON_FORCE_OBJECT);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length:' . mb_strlen($data_string),
'Authorization: Basic ' . base64_encode(SIGNATUR_USER . ":" . SIGNATUR_PASSWORD)
]);
$result = curl_exec($ch);
if (curl_errno($ch)) {
curl_close($ch);
return error($this->ci->documentExportPhrases->t("document_export", "error_sign_timeout"));
}
curl_close($ch);
$resultdata = json_decode($result);
// If it is success
if (isset($resultdata->error) && $resultdata->error == 0) {
$signed_filename = $temp_folder . '/signed.pdf';
file_put_contents($signed_filename, base64_decode($resultdata->retval));
return success($signed_filename);
}
// otherwise if it is an error
return error($resultdata->retval ?? $this->ci->documentExportPhrases->t("global", "unknown_error", ["error" => $result]));
}
/**
* Deletes all files in the $temp_folder and changes back to the source_folder
*
* @param string $temp_folder
* @param string $source_folder
*
* @return void
*/
protected function close($temp_folder, $source_folder)
{
$files = glob($temp_folder . '/*'); // get all file names
foreach ($files as $file)
if (is_file($file))
unlink($file);
chdir($source_folder);
rmdir($temp_folder);
}
/**
* Convert an array to XML
*
* @param array $data
* @param string $root
* @param SimpleXMLElement $xml_data
*
* @return string|boolean
*/
private function convertArrayToXML($data, $root = null, $xml_data = null)
{
$_xml_data = $xml_data;
if ($_xml_data === null)
$_xml_data = new SimpleXMLElement($root !== null ? '<' . $root . ' />' : '<root/>');
foreach ($data as $key => $value) {
if (is_array($value)) {
if (is_numeric($key)) {
$key = 'item' . $key; // dealing with <0/>..<n/> issues
$this->convertArrayToXML($value, null, $_xml_data);
} else {
$subnode = $_xml_data->addChild($key);
$this->convertArrayToXML($value, null, $subnode);
}
} else {
// Remove UTF8 Control Characters (breaking XML)
$value = preg_replace('/[\x00-\x1F\x7F]/u', '', $value);
$_xml_data->addChild((string)$key, htmlspecialchars("$value"));
}
}
return $_xml_data->asXML();
}
/**
* Get default outputformat from mimetype if its not set
*
* @param string $outputformat
* @param string $mimetype
*
* @return string
*/
private function getDefaultOutputFormat($outputformat, $mimetype)
{
if ($outputformat)
return $outputformat;
if ($mimetype == 'application/vnd.oasis.opendocument.spreadsheet')
return 'ods';
if ($mimetype == 'application/vnd.oasis.opendocument.text')
return 'odt';
return 'pdf';
}
}
+10 -10
View File
@@ -371,21 +371,21 @@ class FilterCmptLib
foreach ($filterFields as $filterField)
{
// If not an empty array
if ($filterField != null)
if (!isEmptyArray($filterField))
{
//
if (isset($filterField->name) && isset($filterField->operation) && isset($filterField->condition)
&& !isEmptyString($filterField->name) && !isEmptyString($filterField->operation)
&& !isEmptyString($filterField->condition))
if (isset($filterField['name']) && isset($filterField['operation']) && isset($filterField['condition'])
&& !isEmptyString($filterField['name']) && !isEmptyString($filterField['operation'])
&& !isEmptyString((string)$filterField['condition']))
{
// Fine
$filter = new stdClass();
$filter->name = $filterField->name;
$filter->operation = $filterField->operation;
$filter->condition = $filterField->condition;
if (isset($filterField->option) && !isEmptyString($filterField->option))
$filter->name = $filterField['name'];
$filter->operation = $filterField['operation'];
$filter->condition = $filterField['condition'];
if (isset($filterField['option']) && !isEmptyString($filterField['option']))
{
$filter->option = $filterField->option;
$filter->option = $filterField['option'];
}
else
{
@@ -565,6 +565,7 @@ class FilterCmptLib
getAuthPersonId()
);
// If filters were loaded
if (hasData($filters))
{
@@ -1173,4 +1174,3 @@ class FilterCmptLib
return $filterName;
}
}
+21 -15
View File
@@ -246,7 +246,27 @@ class IssuesLib
$fehlertext = vsprintf($fehlertextVorlage, $fehlertext_params);
}
$openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount($fehlercode, $person_id, $oe_kurzbz, $fehlercode_extern);
if (isset($resolution_params))
{
if (is_array($resolution_params))
{
foreach ($resolution_params as $resolution_key => $resolution_param)
{
if (!is_string($resolution_key))
return error("Invalid parameter for resolution, must be an associative array");
}
}
else
return error("Invalid parameters for resolution");
}
$openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount(
$fehlercode,
$person_id,
$oe_kurzbz,
$fehlercode_extern,
$resolution_params
);
if (hasData($openIssuesCountRes))
{
@@ -256,20 +276,6 @@ class IssuesLib
if ($openIssueCount == 0)
{
if (isset($resolution_params))
{
if (is_array($resolution_params))
{
foreach ($resolution_params as $resolution_key => $resolution_param)
{
if (!is_string($resolution_key))
return error("Invalid parameter for resolution, must be an associative array");
}
}
else
return error("Invalid parameters for resolution");
}
// insert new issue
return $this->_ci->IssueModel->insert(
array(
+27
View File
@@ -95,6 +95,33 @@ class PermissionLib
return $isBerechtigt;
}
/**
* Prueft ob die Berechtigung zumindest fuer eine der angegebenen OE vorhanden ist.
* @param $berechtigung_kurzbz
* @param $oe_kurzbz
* @param $art
* @param $kostenstelle_id
* @return boolean
*/
public function isBerechtigtMultipleOe($berechtigung_kurzbz, $oe_kurzbz, $art=null, $kostenstelle_id=null)
{
$results = array();
foreach($oe_kurzbz as $value)
{
$results[] = $this->isBerechtigt($berechtigung_kurzbz, $art, $value, $kostenstelle_id);
}
if(!in_array(true, $results))
{
return false;
}
else
{
return true;
}
}
/**
* Checks if the caller is allowed to access to this content with the given permissions
* - if it's called from command line than it's trusted
+13 -1
View File
@@ -200,6 +200,17 @@ class PhrasesLib
return '<< PHRASE '.$phrase.' >>';
}
/**
* Workaround to reload the phrases array on an already constructed library.
* @parameters -> look for _setPhrases docs
*/
public function setPhrases($categories, $language)
{
if (count($categories) > 0) $this->_setPhrases($categories, $language);
return $this->_phrases;
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
@@ -319,6 +330,7 @@ class PhrasesLib
{
$this->_phrases = $phrases->retval;
}
}
/**
@@ -329,4 +341,4 @@ class PhrasesLib
{
return json_encode($this->_phrases);
}
}
}
+30 -1
View File
@@ -254,7 +254,7 @@ class PrestudentLib
$studiengang = current(getData($res));
$prestudent_status = current($result);
if($prestudent_status->ausbildungssemester + 1 < $studiengang->max_semester)
if ($prestudent_status->status_kurzbz != Prestudentstatus_model::STATUS_UNTERBRECHER && $prestudent_status->ausbildungssemester + 1 < $studiengang->max_semester)
$ausbildungssemester_plus = 1;
if(!$result)
@@ -264,6 +264,35 @@ class PrestudentLib
'studiensemester_kurzbz' => $studiensemester_kurzbz
]));
}
} elseif (current($result)->status_kurzbz == Prestudentstatus_model::STATUS_UNTERBRECHER) {
if ($studierendenantrag_id)
{
$resultAntrag = $this->_ci->StudierendenantragModel->load($studierendenantrag_id);
if (isError($resultAntrag))
return $resultAntrag;
$resultAntrag = getData($resultAntrag);
if (!$resultAntrag)
return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]));
$antrag = current($resultAntrag);
$anmerkung = current($result)->anmerkung . ' Wiedereinstieg ' . $antrag->datum_wiedereinstieg;
$result = $this->_ci->PrestudentstatusModel->update([
'prestudent_id' => $prestudent_id,
'status_kurzbz' => Prestudentstatus_model::STATUS_UNTERBRECHER,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'ausbildungssemester' => current($result)->ausbildungssemester
], [
'updatevon' => $insertvon,
'updateamum' => date('c'),
'anmerkung'=> $anmerkung
]);
if (isError($result))
return $result;
}
return success();
}
$prestudent_status = current($result);
+141 -8
View File
@@ -33,7 +33,7 @@ class SearchBarLib
const ERROR_NOT_AUTH = 'ERR005';
// List of allowed types of search
const ALLOWED_TYPES = ['mitarbeiter', 'mitarbeiter_ohne_zuordnung', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms'];
const ALLOWED_TYPES = ['mitarbeiter', 'mitarbeiter_ohne_zuordnung', 'organisationunit', 'raum', 'person', 'student','studentStv', 'prestudent', 'document', 'cms'];
const PHOTO_IMG_URL = '/cis/public/bild.php?src=person&person_id=';
@@ -178,6 +178,7 @@ class SearchBarLib
protected function buildSearchClause(DB_Model $dbModel, array $columns, $searchstr)
{
$searchstr = preg_replace('/[[:punct:]]/', ' ', $searchstr);
$document = implode(' || \' \' || ', $columns);
$query = '\'' . implode(':* & ', explode(' ', trim($searchstr))) . ':*\'';
$reversequery = '\'*:' . implode(' & *:', explode(' ', trim($searchstr))) . '\'';
@@ -297,13 +298,15 @@ EOSC;
AND (datum_bis IS NULL OR datum_bis >= NOW())
AND b.aktiv = TRUE
) bfLeader ON(bfLeader.oe_kurzbz = o.oe_kurzbz)
WHERE ' .
WHERE
o.aktiv = true
AND (' .
$this->buildSearchClause(
$dbModel,
array('o.oe_kurzbz', 'o.bezeichnung', 'ot.bezeichnung'),
$searchstr
) .
'
')
GROUP BY type, o.oe_kurzbz, o.bezeichnung, ot.bezeichnung, oParent.oe_kurzbz, oParent.bezeichnung, otParent.bezeichnung
');
@@ -359,17 +362,26 @@ EOSC;
private function _student($searchstr, $type)
{
$dbModel = new DB_Model();
$gesperrtes_foto = base64_encode(file_get_contents(DOC_ROOT.'skin/images/profilbild_dummy.jpg'));
$students = $dbModel->execReadOnlyQuery('
SELECT
\''.$type.'\' AS type,
s.student_uid AS uid,
CONCAT(s.student_uid,\'@'.DOMAIN.'\') AS email,
s.matrikelnr,
CONCAT(UPPER(stg.typ),UPPER(stg.kurzbz),\'-\',s.semester,s.verband) as verband,
stg.bezeichnung AS studiengang,
p.person_id AS person_id,
p.vorname || \' \' || p.nachname AS name,
k.kontakt as email ,
p.foto
CASE
when s.student_uid = \''.getAuthUID().'\' then p.foto
when p.foto IS NULL then \''.$gesperrtes_foto.'\'
when p.foto_sperre = false then p.foto
else \''.$gesperrtes_foto.'\'
end as foto,
b.aktiv
FROM public.tbl_student s
JOIN public.tbl_studiengang stg USING(studiengang_kz)
JOIN public.tbl_benutzer b ON(b.uid = s.student_uid)
JOIN public.tbl_person p USING(person_id)
LEFT JOIN (
@@ -377,10 +389,57 @@ EOSC;
FROM public.tbl_kontakt
WHERE kontakttyp = \'email\'
) as k USING(person_id)
WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
WHERE
b.aktiv = TRUE
AND (b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\')
GROUP BY type, s.student_uid, s.matrikelnr, p.person_id, name,
email, p.foto, s.verband, s.semester, stg.bezeichnung,
stg.typ, stg.kurzbz, b.aktiv
ORDER BY b.aktiv DESC, p.nachname ASC, p.vorname ASC
');
// If something has been found then return it
if (hasData($students)) return getData($students);
// Otherwise return an empty array
return array();
}
private function _studentStv($searchstr, $type)
{
$dbModel = new DB_Model();
$students = $dbModel->execReadOnlyQuery('
SELECT
\''.$type.'\' AS type,
s.student_uid AS uid,
s.matrikelnr,
CONCAT(UPPER(stg.typ),UPPER(stg.kurzbz),\'-\',s.semester,s.verband) as verband,
stg.bezeichnung AS studiengang,
p.person_id AS person_id,
p.vorname || \' \' || p.nachname AS name,
k.kontakt AS email,
p.foto,
b.aktiv
FROM public.tbl_student s
JOIN public.tbl_studiengang stg USING(studiengang_kz)
JOIN public.tbl_benutzer b ON(b.uid = s.student_uid)
JOIN public.tbl_person p USING(person_id)
LEFT JOIN (
SELECT kontakt, person_id
FROM public.tbl_kontakt
WHERE kontakttyp = \'email\'
) as k USING(person_id)
WHERE
b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
GROUP BY type, s.student_uid, s.matrikelnr, p.person_id, name, email, p.foto
GROUP BY type, s.student_uid, s.matrikelnr, p.person_id, name,
k.kontakt, p.foto, s.verband, s.semester, stg.bezeichnung,
stg.typ, stg.kurzbz, b.aktiv
ORDER BY b.aktiv DESC, p.nachname ASC, p.vorname ASC
');
// If something has been found then return it
@@ -454,6 +513,80 @@ EOSC;
*/
private function _raum($searchstr, $type)
{
$dbModel = new DB_Model();
$rooms = $dbModel->execReadOnlyQuery('
SELECT
\''.$type.'\' AS type,
COALESCE(ort.ort_kurzbz, \'N/A\') as ort_kurzbz,
COALESCE(ort.gebteil, \'N/A\') as building,
COALESCE(ort.ausstattung, \'N/A\') as austattung,
COALESCE(CAST(ort.stockwerk AS VARCHAR), \'N/A\') as floor,
COALESCE(CAST(ort.dislozierung AS VARCHAR), \'N/A\') as room_number,
COALESCE(CAST(ort.content_id AS VARCHAR), \'N/A\') as content_id,
CASE
WHEN standort.plz IS NULL OR standort.ort IS NULL THEN
CASE
WHEN standort.strasse IS NULL THEN
CASE
WHEN ort.stockwerk IS NULL THEN \'N/A\'
ELSE CONCAT(ort.stockwerk,\' Stockwerk\')
END
ELSE
CASE
WHEN ort.stockwerk IS NULL THEN standort.strasse
ELSE CONCAT(standort.strasse,\' / \',ort.stockwerk,\' Stockwerk\')
END
END
ELSE
CASE
WHEN standort.strasse IS NULL THEN
CASE
WHEN ort.stockwerk IS NULL THEN CONCAT(standort.plz,\' \',standort.ort)
ELSE CONCAT(standort.plz,\' \',standort.ort,\' / \',ort.stockwerk,\' Stockwerk\')
END
ELSE
CASE
WHEN ort.stockwerk IS NULL THEN CONCAT(standort.plz,\' \',standort.ort,\' / \',standort.strasse)
ELSE CONCAT(standort.plz,\' \',standort.ort,\', \',standort.strasse,\' / \',ort.stockwerk,\' Stockwerk\')
END
END
END as standort,
CASE
WHEN ort.max_person IS NULL OR ort.arbeitsplaetze IS NULL THEN \'N/A\'
ELSE CONCAT(ort.max_person,\', davon \',ort.arbeitsplaetze,\' PC-Plätze\')
END as sitzplaetze
FROM public.tbl_ort as ort
LEFT JOIN (
select ort,standort_id,strasse, plz
FROM public.tbl_standort
LEFT JOIN public.tbl_adresse USING(adresse_id)
) standort USING(standort_id)
WHERE
ort.aktiv = true
AND
ort.lehre = true
AND (' .
$this->buildSearchClause(
$dbModel,
array('ort.ort_kurzbz', 'ort.bezeichnung'),
$searchstr
) .
')'
);
// If something has been found
if (hasData($rooms))
{
// Returns the dataset
return getData($rooms);
}
// Otherwise return an empty array
return array();
}
}
+2
View File
@@ -26,6 +26,8 @@ class TableWidgetLib
{
const TABLE_UNIQUE_ID = 'tableUniqueId'; // TableWidget unique id
const TABLE_BOOTSTRAP_VERSION = 'bootstrapVersion'; // TableWidget bootstrap version
// TableWidget session name
const SESSION_NAME = 'FHC_TABLE_WIDGET';
@@ -0,0 +1,232 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
use \stdClass as stdClass;
/**
* Description of DashboardLib
*
* @author bambi
*/
class DashboardLib
{
const WIDGET_ID_RANDOM_BYTES = 16;
const DEFAULT_DASHBOARD_KURZBZ = 'fhcomplete';
const SECTION_IF_FUNKTION_KURZBZ_IS_NULL = 'general';
const USEROVERRIDE_SECTION = 'custom';
private $_ci; // CI instance
public function __construct()
{
// Loads CI instance
$this->_ci =& get_instance();
$this->_ci->load->model('dashboard/Dashboard_model', 'DashboardModel');
$this->_ci->load->model('dashboard/Dashboard_Preset_model', 'DashboardPresetModel');
$this->_ci->load->model('dashboard/Dashboard_Override_model', 'DashboardOverrideModel');
}
public function generateWidgetId($dashboard_kurzbz = '')
{
$dashboard_kurzbz = (!empty($dashboard_kurzbz)) ? $dashboard_kurzbz : self::DEFAULT_DASHBOARD_KURZBZ;
$widgetid_input = time() . '_' . $dashboard_kurzbz . '_' . bin2hex(random_bytes(self::WIDGET_ID_RANDOM_BYTES));
$widgetid = md5($widgetid_input);
return $widgetid;
}
public function getDashboardByKurzbz($dashboard_kurzbz)
{
$result = $this->_ci->DashboardModel->getDashboardByKurzbz($dashboard_kurzbz);
if (hasData($result))
{
return current(getData($result));
}
return null;
}
public function getMergedConfig($dashboard_id, $uid)
{
$defaultconfig = $this->getDefaultConfig($dashboard_id, $uid);
$userconfig = $this->getUserConfig($dashboard_id, $uid);
$mergedconfig = array_replace_recursive($defaultconfig, $userconfig);
return $mergedconfig;
}
public function getDefaultConfig($dashboard_id, $uid)
{
$res_presets = $this->_ci->DashboardPresetModel->getPresets($dashboard_id, $uid);
$defaultconfig = array();
if (hasData($res_presets))
{
$presets = getData($res_presets);
foreach ($presets as $presetobj)
{
$preset = json_decode($presetobj->preset, true);
if (null !== $preset)
{
$defaultconfig = array_replace_recursive($defaultconfig, $preset);
}
}
}
return $defaultconfig;
}
public function getUserConfig($dashboard_id, $uid)
{
$res_userconfig = $this->_ci->DashboardOverrideModel->getOverride($dashboard_id, $uid);
if (hasData($res_userconfig))
{
$data = getData($res_userconfig);
$decodedconfig = json_decode(current($data)->override, true);
if (null !== $decodedconfig)
{
return $decodedconfig;
}
}
return [];
}
public function getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid)
{
$override = $this->getOverride($dashboard_kurzbz, $uid);
if (null !== $override) {
return $override;
}
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
$emptyoverride = new stdClass();
$emptyoverride->dashboard_id = $dashboard->dashboard_id;
$emptyoverride->uid = $uid;
$emptyoverride->override = '{"widgets": {"' . self::USEROVERRIDE_SECTION . '": {}}}';
return $emptyoverride;
}
public function getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz)
{
if ($funktion_kurzbz === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL)
$funktion_kurzbz = null;
$preset = $this->getPreset($dashboard_kurzbz, $funktion_kurzbz);
if (null !== $preset) {
return $preset;
}
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
$emptypreset = new stdClass();
$emptypreset->dashboard_id = $dashboard->dashboard_id;
$emptypreset->funktion_kurzbz = $funktion_kurzbz;
$section = ($funktion_kurzbz !== null) ? $funktion_kurzbz : self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL;
$emptypreset->preset = '{"widgets": {"' . $section . '": {}}}';
return $emptypreset;
}
public function getPreset($dashboard_kurzbz, $section)
{
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
$funktion_kurzbz = ($section === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL) ? null : $section;
$result = $this->_ci->DashboardPresetModel
->getPresetByDashboardAndFunktion($dashboard->dashboard_id, $funktion_kurzbz);
if (hasData($result))
{
return current(getData($result));
}
return null;
}
public function getOverride($dashboard_kurzbz, $uid)
{
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
$result = $this->_ci->DashboardOverrideModel
->getOverride($dashboard->dashboard_id, $uid);
if (hasData($result))
{
return current(getData($result));
}
return null;
}
public function insertOrUpdatePreset($preset)
{
if (isset($preset->preset_id) && $preset->preset_id > 0)
{
$result = $this->_ci->DashboardPresetModel->update($preset->preset_id, $preset);
}
else
{
$result = $this->_ci->DashboardPresetModel->insert($preset);
}
return $result;
}
public function insertOrUpdateOverride($override)
{
if (isset($override->override_id) && $override->override_id > 0)
{
$result = $this->_ci->DashboardOverrideModel->update($override->override_id, $override);
}
else
{
$result = $this->_ci->DashboardOverrideModel->insert($override);
}
return $result;
}
public function addWidgetsToWidgets(&$widgets, $dashboard_kurzbz, $section, $addwigets)
{
foreach ($addwigets as $widget)
{
if(!isset($widget->widgetid))
{
$widget->widgetid = $this->generateWidgetId($dashboard_kurzbz);
}
$this->addWidgetToWidgets($widgets, $section, $widget, $widget->widgetid);
}
}
public function addWidgetToWidgets(&$widgets, $section, $widget, $widgetid)
{
$section = ($section !== null) ? $section : self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL;
if (!isset($widgets[$section]) || !is_array($widgets[$section]))
{
$widgets[$section] = array();
}
$widgets[$section][$widgetid] = $widget;
}
public function removeWidgetFromWidgets(&$widgets, $section, $widgetid)
{
$section = ($section !== null) ? $section : self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL;
if (isset($widgets[$section]) && isset($widgets[$section][$widgetid]))
{
unset($widgets[$section][$widgetid]);
if(empty($widgets[$section]) && $section !== self::USEROVERRIDE_SECTION) {
unset($widgets[$section]);
}
return true;
}
else {
return false;
}
}
}

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