Compare commits

...

899 Commits

Author SHA1 Message Date
Harald Bamberger d0f3cee7de add permissions for vw_oe_path 2024-07-29 18:11:13 +02:00
Harald Bamberger e6684a0116 add db view that contains oe path 2024-07-29 17:41:24 +02:00
Harald Bamberger 965e23dba7 Merge branch 'feature-40743/Anrechnung_Config-fuer-zusaetzliche-Felder' 2024-07-17 14:08:55 +02:00
Harald Bamberger f064a29efc Merge branch 'master' into feature-40743/Anrechnung_Config-fuer-zusaetzliche-Felder 2024-07-17 08:02:55 +02:00
Harald Bamberger 6dd1dc62bf Merge branch 'feature-39592/vereinfachte_Sicht_fuer_Assistenz' 2024-07-16 20:59:48 +02:00
Harald Bamberger fcacd2a660 Merge branch 'master' into feature-39592/vereinfachte_Sicht_fuer_Assistenz 2024-07-16 14:23:16 +02:00
Harald Bamberger 8c9ed2c52c Textaenderung 2024-07-16 14:19:32 +02:00
Harald Bamberger 36aab1b579 Merge branch 'feature-36555/Studstatus_HinweistextFAS_Pruefungsdatum' 2024-07-16 14:11:34 +02:00
Harald Bamberger 3c50ffd945 remove unnecessary style 2024-07-16 14:07:44 +02:00
Harald Bamberger bf1f0428ea use textbox to retain layout 2024-07-15 19:06:19 +02:00
Harald Bamberger f49161420d try to improve layout 2024-07-15 18:18:53 +02:00
Harald Bamberger 464dbba457 add missing api js files 2024-07-11 18:43:31 +02:00
Harald Bamberger 9d455c35d0 Betriebsmittel.js: use arrow function for dynamic ajaxParams, Filter.js: remove required from filterType 2024-07-11 18:32:47 +02:00
Harald Bamberger 3f84024ce8 uncomment null check, layout of hint 2024-07-11 17:35:18 +02:00
Harald Bamberger 16ab9998b0 Merge branch 'master' into feature-39592/vereinfachte_Sicht_fuer_Assistenz 2024-07-11 14:44:44 +02:00
Harald Bamberger 115151473a backport recent changes of Betriebsmittel component and phrases from feature-30660/FHC4_StudierendenGUI_Prototyp Branch 2024-07-11 11:57:45 +02:00
Cris a23b133217 Adapted requestAnrechnung.js to handle submit data and events on Begruendung-zur-Gleichwertigkeit fields
...depending on $config['explain_equivalence']
2024-07-11 10:54:43 +02:00
Cris 1139b251ef Adapted Views to handle display of Begruendung-zur-Gleichwertigkeit fields
...depending on $config['explain_equivalence']
2024-07-11 10:52:51 +02:00
Cris 8c3b85066a Adapted Controller RequestAnrechnung.php to handle Begruendung-zur-Gleichwertigkeit fields
...depending on $config['explain_equivalence']
2024-07-11 10:49:05 +02:00
Cris 0b48e94d3c Added config variable $config['explain_equivalence'] (Begruendung zu Gleichwertigkeit)
...to display and enable 'Begründung zu Gleichwertigkeit'-fields
2024-07-11 10:44:12 +02:00
Harald Bamberger 46ea054bac change text, add config to show hint or not, styling 2024-07-10 15:52:57 +02:00
Cris 03205674aa Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-07-10 15:51:51 +02:00
Harald Bamberger 8b254b3967 Merge branch 'master' into feature-36555/Studstatus_HinweistextFAS_Pruefungsdatum 2024-07-09 11:52:07 +02:00
Harald Bamberger c4ef0f998c Merge branch 'feature-40285/Studstatus_Datum_der_Abmeldung_auf_den_3_Abmeldungsdokumenten' 2024-07-09 11:49:41 +02:00
Harald Bamberger 37fb9dd851 use date that seems more stable than one that depends on a config entry that may change over time and then change the date in previous documents 2024-07-09 11:38:16 +02:00
Harald Bamberger 2a537df687 Merge branch 'master' into feature-40285/Studstatus_Datum_der_Abmeldung_auf_den_3_Abmeldungsdokumenten 2024-07-09 10:35:40 +02:00
Harald Bamberger dd0bdddbc6 backport recent changes of Betriebsmittel component and phrases from feature-30660/FHC4_StudierendenGUI_Prototyp Branch 2024-07-01 14:12:48 +02:00
Cris e8fe3c2eff Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-06-26 11:53:28 +02:00
Andreas Österreicher b56e8c5f9f Im Abschlusspruefung Karteireiter wird in der Liste bei der Beurteilung jetzt die
Bezeichnung der Note angezeigt anstatt der Kurzbz
2024-06-21 13:02:55 +02:00
cgfhtw 9c53a7a75b PDF Download Button während Einspruchsfrist verbergen 2024-06-19 14:02:20 +02:00
Harald Bamberger 1f36a08f05 Merge branch 'merge_37107_37133_39212' 2024-06-19 11:41:11 +02:00
cgfhtw 631a552708 Datum bei Abmeldung d Stud PDF 2024-06-19 10:55:48 +02:00
Harald Bamberger ea9c35a64b Merge branch 'feature-37107/Fristenmanagement' into merge_37107_37133_39212 2024-06-19 10:28:39 +02:00
Harald Bamberger 04c006a733 do not create dummy manual events 2024-06-19 10:28:03 +02:00
Harald Bamberger aff1f9126f Merge branch 'master' into merge_37107_37133_39212 2024-06-19 09:45:05 +02:00
cgfhtw a8acf91980 Datum bei Abmeldung Fristablauf d WH PDF 2024-06-19 09:21:13 +02:00
Andreas Österreicher fb77ab67e7 Prüfungshonorare im Notenkarteireiter zeigen nur aktive Mitarbeiter an 2024-06-19 09:05:08 +02:00
Harald Bamberger d3a277f9fb Merge branch 'feature-39212/PV21-Grund_beim_Beenden_eines_DV' into merge_37107_37133_39212 2024-06-19 08:52:03 +02:00
Harald Bamberger 0aa53f64ff db Aenderungen Gegenpruefung hinzugefuegt 2024-06-19 08:51:34 +02:00
cgfhtw 3e0c15e18f Datum bei Abmeldung d StgL PDF 2024-06-18 11:12:12 +02:00
Cris 538c2e09ce Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-06-17 14:20:43 +02:00
Harald Bamberger e05fa0f4d8 Merge branch 'master' into merge_37107_37133_39212 2024-06-14 11:50:32 +02:00
Harald Bamberger c3278ad30f add app softwarebereitstellung to prevent checksystem errors when adding phrases for softwarebereitstellung while not having installed the extension 2024-06-14 11:49:43 +02:00
Harald Bamberger e4326e00e4 Merge branch 'feature-39212/PV21-Grund_beim_Beenden_eines_DV' into merge_37107_37133_39212 2024-06-14 11:02:25 +02:00
Harald Bamberger 93d0f88b0d function getDVByPersonUID: add dvendegrund_kurzbz and dvendegrund_anmerkung to select 2024-06-14 10:48:43 +02:00
Harald Bamberger 1c385d22cd Merge branch 'feature-37133/Gehaltsbaender' into merge_37107_37133_39212 2024-06-14 10:41:48 +02:00
Harald Bamberger 24786c6ae6 Merge branch 'feature-37107/Fristenmanagement' into merge_37107_37133_39212 2024-06-13 13:30:38 +02:00
Harald Bamberger 0e5d4b30ed Merge branch 'master' into feature-37133/Gehaltsbaender 2024-06-13 13:26:48 +02:00
Harald Bamberger 4e233f760d Merge branch 'master' into feature-37107/Fristenmanagement 2024-06-13 13:26:02 +02:00
Harald Bamberger fd2474cc38 Merge branch 'master' into feature-39212/PV21-Grund_beim_Beenden_eines_DV 2024-06-13 11:51:10 +02:00
Andreas Österreicher 20eee62c19 Merge branch 'sonstiges-40279/SWB-Lizenzserverport' 2024-06-13 11:13:30 +02:00
Werner Masik eb327c3adc update Handyverwaltung filter 2024-06-12 14:52:22 +02:00
Harald Bamberger 1e56707e5a Merge branch 'feature-40415/Studstatus-UID_in_Sancho_Message_Abmeldung_StG_Ablauf_Einspruchsfrist' 2024-06-12 08:13:11 +02:00
Harald Bamberger 6816a300f6 Beschriftung korrigiert 2024-06-11 16:39:20 +02:00
Harald Bamberger 0b8191a435 Beschriftung zu IDs in Sancho Message hinzugefuegt 2024-06-11 16:26:52 +02:00
Harald Bamberger f8d8a44a3c student_uid zu sancho message Abmeldung StG Ablauf Einspruchsfrist 2024-06-11 14:47:54 +02:00
Cris cd0eacf947 Updated phrases: Added phrases 'lizenzserverPort' and 'raumSwZuordnung' 2024-06-11 13:52:03 +02:00
Cris dd47cd2a7c Updated filter: Added lizenzserver_kurzbz and lizenzserver_port to SoftwareManagement filter 2024-06-11 13:51:03 +02:00
Cris a4b77fc43f Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-06-11 11:32:47 +02:00
Andreas Österreicher f943ae7566 Merge branch 'feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' 2024-06-10 14:05:49 +02:00
Cris f1547b069d Merge branch 'feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' of https://github.com/FH-Complete/FHC-Core into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2024-06-10 13:37:46 +02:00
Cris ac7dc1599c Corrected path to init.js.php 2024-06-10 13:37:14 +02:00
Andreas Österreicher 46b7dc1ce7 Dauer für die Anzeige von abgelaufenen Projekten in der Zeitaufzeichnung
auf 2 Monate verlängert
2024-06-07 10:19:12 +02:00
Werner Masik cd8fffd2f7 added filter update for Handyverwaltung 2024-06-04 16:20:43 +02:00
Cris 125a2da9b3 Merge branch 'feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' of https://github.com/FH-Complete/FHC-Core into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2024-06-04 16:16:49 +02:00
Cris 884d930e71 Merge branch 'master' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2024-06-04 16:05:33 +02:00
Cris 49045c06af Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-06-04 16:04:19 +02:00
Harald Bamberger 7b148b1a39 Merge branch 'master' into feature-39212/PV21-Grund_beim_Beenden_eines_DV 2024-06-03 17:21:50 +02:00
Harald Bamberger 0cbb8997e2 migratecontract config und config check auch in MigrateHourlyRate verwenden 2024-06-03 17:14:55 +02:00
Cris 512002c0e8 Created init.js file and changed link url in stpl_week to open Software-Raumsuche by OrtKurzbz 2024-06-03 16:40:35 +02:00
Cris 9652f48044 Added phrases 'zugeklappt', 'softwareliste', 'raumverfuegbarkeit' 2024-06-03 16:27:31 +02:00
Harald Bamberger 9454bde14a backport Betriebsmittel Component from feature-30660/FHC4_StudierendenGUI_Prototyp Branch 2024-05-29 15:19:23 +02:00
Harald Bamberger a924c9d2bb backport Betriebsmittel Component from feature-30660/FHC4_StudierendenGUI_Prototyp Branch 2024-05-29 11:49:11 +02:00
Andreas Österreicher 5453579c7b Merge branch 'feature-36963/BIS_check_duales_Studium' 2024-05-28 09:29:44 +02:00
KarpAlex d8ba92e343 Merge branch 'master' into feature-36963/BIS_check_duales_Studium 2024-05-27 19:42:48 +02:00
cgfhtw d5e8227918 Bugfix: api/frontend/fas controller do not inherit from FHCAPI_Controller 2024-05-27 12:45:10 +02:00
Harald Bamberger 8cba0aec5a vertragsarten dvbund, dvanderegk und dvanderebet hinzugefuegt, MigrateContract default oe und ba1code mapping in config verschoben und config check implementiert 2024-05-22 15:32:28 +02:00
Cris aab198e355 Merge branch 'master' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2024-05-22 11:03:34 +02:00
Cris 559a6b317d Fixed multiple display of child software 2024-05-21 14:44:41 +02:00
Cris 66a80697c2 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-05-21 14:21:34 +02:00
Werner Masik 706dad6df6 added DV Ende 2024-05-16 21:58:34 +02:00
Harald Bamberger f2a2469e6e MigrateContract: keine ZeitaufzeichnungsVbs erstellen wenn za oder azg flag null ist. MigrateHourlyRate: kalkulatorische Stundensaetze nur migrieren wenn SAP Sync Tabelle existiert. 2024-05-15 17:25:26 +02:00
Cris c4c17f69c7 Added phrase softwaretypKurzbz 2024-05-14 13:41:33 +02:00
Cris 8a0d2a2f10 Refactored Tabs title assignment to utilize computed property
This is necessary to render language phrases correctly
2024-05-13 14:02:05 +02:00
Cris 6d728ae0e7 Merge branch 'master' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software
# Conflicts:
#	public/js/components/Tabs.js
#	public/js/components/filter/Filter.js
2024-05-13 12:07:37 +02:00
Cris 58f52dfaae Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-05-13 11:07:16 +02:00
Cris 5643607845 Added phrases 'statusErfolgreichUebertragen' and 'statusUebertragenMsg' to Softwarebereitstellung app 2024-05-13 11:06:32 +02:00
Harald Bamberger 93b111af93 fix handleSystemError is not a function 2024-05-06 16:48:38 +02:00
Harald Bamberger 6a8a96b748 fix long lasting request getPrestudents to block browser when timedout once 2024-05-06 16:04:45 +02:00
Harald Bamberger 69b0b3601d Merge branch 'master' into feature-39212/PV21-Grund_beim_Beenden_eines_DV 2024-05-03 13:08:12 +02:00
Andreas Österreicher 40c0393bc0 Voller Name der Kritikalität des Services wird angezeigt im
Servicekatalog
2024-05-02 16:31:34 +02:00
Andreas Österreicher c6193530db Merge branch 'feature-39288/Servicekatalog_Kritikalitaet' 2024-05-02 16:27:09 +02:00
Harald Bamberger 3a3d28e9e6 Merge branch 'feature-37246/APIs_Konsolidierung' 2024-04-30 21:45:48 +02:00
Harald Bamberger 3b8776f947 Merge branch 'master' into feature-37246/APIs_Konsolidierung 2024-04-30 16:26:15 +02:00
Andreas Österreicher 23255ed84f Merge branch 'feature-17727/FasDefaultStundensatzProjektbetreuungAnzeigen' 2024-04-30 16:17:00 +02:00
Andreas Österreicher a3b5996c50 Stundensatz wird abhängig vom Studiensemester der Projektarbeit /
Lehreinheit ermittelt
2024-04-30 16:16:03 +02:00
Andreas Österreicher a606add6eb Merge branch 'master' into feature-17727/FasDefaultStundensatzProjektbetreuungAnzeigen 2024-04-30 10:55:58 +02:00
KarpAlex 18dabf26e4 service uebersicht in cis: loading only one moodle config instead of all addon configs to avoid php notices 2024-04-29 14:00:30 +02:00
Harald Bamberger ef5040557d Merge branch 'master' into feature-37246/APIs_Konsolidierung 2024-04-29 09:37:06 +02:00
Andreas Österreicher 8999b59f4e Renamed Field 2024-04-26 13:41:33 +02:00
Harald Bamberger 2ea3597a10 Merge branch 'master' into feature-39212/PV21-Grund_beim_Beenden_eines_DV 2024-04-25 15:11:41 +02:00
Harald Bamberger 08dd6a7783 add dvendegrund_kurzbz and dvendegrund_anmerkung when reading dvs from db 2024-04-25 15:11:16 +02:00
Andreas Österreicher d55cb56a1a Merge branch 'bug-39609/automatischer_abgewiesener_status_setzen' 2024-04-25 14:24:43 +02:00
ma0048 8bac75ae52 - bug behoben, damit keine leeren "Status Abgewiesen gesetzt" Mails verschickt werden 2024-04-25 14:20:18 +02:00
Werner Masik 3b06519f2f updated phrases for salary range 2024-04-24 15:25:42 +02:00
Werner Masik c15a350392 moved dbUpdate for gehaltsband to extension 2024-04-24 14:55:22 +02:00
Harald Bamberger c33a11e952 Merge branch 'master' into feature-37246/APIs_Konsolidierung 2024-04-24 08:30:25 +02:00
Harald Bamberger 844c07be9c Merge branch 'feature-39174/Studstatus_AbmeldungStglFuerUnterbrecher' 2024-04-24 08:25:51 +02:00
Harald Bamberger 5175dcdbe4 Merge branch 'master' into feature-37246/APIs_Konsolidierung 2024-04-23 15:57:50 +02:00
Andreas Österreicher 0655118f2b Merge branch 'feature-39349/tdb_phrasen' 2024-04-19 10:38:39 +02:00
Alexei Karpenko 412bb10a06 Servicekatalog: renamed Kategorie column to Kritikalität in vilesci, added column Kritikalitaet in cis overview 2024-04-18 15:38:22 +02:00
Andreas Österreicher 3a4492671d Fixed Signing Documents via CIS 2024-04-18 08:53:22 +02:00
Werner Masik b2deea6962 added db schema for Gehaltsbaender 2024-04-17 16:40:12 +02:00
Andreas Österreicher 8a115626ba CDATA bei Lernergebnisse hinzugefügt 2024-04-16 10:33:27 +02:00
Andreas Österreicher 20aba9aa90 Merge branch 'feature-27349/DiplomaSupplementQuereinstiegerRahmenvertrag' 2024-04-16 10:22:48 +02:00
Andreas Österreicher 8057ecbc60 Merge branch 'feature-15490/lehrauftragsliste_stammkostenstelle_bei_fix_angestellten' 2024-04-15 15:41:53 +02:00
cgfhtw e0c7691e04 missing catch 2024-04-11 15:14:15 +02:00
Andreas Österreicher c03e6deb95 Removed useless code 2024-04-10 16:45:46 +02:00
ma0068 941dce6032 Diplomasupplement: Adaptierung Wording Niveau 2024-04-10 14:48:04 +02:00
Harald Bamberger 94224f7ef7 dvendegrund Ablauf durch Zeit added 2024-04-10 14:28:07 +02:00
Cris f51f006377 Corrected phrase anmerkungIntern 2024-04-10 14:07:41 +02:00
Andreas Österreicher 637392c844 Merge branch 'master' into feature-15490/lehrauftragsliste_stammkostenstelle_bei_fix_angestellten 2024-04-10 09:56:58 +02:00
Harald Bamberger e11dd21a1e add parameter dvendegrund_kurzbz and dvendegrund_anmerkung 2024-04-09 16:35:00 +02:00
Harald Bamberger 1a1cd76bc4 add grant on hr.tbl_dvendegrund to user vilesci 2024-04-09 15:42:00 +02:00
Harald Bamberger a9818e1f63 add initial values to hr.tbl_dvendegrund 2024-04-09 15:27:47 +02:00
Harald Bamberger 56900e31db add table hr.tbl_dvendegrund, add columns dvendegrund_kurzbz and dvendegrund_anmerkung to hr.tbl_dienstverhaeltnis 2024-04-09 15:08:32 +02:00
Andreas Österreicher e41eada893 Removed unused Code 2024-04-09 14:08:58 +02:00
Andreas Österreicher a32e78c9b8 Merge branch 'master' into feature-27349/DiplomaSupplementQuereinstiegerRahmenvertrag 2024-04-09 13:53:37 +02:00
Cris 1d0c2be449 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-04-09 11:33:38 +02:00
Andreas Österreicher bdb0a5702d Fehler behoben wodurch keine Note im Freigabemail angezeigt wurde
Fehler behoben wodurch keine Punkteübernahme bie Nachprüfungen möglich
war
2024-04-09 11:24:44 +02:00
Harald Bamberger 026a276c02 add grant on frist_id sequence 2024-04-09 11:11:03 +02:00
Harald Bamberger 3b41df5ddc Merge branch 'master' into feature-37107/Fristenmanagement 2024-04-09 10:44:02 +02:00
Andreas Österreicher 8a9477eaf0 Fixed PHP7.4 Warning 2024-04-08 12:54:05 +02:00
Werner Masik f2ba0fd469 update phrases and added events for fristenmanagement 2024-04-07 00:33:25 +02:00
Andreas Österreicher 257c7a5aac Projektzeitenexport für Administration/HR im Vilesci hinzugefügt 2024-04-05 14:14:13 +02:00
ma0048 753a193be1 - added phrases for bpks details 2024-04-04 15:41:18 +02:00
KarpAlex 2132fe76ae added Plausicheck: students in DUAL Studiengang should have set boolean value dual to true, plausicheck bugfixes (loading model, remove unnecessary property) 2024-04-03 17:39:00 +02:00
Cris cfe73b361e Sorted project phases by start date and bezeichnung in Zeitaufzeichnung
Sorted within dropdown
2024-04-03 15:13:32 +02:00
Cris a2791fecd1 Sorted projects in alphabetical order in Zeitaufzeichnung
Sorted within dropdown and in project cvs export file.
2024-04-03 13:10:30 +02:00
Cris d2a8d59f6d Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-04-03 12:59:00 +02:00
Cris 9907ee2267 Added phrase global/zeilenAuswaehlen 2024-04-03 11:45:43 +02:00
Werner Masik 5cabac62d7 add frist events for befristung 2024-04-02 18:33:37 +02:00
cgfhtw 8ffc8a20d3 s&d 2024-03-29 14:27:45 +01:00
cgfhtw d34ce78c94 s&d 2024-03-29 13:00:54 +01:00
kindlm 5d49516b77 Merge branch 'ReportingFilterParameter' 2024-03-28 13:56:07 +01:00
kindlm 538264e577 Merge branch 'master' into ReportingFilterParameter 2024-03-28 13:55:29 +01:00
kindlm 2f99457283 GET-Parameter auch für Text übernehmen 2024-03-28 13:54:45 +01:00
Cris ba1fa6add4 Merge branch 'master' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2024-03-28 13:20:51 +01:00
Cris 8d8e45b6de Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-03-28 13:20:16 +01:00
Cris 05516f2952 Fixed: issue with component tabs not recognizing loaded phrases
Vue.computed ensures loading phrase reactively when phrases are loaded
2024-03-28 13:19:31 +01:00
Cris d34f5b92f4 Added new phrases for softwarebereitstellung- and for core app 2024-03-28 13:14:34 +01:00
Andreas Österreicher 4ccf2aebcc Prüfungstyp Termin3 wird nicht automatisch angelegt 2024-03-27 12:57:17 +01:00
Manfred 21b05394c8 Merge branch 'master' into ReportingFilterParameter 2024-03-26 17:24:07 +01:00
kindlm 7240a97d6e Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-03-26 17:16:57 +01:00
kindlm e469f54901 Typ "Text" bei vordefinierten Filtern ergänzt 2024-03-26 17:16:44 +01:00
Andreas Österreicher 42ddea9f51 Fixed Typ in Variable Name 2024-03-26 16:37:13 +01:00
Andreas Österreicher 058ed94c2b Merge branch 'feature-36196/DVUH_Meldestatus_beruecksichtigen' 2024-03-26 11:34:26 +01:00
Harald Bamberger a95c2fe47e studstatus switch fullname to have surname first 2024-03-26 11:27:44 +01:00
Andreas Österreicher 1e9a681c9a Gegencheck für tbl_tmp_store und tbl_audit_log entfernt da dies Tabellen
aus der Personalveraltung Extension sind
Gegencheck für Habiliation hinzugefügt
2024-03-26 09:19:36 +01:00
Harald Bamberger aabc10d1fc Merge branch 'master' of github.com:FH-Complete/FHC-Core 2024-03-25 16:54:00 +01:00
Harald Bamberger d4bc5148a7 fix disappearing searchbar when session expires, add functions to fetch dvs at a certain duedate for valorisation 2024-03-25 16:53:03 +01:00
Andreas Österreicher fe1ea63496 Merge branch 'feature-33294/StudienerfolgsbestaetigungAbbrecher' 2024-03-25 15:59:12 +01:00
Harald Bamberger 2a26765ff6 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' 2024-03-25 15:05:46 +01:00
Harald Bamberger 5413292529 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-03-25 14:55:46 +01:00
Harald Bamberger 8a86bce567 Merge branch 'feature-33003/BIS_Meldung_Personal' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-03-25 14:55:11 +01:00
Harald Bamberger ad415ad665 deactivateDienstverhaeltnis: only set user to inactive if no other dv is active 2024-03-25 14:04:21 +01:00
Andreas Österreicher 6a6db4292f Merge branch 'feature-18571/EntwicklungsteamBisMeldung' 2024-03-25 13:54:42 +01:00
Andreas Österreicher 5fd4ded184 Merge branch 'master' into feature-18571/EntwicklungsteamBisMeldung 2024-03-25 13:12:35 +01:00
Harald Bamberger 9f2dd82009 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-03-25 13:08:10 +01:00
cgfhtw 06b0529813 Autocomplete: empty message 2024-03-22 09:10:13 +01:00
cgfhtw c4942cc70e Studstatus => FhcApi 2024-03-21 15:45:55 +01:00
Cris bc798bd0b4 Added uniqueId prop to Filter.js to fix URL using apiFunctionParameters.filterUniqueId 2024-03-20 09:58:25 +01:00
Cris f6eceb892d Added label property 'class' to Input.js
...which fixes style issues when creating input-group buttons using the Input.js component
2024-03-20 09:52:26 +01:00
Cris 6eae83f4eb Added primevues autocomplete slot template to Input.js
Now, when using the Input Component with type 'autocomplete', it is possible to add also primevues built in slot templates there
2024-03-20 09:50:03 +01:00
Cris 842e62b0dd Fixed Input.js error causing to keep last entries' first letter in form inputs, even when formdata was emptied 2024-03-20 09:42:23 +01:00
Cris 10e57dae2d Adapted style of .tabulator-cell .btn to be squared and increased padding 2024-03-20 09:38:08 +01:00
cgfhtw 69803cdb0d Phrasen: Bugfix - correct function for multiple categories 2024-03-20 08:27:26 +01:00
Werner Masik 426a439552 added sort column to frist 2024-03-20 00:13:55 +01:00
cgfhtw 4e6b7a845b FhcApi: use errorHeader for multiple calls 2024-03-19 16:54:14 +01:00
cgfhtw 30efd55d6c FhcApi: settle handled Promises & discard them in FhcAlert 2024-03-19 16:53:36 +01:00
Manfred e1b5a86390 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-03-19 15:55:00 +01:00
Manfred be0d73cd22 Sortierung der Studiensemester absteigend; Ziel-Studiensemester passt sich automatisch an 2024-03-19 15:54:54 +01:00
cgfhtw 8f0e837fb7 Phrasen Plugin: Bugfix this 2024-03-19 08:45:10 +01:00
cgfhtw b147f73954 Merge branch 'master' into feature-37246/APIs_Konsolidierung 2024-03-18 09:51:29 +01:00
Andreas Österreicher 2cce61ca6a Korrekturen für Gehaltsimport 2024-03-15 13:37:07 +01:00
kindlm 1d81a4c2e8 Buttonbeschriftung geändert um barrierefreier zu sein 2024-03-14 17:08:03 +01:00
kindlm 79a1e6a7fd Merge branch 'benutzerberechtigungGUIneu' 2024-03-14 16:41:53 +01:00
kindlm 7bec921018 Merge branch 'master' into benutzerberechtigungGUIneu 2024-03-14 16:40:07 +01:00
kindlm d9caf746a1 Rechte-GUI verbesserungen
- Inaktive und WaWi-Einträge ausgblenden
- Kopie-Anmerkung verkürzt
- Inaktive OE Kennzeichnen
- Link ins CIS-Profil
- Shortcut zum einfügen von Datum und Kürzel
- "Mitarbeiter" ist default bei Benutzersuche
- GUI-Verbesserungen bei Rollenvergleich
2024-03-14 16:39:01 +01:00
Harald Bamberger bacfbd33f3 Merge branch 'feature-36016/Studstatus_QMB' 2024-03-14 12:37:21 +01:00
Harald Bamberger 77221e507f set tabulator to fixed height, fix missing grund when editing unterbrechung 2024-03-14 11:42:39 +01:00
cgfhtw bc5d42b310 Studstatus: ausbildungssemester in getAllPrestudentsWhereCommitteeExamFailed 2024-03-14 08:52:55 +01:00
cgfhtw cba4c8e365 Studstatus: Fallback for antrag details 2024-03-13 16:46:10 +01:00
Harald Bamberger af79736d67 documents use ausbildungssemester from prestudentstatus in semester of antrag, fix missing grund when editing unterbrechung 2024-03-13 16:16:23 +01:00
cgfhtw f5bc8bdcb2 Studstatus: Unterbrechung: get semester for current status on new Antrag 2024-03-13 10:40:32 +01:00
cgfhtw 673fd889fe Studstatus: get details without whitelist 2024-03-13 10:39:51 +01:00
cgfhtw ab7a5bac68 Unterbrechung studienjahr und semester anzeige 2024-03-13 08:37:40 +01:00
Werner Masik e28627a676 removed verantwortlich column from tbl_frist 2024-03-12 17:34:13 +01:00
Harald Bamberger 4c8486af22 use correct config property 2024-03-12 14:36:27 +01:00
Harald Bamberger d05df01178 move load lib from function handleAbmeldungenStglDeadline to constructor as its also used in handleWiederholerDeadline 2024-03-12 13:22:01 +01:00
Harald Bamberger 7bdf5b832b Merge branch 'master' into feature-36016/Studstatus_QMB 2024-03-12 11:32:25 +01:00
Harald Bamberger 9504b713fc add missing insertvon to phrases definition 2024-03-12 11:31:12 +01:00
Andreas Österreicher 8d2d1c049a Removed wrong Semicolon 2024-03-12 08:28:16 +01:00
cgfhtw ac39ce8e71 Studstatus create view: fallback for studierendenantrag_id 2024-03-11 15:27:34 +01:00
cgfhtw 6acf65b49f Form Component: expose _defaultErrorHandlers 2024-03-11 15:24:48 +01:00
cgfhtw 40c98b1dcc FHCAPI Controller: optional status param for error function 2024-03-11 15:23:54 +01:00
cgfhtw b359a77a8d Comments 2024-03-11 09:56:34 +01:00
cgfhtw d259c0d35c Fetch: more robust error handling 2024-03-11 09:46:59 +01:00
cgfhtw 011b4a83eb Filter => FhcApi 2024-03-11 09:46:39 +01:00
Harald Bamberger 664fe3830f Merge branch 'master' into feature-33003/BIS_Meldung_Personal 2024-03-08 11:39:02 +01:00
Harald Bamberger b17f253273 Tabs component: add flex-grow-1 class to use available space 2024-03-08 11:37:23 +01:00
Harald Bamberger d9e44c8c23 Merge branch 'master' into feature-33003/BIS_Meldung_Personal 2024-03-08 11:08:40 +01:00
cgfhtw 85f9b14326 Comments 2024-03-07 16:56:37 +01:00
cgfhtw 5f77bdd6fc Spelling 2024-03-07 16:56:30 +01:00
cgfhtw d2eadb98ce Navigation => FhcApi 2024-03-07 16:56:14 +01:00
cgfhtw 291f32bfe2 Tabs => FhcApi 2024-03-07 14:35:29 +01:00
cgfhtw f539ed8977 Depricated comment 2024-03-07 08:54:28 +01:00
cgfhtw 20619311e3 Use fhcApi in Searchbar 2024-03-07 08:50:27 +01:00
cgfhtw 4ac46d19e9 Testsearch view: naming convention 2024-03-07 08:23:29 +01:00
cgfhtw dad459e023 Testsearch: Codequality 2024-03-07 08:18:49 +01:00
cgfhtw 8f6fbda4cf Testsearch: Bugfixes 2024-03-07 08:11:58 +01:00
Andreas Österreicher b753a05f0e Anpassungen am Import Script für Gemeinden von FHB übernommen 2024-03-07 08:10:17 +01:00
cgfhtw b6723e92d8 Code Quality 2024-03-07 08:01:11 +01:00
cgfhtw 1344ab987e Options for custom FhcApiFactory 2024-03-06 16:52:42 +01:00
cgfhtw 1dcece8563 Use Factory for Phrasen 2024-03-06 16:52:10 +01:00
cgfhtw f2ebf25640 Use new FhcApiFactory Folder 2024-03-06 16:51:25 +01:00
cgfhtw f6427f57b8 Use FHCAPI Controller for Phrasen 2024-03-06 16:49:35 +01:00
cgfhtw 68459e086a Auth_Controller special permissions 2024-03-06 16:15:04 +01:00
Cris 03e166dc89 Merge branch 'master' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software
# Conflicts:
#	public/js/components/filter/Filter.js
#	public/js/plugin/FhcAlert.js
#	system/filtersupdate.php
2024-03-06 14:07:19 +01:00
Cris 0940ea77de Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-03-06 13:59:06 +01:00
cgfhtw 872ef7c31c Move Phrasen API 2024-03-06 13:02:34 +01:00
cgfhtw e89aa824d2 FHCAPI_Controller extends Auth_Controller + auth error handling in FhcApi 2024-03-06 11:48:15 +01:00
cgfhtw 1b65378d6c Auth_Controller private functions 2024-03-06 11:47:34 +01:00
Werner Masik 77666e5210 added column verantwortlich_uid 2024-03-06 08:27:39 +01:00
KarpAlex 1085b9243d Merge branch 'master' into feature-33003/BIS_Meldung_Personal 2024-03-05 17:07:17 +01:00
Harald Bamberger 3d6b2eb202 add app fhctemplate if it does not exist 2024-03-05 17:04:43 +01:00
Harald Bamberger 5ad3510af6 add use of phrasen plugin to apps 2024-03-05 16:47:29 +01:00
Harald Bamberger d5d190777a Merge branch 'feature-34543/UX_Template' 2024-03-05 16:46:48 +01:00
Cris 7f735e9a10 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-03-05 13:05:03 +01:00
Andreas Österreicher 7524d054db Merge branch 'feature-36530/bis_internationalisierung_codextabelle_neuerungen' 2024-03-05 13:04:25 +01:00
Andreas Österreicher 6869c147ef Beim deaktivieren von Benutzern wird Updateaktivam und Updateaktivvon
gesetzt
2024-03-05 11:32:30 +01:00
Werner Masik c60f7ed8b0 dbUpdate for fristenmanagement completed 2024-03-01 15:43:15 +01:00
Manfred e32d464b7f Merge branch 'master' into benutzerberechtigungGUIneu 2024-03-01 15:28:10 +01:00
Manfred 2e4f2709ed Merge branch 'RechteAnpassen' into benutzerberechtigungGUIneu 2024-03-01 15:27:11 +01:00
SimonGschnell 474c4ad34f removes file that belongs to CIS_Profil 2024-03-01 10:53:06 +01:00
Werner Masik 7a6d095b78 create db tables for fristenmanagement 2024-02-29 17:09:59 +01:00
kindlm 621429798c Abschlussgrad in Studienblatt erst aus Studienordnung ermitteln 2024-02-29 09:50:58 +01:00
cgfhtw 6500708f90 Code Quality 2024-02-29 09:02:20 +01:00
cgfhtw 2d2098984a Pause feature 2024-02-29 08:34:58 +01:00
Harald Bamberger c4d4f55d06 use tabulator5 simple theme to get smaller tables 2024-02-28 18:22:35 +01:00
Andreas Österreicher a4a06507dc Merge branch 'feature-229015/SAPByD_EBCL_Buchungen_sollen_auf_eigene_Kostenstelle_zugeordnet_werden' 2024-02-28 15:08:57 +01:00
Andreas Österreicher 23b1a76190 Merge branch 'feature-36148/tdb_uebersicht_erweitert_und_job_bug' 2024-02-28 13:43:19 +01:00
Cris f94b1700e7 Renamed filter- and phrases app for Fhc-Core-Extension
Renamed from extension to fhctemplate
2024-02-28 13:38:59 +01:00
Harald Bamberger 45f2593b13 fix bug with excel showing file error when switching to editmode 2024-02-27 13:54:58 +01:00
Andreas Österreicher e243980ae6 Merge branch 'master' into feature-18571/EntwicklungsteamBisMeldung 2024-02-26 15:58:49 +01:00
Andreas Österreicher 4862168b8d Merge branch 'feature-36986/fas_filter_reihungstest_dual' 2024-02-26 14:49:46 +01:00
Andreas Österreicher 93f1bc752b Merge branch 'feature-36744/uebersetzungen_payments_karteireiter' 2024-02-26 12:57:18 +01:00
cgfhtw 4bbac35540 Status colors 2024-02-26 11:56:29 +01:00
ma0048 aa6c5c50c2 - fas filter gefixt 2024-02-26 09:03:06 +01:00
Alexei Karpenko d9ec506c86 Codextabelle Mobilitaetsprogramm Neuerungen: changed name of some programs, set correct sichtbar and sichtbar_outgoing booleans 2024-02-23 16:54:51 +01:00
Cris 296741b584 Merge branch 'feature-34543/UX_Template' of https://github.com/FH-Complete/FHC-Core into feature-34543/UX_Template 2024-02-22 11:17:38 +01:00
Cris c232eddf89 Added filter and phrases for Fhc-Core-Extension 2024-02-22 11:17:27 +01:00
Werner Masik fff0e937cc added Method to end DV and deactivate Benutzer 2024-02-21 16:23:39 +01:00
SimonGschnell 2d1e8a829d userdata changes 2024-02-21 13:50:38 +01:00
cgfhtw c034efb8b0 Unterbrechung bei laufender Unterbrechung 2024-02-21 09:19:56 +01:00
ma0048 6f92698631 - bewerbungstool payments uebersetzungen anpassungen 2024-02-20 17:01:49 +01:00
Werner Masik cd64df28bb added phrase for habilitation 2024-02-20 15:02:14 +01:00
cgfhtw 72d166a050 FHCAPI Controller: multipart upload 2024-02-20 08:38:29 +01:00
KarpAlex dfe0434cce added new mobilitaetsprogramm codes 2024-02-19 17:59:20 +01:00
cgfhtw 013664db70 FhcApi Controller: new helper functions 2024-02-19 15:23:43 +01:00
cgfhtw 469b3e9833 Form Input: auto classes 2024-02-19 15:23:13 +01:00
cgfhtw 8ad2908ca9 UploadDms: Delete Button styles 2024-02-19 15:23:00 +01:00
cgfhtw 6aebbada06 Form Input: only setFeedback on last radio/checkbox in production mode 2024-02-19 10:39:18 +01:00
Andreas Österreicher e433ca3d9b Fehlende Gegenpruefungen im DB Check hinzugefuegt 2024-02-19 09:22:54 +01:00
Andreas Österreicher 7962e181df Merge branch 'feature-21620/Neues_Feld_zum_Erfassen_des_ESI' 2024-02-19 08:58:49 +01:00
Andreas Österreicher 126defadb7 Link hinzugefügt beim Zusammenlegen von Personen wenn beide Personen
UHSTAT ausgefüllt haben damit diese direkt verglichen und gelöscht
werden können.
Fehlende DB checks hinzugefügt
2024-02-16 14:59:53 +01:00
Andreas Österreicher 01c3a67762 Merge branch 'master' into feature-21620/Neues_Feld_zum_Erfassen_des_ESI 2024-02-16 14:11:02 +01:00
cgfhtw 658212a6eb Show Antrag to Student when finished 2024-02-16 13:28:26 +01:00
cgfhtw ab2fc11797 PDF Download Wiederholung Deadline 2024-02-16 11:44:27 +01:00
Andreas Österreicher cbf71a416f Deprecated Spalte Gesamtstunden aus Projektarbeitsexport entfernt 2024-02-16 11:23:20 +01:00
cgfhtw 75e05d6eed PDF Download korrektur 2024-02-16 09:27:42 +01:00
cgfhtw 70386a58f3 Tabs Component: removed TODOs 2024-02-16 08:53:34 +01:00
Cris caa7ad6cc4 Merge remote-tracking branch 'origin/feature-34543/UX_Template' into feature-34543/UX_Template 2024-02-15 09:54:51 +01:00
cgfhtw 3322f5115a FhcApi: Clean return value 2024-02-15 09:41:11 +01:00
cgfhtw f5b5f39689 FhcApi: return value 2024-02-14 16:00:48 +01:00
Cris 8f81426fa4 Corrected error when using alertMultiple and handleSystemMessage 2024-02-13 14:54:42 +01:00
cgfhtw 091d8509f0 Send E-Mails after Wiederholer deadline 2024-02-13 14:53:58 +01:00
Cris 6140e15139 Removed unused tabulatorAdditionalColumns property. Instead additional cols like 'action buttons' are now checked by index. 2024-02-13 14:53:01 +01:00
Cris acb29c5c69 Merge branch 'master' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software
# Conflicts:
#	application/views/templates/FHC-Footer.php
#	composer.json
#	public/js/components/Bootstrap/Modal.js
#	public/js/components/filter/Filter.js
#	public/js/plugin/FhcAlert.js
2024-02-13 11:54:55 +01:00
Cris 91f43665fd Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-02-13 10:54:14 +01:00
Cris 4d8dbb2e78 Created Core BaseLayout Component 2024-02-13 10:52:11 +01:00
Cris 565f89c884 Added phrases anrechnung, geloescht and aenderungGespeichert 2024-02-13 10:51:37 +01:00
Cris e6774024b9 Merge branch 'feature-34543/UX_Template' of https://github.com/FH-Complete/FHC-Core into feature-34543/UX_Template 2024-02-12 11:25:07 +01:00
Andreas Österreicher b4d6a46426 Fixed Typo in phrase 2024-02-09 15:18:14 +01:00
Andreas Österreicher bffaea8dda Merge branch 'feature-36028/uebersetzungen_zahlungen' 2024-02-09 12:50:45 +01:00
Andreas Österreicher f5dacefbbe Merge branch 'master' into feature-36028/uebersetzungen_zahlungen 2024-02-09 12:50:00 +01:00
Andreas Österreicher 752408aa3a Fixed LineEndings 2024-02-09 12:49:14 +01:00
Andreas Österreicher e34ff8819c Merge branch 'feature-33981/testtool_text_kopieren_verhindern_erschweren' 2024-02-09 11:11:41 +01:00
cgfhtw ce9ebee57d CSS: fhc-header w/o bottom border 2024-02-09 11:10:03 +01:00
Andreas Österreicher 0a8a17e49f Merge branch 'feature-36197/reihungstest_auswertung_bewerberstatus_setzen' 2024-02-09 10:48:51 +01:00
cgfhtw 8c6c2b7e11 FilterCmpt: defaults & Bugfix 2024-02-09 09:32:02 +01:00
cgfhtw 6e85b37b0f Tabs: optional border 2024-02-09 09:31:26 +01:00
cgfhtw c3ec909448 CSS improvements 2024-02-09 09:30:59 +01:00
Manfred ba972c1d8a Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-02-08 16:36:52 +01:00
Manfred ddfe0843de Defaultwert "aggregators "aus Statistik entfernt, weil Fehler wenn leer 2024-02-08 16:36:45 +01:00
Harald Bamberger 5279a7d45a Merge branch 'feature-35768/Studstatus_Status_Abgebrochen_fuer_Wiederholerdeadline_verwenden' 2024-02-08 08:48:26 +01:00
Harald Bamberger 7dfb0429ae Merge branch 'master' into feature-35768/Studstatus_Status_Abgebrochen_fuer_Wiederholerdeadline_verwenden 2024-02-08 08:25:11 +01:00
Harald Bamberger f67a106357 Merge branch 'feature-35637/Studstatus-Wiederholungsdeadline_abbrecher_status_current_semester' 2024-02-08 08:15:19 +01:00
Andreas Österreicher 1d300a604f Funktion zum Migrieren der Habiliation hinzugefügt 2024-02-08 08:03:34 +01:00
Andreas Österreicher 912f62dc01 Merge branch 'master' into feature-33003/BIS_Meldung_Personal 2024-02-08 08:03:00 +01:00
Harald Bamberger 32ed034ad2 Merge branch 'master' into feature-35637/Studstatus-Wiederholungsdeadline_abbrecher_status_current_semester 2024-02-08 08:00:22 +01:00
kindlm 36d4879b90 Hinweistext für Lehrauftragsannahme ergänzt 2024-02-07 16:35:21 +01:00
Cris bc0f7f7087 Merge branch 'feature-34543/UX_Template' of https://github.com/FH-Complete/FHC-Core into feature-34543/UX_Template 2024-02-07 15:50:50 +01:00
kindlm 72197bf993 Merge branch 'master' into RechteAnpassen 2024-02-07 12:58:43 +01:00
kindlm e01d97849a Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-02-07 12:58:13 +01:00
cgfhtw 2f79ae1ece Form/Validation bugfix: dismiss cache problem (correct solution) 2024-02-07 09:19:19 +01:00
cgfhtw a2c5ebb291 Fhc.css: fhc-header 2024-02-07 09:13:21 +01:00
cgfhtw 1f3e283d3c Code cleanup 2024-02-07 09:12:47 +01:00
cgfhtw eb69f77113 Form/Validation bugfix: dismiss cache problem 2024-02-07 09:12:06 +01:00
cgfhtw 6bc6c7c074 Form/Input: Injection defaults 2024-02-07 09:11:20 +01:00
Andreas Österreicher 3b97d8d93f Merge branch 'bug-36275/vertrag_oezuordnung' 2024-02-06 12:42:44 +01:00
Andreas Österreicher 1b70d70edd - Pruefung hinzugefuegt ob eine Person Vorgesetzte oder indirekt
Vorgesetzte einer anderen Person ist
- Bei mehreren OEZuordnungen wird bevorzugt die nicht karenzierte
  ermittelt
2024-02-06 12:40:11 +01:00
Andreas Österreicher b5024b86ea OEZuordnung wird priorisiert ermittelt bei Karenzen 2024-02-05 18:54:33 +01:00
kindlm 238208f252 Zeitwünsche mit mitarbeiter/zeitwuensche einsehen 2024-02-05 16:39:53 +01:00
KarpAlex 1c2c12f0a5 Bismeldestichtag Model: added getByStudiensemester method 2024-02-02 18:41:18 +01:00
cgfhtw dfbd67c52b Form/Input: Multiple radios/checkboxes 2024-02-01 15:43:36 +01:00
cgfhtw fe798506a6 raw_input_stream as array instead of stdobj & terminateWithSuccess 2024-02-01 08:59:35 +01:00
cgfhtw 51e556a731 Remove textarea+ & Form.send()
Add $clearValidationForName()
2024-02-01 08:58:32 +01:00
Andreas Österreicher a193a7a1c8 Naming Convention korrigiert fuer DBUpdate File 2024-02-01 08:50:06 +01:00
Andreas Österreicher 53fc8fc807 Berechtigungen für Entwicklungsteam ins Studiengangsverwaltungs Addon
verschoben
2024-02-01 08:38:55 +01:00
Andreas Österreicher ef64aa7da2 - Fehler behoben wodurch Entwicklugnsteam nicht gespeichert werden konnte
wenn das Endedatum leer ist.
- Entwicklungsteam update aus alten DB-Update entfernt
2024-02-01 08:20:10 +01:00
kindlm ac9b36cc1a Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-01-31 16:02:41 +01:00
kindlm 1b3c509ee8 Rechte in Rollen kopieren 2024-01-31 16:02:29 +01:00
Andreas Österreicher fae185958b Merge branch 'master' into feature-18571/EntwicklungsteamBisMeldung 2024-01-31 13:27:58 +01:00
Cris 02f0c54f10 Adapted Filter.js to ensure displaying tabulator 'formatter' columns not provided by filtersupdate filter definition
...like rowSelection checkboxes or custom formatted action buttons
2024-01-31 13:25:44 +01:00
Andreas Österreicher 559835becd Merge branch 'feature-35653/personensuche_deaktivieren' 2024-01-31 12:50:30 +01:00
Andreas Österreicher 603ef170ba Merge branch 'feature-34728/notenauswahl_im_fas_deaktivierte_noten_durchstreichen' 2024-01-31 12:33:02 +01:00
Andreas Österreicher cd7478539d Merge branch 'master' into feature-34728/notenauswahl_im_fas_deaktivierte_noten_durchstreichen 2024-01-31 12:29:23 +01:00
ma0048 ef3c680e91 - auswertung_fhtw funktionen "Zu Bewerber machen" entfernt 2024-01-31 12:28:03 +01:00
cgfhtw 2dbdf41086 FHC-Api: finetuning 2024-01-31 09:39:51 +01:00
Cris 7e14fff7f3 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-01-30 17:18:55 +01:00
Cris 6bd834c509 Added filter AnrechnungTable (for testing) 2024-01-30 17:05:03 +01:00
Cris aa06a97eb3 Corrected alertMultiple to display all messages
Before it stucked with only the first message. Now all messages are displayed.
2024-01-30 17:04:02 +01:00
Cris b868024175 Corrected wrong variable name in FhcAlert handleSystemMessage 2024-01-30 17:00:49 +01:00
Andreas Österreicher bea14724b0 Phrasen für Anrechnungen korrigiert 2024-01-30 16:56:19 +01:00
cgfhtw ef3ee76fa1 Form Validation 2024-01-30 11:39:17 +01:00
cgfhtw 272c4d5ccc FhcApi cleanup 2024-01-30 11:39:08 +01:00
cgfhtw 30bd6ea6a4 FhcApi Plugin + Form updates 2024-01-30 10:42:48 +01:00
cgfhtw b010cbb35d FhcAlert: CSS 2024-01-30 10:42:12 +01:00
cgfhtw ea9e58a640 Bugfix: Typo 2024-01-30 10:41:45 +01:00
ma0048 5e99ff9c8b - uebersicht erweitert
- job angepasst
2024-01-29 14:29:39 +01:00
Andreas Österreicher 1d779feb4b Merge branch 'feature-35202/internationalisierungsmassnahmen_wording_anpassen_fuer_akzeptieren' 2024-01-26 10:50:59 +01:00
cgfhtw 1fec3543cd FHCAPI Controller 2024-01-25 16:41:05 +01:00
ma0048 cd37972cad - ubersetzuengen hinzugefuegt 2024-01-25 12:54:57 +01:00
Harald Bamberger cf40f33fc6 prevent returning html entities in sanitizeProblemChars helper 2024-01-25 12:44:20 +01:00
Harald Bamberger 72bcb919aa prevent returning html entities in sanitizeProblemChars helper 2024-01-25 12:41:32 +01:00
Cris 4706b16a99 Merge branch 'feature-34543/UX_Template' of https://github.com/FH-Complete/FHC-Core into feature-34543/UX_Template 2024-01-25 10:40:09 +01:00
cgfhtw afc995b4bd Form Input modelValue dummy 2024-01-25 10:29:19 +01:00
Andreas Österreicher 70303dbec6 CI Environment im CIS Config hinzugefügt 2024-01-25 10:19:40 +01:00
Andreas Österreicher 89f5613373 Fehler behoben wodurch die Homeoffice Checkbox nicht angezeigt wurde
wenn die Person keinen Projekten zugeordnet ist
Fehler behoben wodurch die Homeoffice Checkbox am ersten Tag der
Homeofficegültigkeit nicht
korrekt angezeigt wurde
2024-01-24 07:02:28 +01:00
Harald Bamberger 7d4bc9c1d0 change => to >= in sql comparison 2024-01-23 14:21:04 +01:00
Cris 693d59e8bc Merge branch 'feature-34543/UX_Template' of https://github.com/FH-Complete/FHC-Core into feature-34543/UX_Template 2024-01-23 09:57:51 +01:00
cgfhtw e2a66d5143 Fragment Component 2024-01-23 09:43:41 +01:00
cgfhtw 41e5c52d2f Css updates 2024-01-23 09:42:33 +01:00
cgfhtw be82d9b6cb Tabs Component update 2024-01-23 09:32:26 +01:00
cgfhtw d66a6567b0 Form Components 2024-01-23 09:29:47 +01:00
Harald Bamberger e90f0c75fa fix missing entries due to missing prestudentstatus for target semester 2024-01-22 13:47:35 +01:00
Harald Bamberger a3a28a428c Merge branch 'feature-35636/Studstatus-Leitung_AntragId_sort_by_number' 2024-01-22 12:54:39 +01:00
Andreas Österreicher 3b85729b6f Syntaxfehler und Styling korrigiert 2024-01-19 15:27:04 +01:00
cgfhtw 1b27dbcb5f Bugfix: WH Antrag Prüfungstest kleiner vs kleiner gleich 2024-01-19 13:17:41 +01:00
kindlm 363ec9aa2f Merge branch 'master' into benutzerberechtigungGUIneu 2024-01-18 20:33:42 +01:00
kindlm 146b62d185 Filter in GET-Parameter 2024-01-18 20:33:03 +01:00
kindlm f298814619 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-01-18 20:31:31 +01:00
Werner Masik 304caf9157 added time recording query 2024-01-18 12:30:35 +01:00
Cris af010a51e9 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-01-17 11:33:54 +01:00
Andreas Österreicher 125a0174b9 Berechtigung für Web User zu Freitextbestandteilen hinzgefügt damit die Zeitaufzeichnung auf
AllIn prüfen kann
2024-01-17 07:41:17 +01:00
Andreas Österreicher c7e86950f4 FreierDV auf Darunterliegenden externerLehrender geändert da freierdv
nicht zu einem Dienstverhaeltnis zugeordnet werden soll
2024-01-17 07:36:28 +01:00
Andreas Österreicher 69e6c4ca29 Fehler beim Laden von Reports mit mehreren Variablen behoben 2024-01-16 17:01:09 +01:00
Harald Bamberger 6c95e31bae remove files moved to FHC-Core-Personalverwaltung Extension 2024-01-16 11:52:13 +01:00
Harald Bamberger 9552077209 Merge branch 'deploy-PV21' 2024-01-16 11:36:57 +01:00
Harald Bamberger 514ac2050f Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into deploy-PV21 2024-01-15 18:18:35 +01:00
Harald Bamberger 34a083d0ee update Logik beim Beenden von DVs verwenden 2024-01-15 18:16:54 +01:00
ma0048 a2905c3e93 - scheduler angepasst
- config erweitert um mahnsperre und zahlungsbedingungen
- fas config hinzugefuegt
2024-01-15 12:25:34 +01:00
ma0048 a9bae3f17d - zgv class erweitert um nur aktive zu holen 2024-01-15 11:58:10 +01:00
Harald Bamberger bed5a62d82 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into deploy-PV21 2024-01-15 11:23:11 +01:00
Harald Bamberger 7b9bfd70c8 make name of enc key more specific 2024-01-15 10:39:54 +01:00
Harald Bamberger 3b952b3838 Merge branch 'feature-25563/PV21_Verschlüsselung_Gehaltsdaten' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-15 10:36:34 +01:00
Cris 579c1c6aff Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2024-01-15 10:28:10 +01:00
Harald Bamberger 45c5b4fd37 Merge branch 'deploy-PV21' of github.com:FH-Complete/FHC-Core into deploy-PV21 2024-01-12 16:17:06 +01:00
Harald Bamberger 57af22a623 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into deploy-PV21 2024-01-12 16:16:56 +01:00
Harald Bamberger d95e972e6c Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' of github.com:FH-Complete/FHC-Core into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-12 16:15:15 +01:00
Harald Bamberger 8824ffd182 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-12 16:14:40 +01:00
Harald Bamberger 81244a06ca antrag_prestudentstatus_whitelist_abmeldung damit Unterbrecher sich auch abmelden koennen 2024-01-12 16:13:19 +01:00
Harald Bamberger 8d5cb39a3d Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into deploy-PV21 2024-01-12 14:57:01 +01:00
Harald Bamberger a49394f456 fix sql 2024-01-12 14:47:40 +01:00
Harald Bamberger 5a2ddbe2b2 use new hr tables depending on config DIENSTVERHAELTNIS_SUPPORT 2024-01-12 14:44:26 +01:00
Harald Bamberger fc89224dc8 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into deploy-PV21 2024-01-11 09:46:30 +01:00
cgfhtw 0f06c8a386 s&d 2024-01-11 08:34:10 +01:00
cgfhtw 13b5b017b8 Expose Antrag Id 2024-01-11 08:34:00 +01:00
cgfhtw 981f6970bc Status severity for "Abgemeldet" 2024-01-11 08:33:43 +01:00
Cris f40862c019 Merge remote-tracking branch 'origin/feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-10 17:16:32 +01:00
Harald Bamberger 7f4ae3a378 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into deploy-PV21 2024-01-10 15:01:48 +01:00
Harald Bamberger d5f6ee2265 improve search to handle multiword search 2024-01-10 15:00:16 +01:00
Cris 73ba14cdec Removed unused function check_isVorgesetzter
This was replaced by using getVorgesetzer / getVorgesetzterByDate method.
2024-01-10 14:44:33 +01:00
Cris e3f10069ef Adapted getUntergebene to allow to include also Mitarbeiter, who ended Dienstverhältnis/changed OE last month
These allows Vorgesetzte to still access their data, for example to be able to accept their November-Monatsliste (last working month)
in December (month to accept the November-Monatsliste)
2024-01-10 14:42:13 +01:00
Harald Bamberger 37493d1af7 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into deploy-PV21 2024-01-10 14:40:18 +01:00
Cris 97a020460d Adapted: getVorgesetzteByDate to retrieve only the latest Vorgesetzte by a specific date
Added order by and limit to get only one and the most actual Vorgesetzte by given date.
Changed name. Before it was getVorgesetzteMonatTimesheet, but it is also used independently from timesheet.
2024-01-10 14:31:26 +01:00
Cris 5452dc6fe3 Adapted: getVorgesetzte retrieve only the latest Vorgesetzte
Added order by and limit to get only one and the most actual Vorgesetzte
2024-01-10 14:29:16 +01:00
Harald Bamberger 36f97bafd6 Merge branch 'feature-30659/SearchBar_Controller_sollte_Berechtigungen_berücksichtigen_können' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-10 14:19:37 +01:00
Harald Bamberger dff97f7c53 Merge branch 'feature-34874/pv21_fas_stundensaetze' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-10 14:18:25 +01:00
Harald Bamberger 49d24d74b0 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-10 13:54:06 +01:00
cgfhtw e907c0b596 Studstatus: use current semester in WiederholerDeadline Job 2024-01-09 15:05:05 +01:00
cgfhtw 2faf310105 Studstatus: Leitungsansicht Sortierung AntragId 2024-01-09 13:40:48 +01:00
ma0048 125bf40fd1 - personensuche im cis ueber die globale suche mithilfe einer config deaktivierbar
- vereinfachte logik fuer die profi link anzeige ueber die globale suche
2024-01-09 12:00:11 +01:00
Harald Bamberger 64279bace2 change function type from volatile to stable for public.get_rolle_prestudent 2024-01-09 09:40:56 +01:00
Harald Bamberger fde1623dc0 Merge branch 'feature-35545/Studstatus_Status_Abgemeldet' 2024-01-08 18:23:10 +01:00
Harald Bamberger 3687f63189 Merge branch 'feature-35411/Studstatus_Query_Performance' 2024-01-08 17:42:20 +01:00
Cris d522389f76 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' of https://github.com/FH-Complete/FHC-Core into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2024-01-08 11:47:17 +01:00
cgfhtw 5b62271711 s&d 2024-01-02 09:36:28 +01:00
Werner Masik 9460d2b2cd removed reactivity warning 'Vue received a Component that was made a reactive object' 2023-12-29 17:09:38 +01:00
cgfhtw 43813b3ef0 getActiveStgs 2023-12-27 10:51:57 +01:00
cgfhtw aa5868826f getAntraege 2023-12-27 10:26:42 +01:00
KarpAlex 2c16e293a0 Merge branch 'master' into feature-33003/BIS_Meldung_Personal 2023-12-24 00:00:27 +01:00
KarpAlex 3e7d917184 deleted anrechnung von outgoing lvs file in dbupdate folder 2023-12-22 19:07:15 +01:00
cgfhtw f03d218872 s&d 2023-12-22 14:49:40 +01:00
Harald Bamberger 151012fedf AntragJob: nur Personen die eine Aufforderung oder einen Reminder zur Wiederholung erhalten haben und die Frist abgelaufen ist zum Abbrecher machen 2023-12-22 11:08:56 +01:00
ma0068 e7703f3c9b neues Attribut abschlussbeurteilung_deutsch 2023-12-22 07:55:29 +01:00
Andreas Österreicher 1530726b0a Merge branch 'feature-20037/reihungstestjob_neue_studienplaene_werden_nicht_korrekt_zugeordnet' 2023-12-21 15:44:58 +01:00
ma0048 250434b806 Merge remote-tracking branch 'origin/master' into feature-20037/reihungstestjob_neue_studienplaene_werden_nicht_korrekt_zugeordnet 2023-12-21 15:41:28 +01:00
Harald Bamberger dcc0093987 sachaufwand_id_seq rechte fuer vilesci user 2023-12-21 14:49:50 +01:00
Harald Bamberger 52b1598ab4 zusaetzlicher Teilzeittyp Wiedereingliederungsteilzeit 2023-12-21 14:44:07 +01:00
Andreas Österreicher 2e742a7913 Merge branch 'feature-29144/Prestudent_status_nach_Bismeldung_sperren_2' 2023-12-21 13:29:02 +01:00
Harald Bamberger 5bfa8ca53c Merge branch 'feature-35066/Studstatus_divers' 2023-12-20 19:57:33 +01:00
ma0048 ef117fbe12 - neue vorlage beim akzeptieren
- neuer filter
- button "alle geplanten markieren"
2023-12-20 16:02:44 +01:00
Harald Bamberger 60ad46b2fb and another dependency of Tabs 2023-12-20 15:24:56 +01:00
Harald Bamberger 2a9181d28d add another dependency of Tabs 2023-12-20 15:20:06 +01:00
Harald Bamberger 1aa6d07559 add dependency for Tabs 2023-12-20 15:09:49 +01:00
Harald Bamberger d9cd3a0b1d add files for manipulating tabs from feature-30660 2023-12-20 14:30:11 +01:00
Andreas Österreicher 29d7a97ee8 Wording korrigiert 2023-12-20 14:26:30 +01:00
Andreas Österreicher 20f9f52eef Doppelten Composer Eintrag entfernt 2023-12-20 14:11:49 +01:00
Andreas Österreicher 72217d9793 Merge branch 'master' into feature-29144/Prestudent_status_nach_Bismeldung_sperren_2 2023-12-20 14:06:18 +01:00
Andreas Österreicher c400e112fd Merge branch 'feature-35007/Text_zu_UHSTAT_Formular_hinzufuegen' 2023-12-20 13:43:23 +01:00
cgfhtw 3f88bba9bb Negative Prüfungen sortiert und bei bestehenden Anträgen nach Antragsdatum und Stdsem gefiltert 2023-12-20 12:06:45 +01:00
cgfhtw ca55b63e01 Load Language before Anträge 2023-12-20 09:30:44 +01:00
cgfhtw ba7f60b16e Filter Beschriftung 2023-12-20 09:18:44 +01:00
cgfhtw 6c0fa3fed3 Leitungsansicht: Aktiv Default & korrekter Filter beim Neuladen der Seite 2023-12-20 09:14:58 +01:00
Harald Bamberger a02e79a33a fix sancho mail template kurzbz too long 2023-12-19 18:14:08 +01:00
KarpAlex 8b9c023781 Personen zusammenlegen: Rueckstellungen are checked 2023-12-18 17:51:05 +01:00
KarpAlex e60157dd9b Personen zusammenlegen: uhstat1daten are checked 2023-12-18 17:16:20 +01:00
KarpAlex f6e7d2858a Merge branch 'master' into feature-21620/Neues_Feld_zum_Erfassen_des_ESI 2023-12-18 17:01:25 +01:00
cgfhtw f4194c251a loadActiveForStudiengaenge eigene Funktion 2023-12-18 14:27:32 +01:00
cgfhtw d8dc19ef2f Merge branch 'master' into feature-35066/Studstatus_divers 2023-12-18 14:19:50 +01:00
Andreas Österreicher 7868c2e073 Merge branch 'feature-35019/visual_library_abgabetool_nutzungsbedingungen_fuer_epub' 2023-12-18 13:32:41 +01:00
ma0048 55fbf40374 - abgabetool text anpassungen
- nutzungsbedingungen
- delay config hinzugefuegt
- required inputs hinzugefuegt
2023-12-18 09:20:01 +01:00
cgfhtw e698564202 StudStatus: Toggle "nur aktive anzeigen" 2023-12-14 11:28:19 +01:00
Cris 00a1c66d86 Corrected: Tagesgenaue Prüfung auf AZG-relevant 2023-12-13 16:14:08 +01:00
Harald Bamberger adc66695e4 Merge branch 'feature-34727/Studstatus_Studienplaene_w_multiple_languages' 2023-12-13 16:05:04 +01:00
Harald Bamberger 9e59caf7bc Merge branch 'master' into feature-34727/Studstatus_Studienplaene_w_multiple_languages 2023-12-13 15:10:21 +01:00
Cris bf20854878 Corrected: Tagesgenaue Prüfung auf Homeoffice 2023-12-13 14:09:20 +01:00
Andreas Österreicher a75234165b Merge branch 'hotfix_Anrechnungsantraege-in-zukuenftigen-Studiensemester-ermoeglichen' 2023-12-12 14:45:18 +01:00
Andreas Österreicher 18f88b7697 Merge branch 'infocenter_2023_12_04' 2023-12-12 13:27:05 +01:00
Andreas Österreicher 5c3f5b26d3 Composer Lock aktualisiert und neuen Config Eintrag für Zahlungstypen
hinzugefügt
2023-12-12 13:25:10 +01:00
cgfhtw 14c24005fe Wiederholung wenn Studierende das letze Semester wiederholen 2023-12-12 11:02:12 +01:00
Werner Masik 52cc0db5da phrases for off time view 2023-12-11 21:28:52 +01:00
ma0048 289358ac6e - inaktive noten durchgestrichen im fas 2023-12-11 13:46:18 +01:00
ma0048 8f46613620 - kopieren von fragen erschweren 2023-12-11 13:30:39 +01:00
Cris 1797abdc5f Merge remote-tracking branch 'origin/feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-12-11 13:22:58 +01:00
Cris bb9eb31e6e Adapted getWochenstunden in Vertragsbestandteil Class to handle Karenz
Karenzierte Dienstverhältnisse werden nicht zurückgegeben.
Dafür aber ein eventuelles 2.DV mit geringfügiger Beschäftigung neben der Karenz.
2023-12-11 13:11:33 +01:00
Cris a361036aa9 Added method isKarenziert to Vertragsbestandteil Class
Prüft, ob MitarbeiterIn zum Abfragedatum karenziert ist.
Wenn kein Datum übergeben wird, wird das heutige Datum gesetzt.
2023-12-11 13:09:56 +01:00
Cris 26ab9ff221 Updated 3 Vertragsbestandteil-Methods: Set 'Order By' to retrieve very last active Vertragsbestandteil 2023-12-11 13:08:57 +01:00
Harald Bamberger 28128ee35e Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-12-11 08:02:21 +01:00
Harald Bamberger 9fa7e6e56c modify label of Studiengaenge in Dropdown and Table 2023-12-07 17:12:38 +01:00
Harald Bamberger b6585dc186 add margin-right to prevent scrollbar from overlaying table 2023-12-07 16:05:52 +01:00
Harald Bamberger 85a743b43a Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-12-07 08:03:34 +01:00
kindlm a246513597 Spalte Organisationseinheit 2023-12-06 18:18:34 +01:00
Manfred a2e6927740 Merge branch 'master' into benutzerberechtigungGUIneu 2023-12-06 18:11:07 +01:00
kindlm 13092be05c Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2023-12-06 18:07:26 +01:00
kindlm c87ae7e74d Suche Person in OE; OE in Rechteliste OE-Suche 2023-12-06 18:06:46 +01:00
Manfred d35223c1a3 Merge branch 'master' into benutzerberechtigungGUIneu 2023-12-06 18:04:25 +01:00
Cris 8a29146fc2 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2023-12-06 14:42:45 +01:00
cgfhtw b15adf7b23 Revert "task-35010: Abmeldung d. StG Pre-Abbrecher Statusgrund nach zurückgezogen wieder rückgängig machen"
This reverts commit 3e9dcf2911.
2023-12-06 14:32:29 +01:00
cgfhtw b6b21d54fc Pre-Abbrecher Statusgrund nach zurückgezogen wieder rückgängig machen 2023-12-06 14:26:59 +01:00
Cris bd4a0af690 Removed 'Lehre Saldo anzeigen' 2023-12-06 13:31:06 +01:00
Cris f18aa42966 Added function getWochenstunden to Vertragsbestandteil Class 2023-12-06 13:24:52 +01:00
cgfhtw 3e9dcf2911 task-35010: Abmeldung d. StG Pre-Abbrecher Statusgrund nach zurückgezogen wieder rückgängig machen 2023-12-06 09:46:34 +01:00
kindlm 32459ccff8 Statistik Load TimeLimit auf 600 gesetzt
Default Parameter bei Statistik aktualisiert
2023-12-05 14:38:07 +01:00
cgfhtw 98de634393 s&d 2023-12-05 09:27:20 +01:00
Cris 83e3898b31 Merge branch 'feature-28269/Zeiterfassung-an-neue-Vertragsstruktur-anpassen' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-12-04 17:35:01 +01:00
Cris 7d701835cc Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' of https://github.com/FH-Complete/FHC-Core into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-12-04 17:34:19 +01:00
Cris 4552050c8a Changed: Allin Saldoanzeige an neue Vertragsstruktur angepasst 2023-12-04 17:30:10 +01:00
Cris b6b8f0d182 Removed unused require_once files 2023-12-04 17:25:43 +01:00
ma0048 f3be186c5a Merge branch 'feature-27398/Offene_Rechnungen_im_Bewerbungstool_anzeigen' into infocenter_2023_12_04 2023-12-04 12:46:16 +01:00
ma0048 ab5d0693eb Merge branch 'feature-16354/TinyMCE_move_to_new_version' into infocenter_2023_12_04
# Conflicts:
#	composer.lock
2023-12-04 12:44:10 +01:00
ma0048 a4417bdd98 Merge remote-tracking branch 'origin/feature-32978/bewerberstatus_cronjob_aktivieren' into infocenter_2023_12_04 2023-12-04 12:33:25 +01:00
ma0048 a8efe3c109 Merge remote-tracking branch 'origin/feature-33037/bewerbungstool_textanpassung' into infocenter_2023_12_04 2023-12-04 12:32:55 +01:00
ma0048 4ceca78ebc Merge remote-tracking branch 'origin/feature-33185/statusfilter_im_fas_fuer_neuen_bewerber_prozess' into infocenter_2023_12_04 2023-12-04 12:32:34 +01:00
ma0048 af1db47e1d Merge remote-tracking branch 'origin/feature-33250/messages_von_reihungstestverwaltungsseite_aus_schicken' into infocenter_2023_12_04 2023-12-04 12:29:43 +01:00
ma0048 fa80c49eba Merge remote-tracking branch 'origin/feature-33714/erhoehter_studienbeitrag_fuer_drittsaatenangehoerig' into infocenter_2023_12_04 2023-12-04 12:29:17 +01:00
Harald Bamberger 483b6171c7 add space between firstname and surname 2023-12-01 09:39:46 +01:00
Harald Bamberger 0e04138480 Merge branch 'feature-34998/Studierendenstatus_Mail_nicht_an_private_Adresse_schicken' 2023-11-30 15:04:10 +01:00
cgfhtw a3963248dd s&d 2023-11-29 14:37:35 +01:00
ma0048 ea14fa1a4b - infocenter kaution spalte angepasst
- infocenter abgewiesen nachricht spalte angepasst
2023-11-29 13:05:49 +01:00
Harald Bamberger 8b55a7843d altersteilzeit geblockt mit 0 Stunden zulassen 2023-11-29 07:33:38 +01:00
KarpAlex 734ab45264 UHSTAT form: added SVNR text 2023-11-29 01:06:42 +01:00
Cris 1310dea4a5 Changed Tabulators new-Button to btn-primary color 2023-11-28 18:55:14 +01:00
Cris be0e2a6dca Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2023-11-28 18:49:37 +01:00
Harald Bamberger ff302e6173 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-11-28 13:08:14 +01:00
Harald Bamberger 0f2f21aa19 Merge branch 'feature-34537/Phrasenmixin_als_Plugin' 2023-11-28 12:56:31 +01:00
Harald Bamberger bbd41f17cc use textarea instead of pre 2023-11-28 12:53:44 +01:00
Harald Bamberger a5d21b3b8d extend DV overlap check 2023-11-28 12:43:25 +01:00
Werner Masik a613abea39 fix kurzbz check 2023-11-28 12:18:13 +01:00
Harald Bamberger c123ad0578 Merge branch 'master' into feature-34537/Phrasenmixin_als_Plugin 2023-11-28 09:28:02 +01:00
ma0048 6b2d728143 - textänderung 2023-11-28 08:57:30 +01:00
cgfhtw a6f18ae424 Bugfix: parameter missing 2023-11-27 12:21:25 +01:00
Andreas Österreicher 71495877f3 Merge branch 'feature-29767/anpassung_abgabetool_fuer_vl' 2023-11-27 10:09:45 +01:00
Harald Bamberger b80df4f0eb refactor benutzerfunktion handling 2023-11-27 07:37:19 +01:00
Harald Bamberger 28e533fb3c replace pre with textarea to fix reason being overlapped by scroll bar 2023-11-23 17:53:43 +01:00
Harald Bamberger a1aff9bd0c Merge branch 'feature-34883/Studstatus_insertvon__bestaetigtvon_bei_Abbrechern' 2023-11-23 16:29:40 +01:00
Harald Bamberger 66cbe5199a correct phrasestext 2023-11-23 16:17:05 +01:00
Harald Bamberger b0d6212c5e Merge branch 'feature-34922/NeuerAbmeldungsgrundPhrase' 2023-11-23 16:06:54 +01:00
cgfhtw c93a4d2fb5 Studstatus: Wiederholer Reminder 1 wird vermutlich mit einem Tag delay versandt 2023-11-23 15:51:35 +01:00
cgfhtw 4932f21204 s&d 2023-11-23 15:37:01 +01:00
ma0068 2d25e08227 Longtext ZGV ohne Hinweis auf Ausbildungsvertrag 2023-11-23 09:45:29 +01:00
ma0048 801780de29 - wording 2023-11-23 09:24:34 +01:00
ma0068 d0bebeaa4a neue Phrase MissingZGV, entfernen new lines 2023-11-23 09:16:56 +01:00
Harald Bamberger 594dbdca21 Merge branch 'feature-34883/bestaetigtvon_bei_Abbrechern' 2023-11-22 17:08:20 +01:00
cgfhtw 8142982ac7 s&d 2023-11-22 14:57:24 +01:00
cgfhtw ca2256bb32 Fix: Better handling of uninitialized variables 2023-11-22 14:57:06 +01:00
Harald Bamberger ad8a18ed7d change lvzuweisungurl to use VILESCI_ROOT if defined for Sancho_Mail_Antrag_W_New 2023-11-22 13:08:47 +01:00
ma0048 cc589a401c - stundensaetze fas 2023-11-22 12:47:33 +01:00
Harald Bamberger 58fa399436 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-11-21 21:29:18 +01:00
Werner Masik cccdfa1ac8 extracted function for generation employee kurzbz 2023-11-21 17:45:20 +01:00
Andreas Österreicher d67d71abd5 Beträge am Lehrauftrag werden Abhängig von der Vertragsart angezeigt und nicht mehr
anhand der Inkludierten Lehre
2023-11-21 11:20:05 +01:00
cgfhtw 73e8761728 Bugfix: Lvzuweisung - DB Errors in production 2023-11-21 10:46:23 +01:00
Andreas Österreicher 5263ffbb7b Lehreinheiten Vorrückung berücksichtigt neue Vertragsstruktur und
Stundensätze
2023-11-21 09:53:00 +01:00
cgfhtw cc779f3d27 finish 2023-11-21 08:48:34 +01:00
ma0048 2158e7a28d - wording
- standardwert
- absage infocenter
2023-11-20 11:55:05 +01:00
Harald Bamberger 11926ca9b2 refactor creation of benutzerfunktiondata, add check for already used benutzerfunktionen in another vb 2023-11-20 09:19:32 +01:00
Andreas Österreicher 72210867a5 Suche an neue Vertragsstruktur angepasst und Feature-Toggle Config
hinzugefügt zum Umschalten zwischen alter und neuer Vertragsstruktur
2023-11-17 14:43:23 +01:00
Andreas Österreicher 9f2eeabdd1 BIS-Verwendung aus Lehrtaetigkeitsbestaetgung entfernt da nicht vewendet 2023-11-17 14:07:18 +01:00
Andreas Österreicher 66d8db7987 Berechtigung für Zugriff auf HR Schema für Web User hinzugefügt 2023-11-17 13:55:32 +01:00
cgfhtw a82df1058d Phrasen Plugin: async loadCategory function & use Vue.computed() 2023-11-16 15:23:40 +01:00
KarpAlex cf85cb084f dbupdate habilitation: added file to dbupdate3.4, code formatting 2023-11-15 20:51:44 +01:00
ma0068 9fdef54efc Funktion json2odt für newline Qualifikationsziele 2023-11-15 14:24:47 +01:00
ma0068 dc76ae8506 neue Tags addon_aktiv und lernergebnisse 2023-11-15 09:44:25 +01:00
Harald Bamberger f9cf1a5b32 change perstistenceID to force new settings in browser localstorage 2023-11-14 22:55:29 +01:00
Harald Bamberger b7c60fe1ef Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' of github.com:FH-Complete/FHC-Core into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-11-14 14:09:16 +01:00
Harald Bamberger 98eb3fbd8b exclude werkvertrag from overlap check 2023-11-14 14:09:06 +01:00
Andreas Österreicher 7f3b1417fd Neuen Gehaltstyp für Zusatzvereinbarung hinzugefügt
Anpassung am Gehaltsimport:
- All-In Bestandteile werden als Zulage importiert
- Zusatzvereinbarungen im neuem Typ Zusatzvereinbarung
- Import funktioniert jetzt auch für Personen die ihr DV nicht mit
  Monatsersten starten sondern ein paar Tage später
2023-11-14 13:37:03 +01:00
Harald Bamberger d6ce81462f Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' of github.com:FH-Complete/FHC-Core into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-11-14 10:36:25 +01:00
Harald Bamberger 7640d4024f alter handling of benutzerfunktion and vertragsbestandteilfunktion 2023-11-14 10:36:01 +01:00
ma0048 1b19c2c306 - feature-34579
- gehaltsabrechnung umbenannt
- historie uid hinzugefuegt
2023-11-13 14:21:35 +01:00
cgfhtw 5b2bfb9340 Code optimizing 2023-11-13 09:52:04 +01:00
Harald Bamberger f2208aa684 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-11-10 17:01:37 +01:00
Harald Bamberger 89c546f74f fix resize-handle in right column header 2023-11-10 15:29:50 +01:00
Harald Bamberger 18f36c9d23 update tabulator5 to version 5.5.2 to get better behaviour of frozen right column 2023-11-10 15:16:40 +01:00
cgfhtw cb009529af Mixin auf Plugin ändern 2023-11-10 14:46:18 +01:00
cgfhtw e56ccffe8d Bugfixes: Studstatus 2023-11-10 14:30:41 +01:00
cgfhtw 479d1a900f Orgform PDFs 2023-11-09 14:19:36 +01:00
Harald Bamberger 1d2a92f37f Merge branch 'feature-34545/Bug_StudStatus_Orgform_falsch' 2023-11-09 13:46:07 +01:00
cgfhtw 46855c9547 Blacklist für Noten 2023-11-09 13:37:56 +01:00
cgfhtw 85f178fcf3 remove var_dump 2023-11-09 13:26:54 +01:00
Cris 9111a10414 Changed Tabulators new-Button to btn-primary color 2023-11-09 12:25:44 +01:00
Cris 410dc022d4 Merge remote-tracking branch 'origin/feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-11-09 12:21:30 +01:00
Harald Bamberger 441a95de7e Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-11-09 12:12:26 +01:00
Harald Bamberger 4bfc26006b Merge branch 'feature-28886/Filter_Component_vs_Table_Component' 2023-11-09 11:48:51 +01:00
KarpAlex 3a8216577f added column habilitation to tbl_mitarbeiter 2023-11-09 10:53:04 +01:00
Harald Bamberger 95fa0cfbf6 change date handling benutzerfunktion 2023-11-08 11:57:57 +01:00
cgfhtw 05744f3921 Bugfix 2023-11-08 09:35:23 +01:00
Werner Masik 3b5f2e6494 added delete for Gehaltsabrechnung 2023-11-08 09:22:14 +01:00
Harald Bamberger 178a383c04 fix typo 2023-11-07 16:26:18 +01:00
Harald Bamberger e4a99b4c84 upgrade datepicker to version 7.2.0, change Dienstverhaeltnis class to honor checkoverlap flag 2023-11-07 11:04:39 +01:00
Werner Masik a806df72e8 increased REST TIMEOUT constant to 5000 2023-11-07 10:52:01 +01:00
Werner Masik 9c1cc947e6 removed superfluous library for multiselect 2023-11-07 10:46:38 +01:00
Werner Masik 624df81da1 add primevue multiselect 2023-11-07 10:33:37 +01:00
Andreas Österreicher fad475fb64 Fixed Loading Lehraufträge with Postgresql 15 2023-11-06 09:00:28 +01:00
ma0048 e0a2fba209 - erhoehte studiengebuehr hinzugefuegt & filter 2023-11-03 11:37:58 +01:00
ma0048 6e18d2ee2b - rt verwaltung message an prestudent 2023-11-03 11:22:27 +01:00
Harald Bamberger c7508d2b8c Merge branch 'master' of github.com:FH-Complete/FHC-Core 2023-11-02 16:50:06 +01:00
Harald Bamberger c12169557b rename vuepic/vue-datepicker to vuejs/vuedatepicker 2023-11-02 16:49:38 +01:00
Harald Bamberger 5a8a7d2401 add multiselect used by pv21 2023-11-02 08:19:33 +01:00
Harald Bamberger f956db5889 Merge branch 'feature-34495/LinkSammelmailStgl' 2023-10-31 13:34:57 +01:00
ma0068 8971f79a77 Verwendung von APP_ROOT 2023-10-31 13:23:56 +01:00
ma0068 fdb4eb5e7d Link Stgl Sammelmail 2023-10-31 13:16:25 +01:00
Cris f7ffbfb914 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' of https://github.com/FH-Complete/FHC-Core into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-10-31 13:01:41 +01:00
Cris d37a8f1357 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2023-10-31 12:58:03 +01:00
Andreas Österreicher ccace2f826 Fehler beim Laden der Lehrauftragsliste korrigiert mit Postgres15 2023-10-31 11:16:53 +01:00
Cris c494dd1cdc Added handleFormErrors- and resetFormErrors method to FhcAlert Plugin 2023-10-31 10:41:00 +01:00
Cris 5a002c0f04 Minor change: Adapted mail-text 2023-10-31 10:40:06 +01:00
Andreas Österreicher 2254aa3643 Merge branch 'bug-34481/infocenter_bug_rueckstellung' 2023-10-31 08:34:11 +01:00
ma0048 684a741f2a - bugfix 2023-10-31 08:33:10 +01:00
Harald Bamberger f53bca1ba6 Merge branch 'feature-33948/Studstatus_CSV_Export' 2023-10-27 10:47:10 +02:00
Harald Bamberger 2ed6f30bea Merge branch 'feature-33947/Studierendenantraege_SammelmailAnAssistenz' 2023-10-27 10:45:35 +02:00
Cris fbb00be7cd Added slot 'search' to Filterwidget.js
Slot to inject a autoselect / inputfield to search tabulator, if tabulator should stay empty until search results are provided. (Example: performance reasons if too many data; search for multiple at once)
2023-10-25 12:55:35 +02:00
Cris c6d82fe029 Minor style change of confirmDelete message 2023-10-25 12:49:37 +02:00
Cris 6b2150b066 Fixed: unknown 'fhcerror' to this 2023-10-25 12:48:00 +02:00
Cris 007ee49844 Merge branch 'feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' of https://github.com/FH-Complete/FHC-Core into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2023-10-24 15:51:10 +02:00
cgfhtw 73cbaf77f1 CSV Options adjusted for German MS Office 2023-10-24 14:16:13 +02:00
cgfhtw 22453c71b4 fhcAlert: slight improvements 2 2023-10-24 13:35:50 +02:00
cgfhtw d57fd9eb60 fhcAlert: slight improvements 2023-10-24 12:23:12 +02:00
ma0068 aead4f3380 Assistenz als CC zu SammelmailSTGL hinzugefügt 2023-10-24 10:44:17 +02:00
Harald Bamberger 05e2808f00 add Models for Vertragsbestandteiltyp and VertragsbestandteilFreitexttyp, implement IValidation Interface on AbstrcatBestandteil, add OverlapChecker checking for overlapping VBs against DB 2023-10-23 17:58:18 +02:00
KarpAlex c9331771b3 lock Prestudentstatus after Bismeldestichtag in FAS: possible to edit student with prestudentstatus check permission, all fields are greyed out when not editable, changed BIS-Meldestichtagsverwaltung menu point text 2023-10-23 16:39:33 +02:00
Andreas Österreicher dc496deadd Merge branch 'bug-33290/ZeitsperreEndeDatumFehlenderMaxwert' 2023-10-23 16:18:54 +02:00
Andreas Österreicher ecba22acfc Merge branch 'master' of github.com:FH-Complete/FHC-Core 2023-10-23 15:03:21 +02:00
Andreas Österreicher 01ca583167 Vertragsstunden werden auf 2 Nachkommastellen gerundet anstatt auf 1 2023-10-23 15:02:34 +02:00
ma0048 a1ee027ea4 - phrasen 2023-10-23 09:51:04 +02:00
Harald Bamberger 548a3e39b9 change label 2023-10-20 15:50:48 +02:00
Harald Bamberger 479df7189c add oetyp to oe and kst labels in search results 2023-10-19 16:38:15 +02:00
cgfhtw b01cd99a93 Plugin: Fhc Alert 2023-10-19 14:10:55 +02:00
Harald Bamberger eee6f918cd add oe_typ_kurzbz and oe_typ_bezeichnung to use in labels 2023-10-19 13:05:02 +02:00
ma0048 6a008fc5da - filter hinzugefuegt 2023-10-17 16:38:05 +02:00
Cris c0b4ad2633 Merge branch 'feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' of https://github.com/FH-Complete/FHC-Core into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2023-10-17 11:38:29 +02:00
Cris d85bbac19b Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2023-10-17 11:32:01 +02:00
Cris 0f80b9d31b Added Primevue-Toast and -Confirmdialog libraries to FHC-Footer 2023-10-17 11:30:35 +02:00
Harald Bamberger dcb308a535 change datum_von of benutzerfunktion if vb gueltig_ab is earlier 2023-10-13 16:45:30 +02:00
Andreas Österreicher 41a51ee286 Allin und Befristung wird mit Titel und Anmerkung migriert 2023-10-11 16:50:18 +02:00
Harald Bamberger 7042427110 fix sql _mitarbeiter_ohne_zuordnung 2023-10-11 16:11:19 +02:00
cgfhtw 56f26e6ebe Bugfix: FilterCmpt: reload function 2023-10-11 15:39:14 +02:00
cgfhtw c3b6a77dad switch visibility only for not frozen columns with title 2023-10-11 13:18:33 +02:00
cgfhtw 16fdb0de69 cleanup 2023-10-11 13:17:45 +02:00
cgfhtw 9db6874dc4 CSS for tabulator 2023-10-11 13:17:32 +02:00
Werner Masik 229d34d168 phrases update 2023-10-09 20:29:54 +02:00
Werner Masik 15225d0b03 added Benutzerfunktion CRUD methods 2023-10-09 20:29:54 +02:00
Werner Masik bf85534011 phrases update 2023-10-09 20:29:54 +02:00
Werner Masik 2298823f70 added phrarses for job functions 2023-10-09 20:29:54 +02:00
Harald Bamberger a4d0653c44 add IF NOT EXISTS to schema and extension creation 2023-10-09 15:49:59 +02:00
KarpAlex af678b3c56 added vue datepicker to composer 2023-10-09 14:29:38 +02:00
Harald Bamberger 2a72d48dea update composer.lock for php7.0 2023-10-09 11:48:50 +02:00
Harald Bamberger 4cc8b555d2 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-10-09 11:38:37 +02:00
ma0068 23aeba4620 Verwendung von datetime-funktionen anstelle von strtotime, Adaptierung config-eintrag, update Phrasen 2023-10-06 12:30:14 +02:00
ma0048 e30ad887c9 - msg an alle moeglich 2023-10-05 10:26:19 +02:00
Harald Bamberger c1171bc716 add user_language to FHC_JS_DATA_STORAGE_OBJECT 2023-10-04 12:20:44 +02:00
ma0048 6c8b3b4ec4 - nur an markierte msg moeglich 2023-10-02 14:12:03 +02:00
Werner Masik cc7067d8e5 updated phrases 2023-09-29 15:28:19 +02:00
ma0048 dc78660433 - fix for fas 2023-09-29 09:49:12 +02:00
ma0068 8fe72ebcf5 neues Element last_prestudentstatus for studienerfolg.xml 2023-09-28 16:47:44 +02:00
ma0068 f9af5638f5 Update Config: Format in Tagen für Validierung JS 2023-09-28 09:31:40 +02:00
KarpAlex 285af0a7f4 composer: updated datepicker 2023-09-27 13:52:31 +02:00
ma0048 2d963c92cc - msg aus rtverwaltung moeglich 2023-09-27 10:38:44 +02:00
ma0068 1809ff3008 accept days, weeks, month and years in config 2023-09-27 08:30:03 +02:00
Werner Masik 909fc896cd added phrases 2023-09-26 22:38:12 +02:00
Werner Masik 5827bde6b0 update phrasen 2023-09-26 15:27:50 +02:00
Werner Masik 822e269f88 add composable wrapper for phrasen mixin 2023-09-26 15:25:49 +02:00
Harald Bamberger f5bbc8a0c0 do not use category from window.FHC_JS_PHRASES_STORAGE_OBJECT since it is propably not complete 2023-09-26 15:11:16 +02:00
Harald Bamberger 67a61c5d2a add phrase to try vue Phrasen 2023-09-26 11:46:48 +02:00
Harald Bamberger f3809b01b2 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-09-26 11:14:47 +02:00
Harald Bamberger 5febccba8a port phrases mixin and Endpoint from branch feature-27351/Digitalisierung_Formulare_Neu 2023-09-26 11:12:15 +02:00
ma0068 be3e4e552b Adapt diffTageMax 2023-09-25 15:44:48 +02:00
ma0068 b1f3916e49 Adaptierung bismax-Validierung 2023-09-25 15:33:17 +02:00
ma0068 746ee76a3b Validierungen Von- und Bis-Felder vilesci 2023-09-25 15:11:14 +02:00
ma0068 f71b0e500e Adaptierung Berechnung diff 2023-09-25 14:15:33 +02:00
ma0068 9eeeeca62c Fix format 2023-09-25 09:54:49 +02:00
ma0068 9b11b19cf9 Zeitsperre: Maxwert bei Bisdatum 2023-09-22 13:33:54 +02:00
Cris 4e11e12c99 Removed aktiv column from SoftwareManagement Filter
Not used anymore.
2023-09-21 14:40:50 +02:00
Cris fa3a718ad4 Added getAutocompleteSuggestions method to OE Model
Get OEs by eventQuery string. Use with autocomplete event queries.
2023-09-21 14:40:05 +02:00
Harald Bamberger 9bfcbf3bf1 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-09-19 11:06:32 +02:00
Harald Bamberger cbe73ae37c Merge branch 'feature-31018/pv21_stundensaetze' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-09-19 10:42:11 +02:00
ma0068 cdb351b66b Delete Testdata and outputs 2023-09-18 10:37:14 +02:00
ma0048 91f3197c24 - added link option
- styling
2023-09-14 11:56:26 +02:00
Werner Masik 2c92ec3e60 added overlaypanel and datatable 2023-09-07 22:29:29 +02:00
ma0048 0e1f4148f5 - anpassungen fuer bewerberautofill 2023-09-07 14:34:20 +02:00
Andreas Österreicher 3e7abf9a45 Merge branch 'master' into feature-18571/EntwicklungsteamBisMeldung 2023-09-05 14:33:31 +02:00
ma0048 07deb7b6c5 - textanpassung 2023-09-04 13:34:42 +02:00
Werner Masik 799911b948 added method to fetch DV by ID 2023-08-17 16:14:53 +02:00
KarpAlex 8122ab0292 simplified error message for invalid status dates 2023-08-15 19:27:39 +02:00
ma0048 c4377010b1 - pv21 stundensaetze hinzugefuegt 2023-08-14 14:14:37 +02:00
KarpAlex 3ea74ab23c Bismeldestichtage GUI: improved datepicker, correct Studiensemester sort, insertamum is set when inserting 2023-08-10 23:15:44 +02:00
Cris e1c23fc6fa Added Filter ImageVerwaltung 2023-08-10 11:34:54 +02:00
Harald Bamberger 597e074bbd Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-08-09 11:13:02 +02:00
Cris b7a3d2dcb4 Removed column 'actions' from filtersupdate 2023-08-09 10:57:06 +02:00
Cris 49e4aa78e9 Merge branch 'feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' of https://github.com/FH-Complete/FHC-Core into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2023-08-09 10:43:57 +02:00
KarpAlex 4a2cdaf52a added primevue autocomplete 2023-08-04 14:46:53 +02:00
Cris 56230e3752 Changed button-color of Tabulators Header-'ADD Button' to primary color 2023-08-03 09:45:45 +02:00
Cris 4e17be39f6 Added column 'actions' to filtersupdate 2023-08-03 09:44:28 +02:00
KarpAlex 2f001987f3 Filter.js additional columns: additional columns are displayed based on field name, not title 2023-08-02 19:14:58 +02:00
KarpAlex 553f2feaa4 filter component: enabled nested tabulator 2023-08-02 16:22:10 +02:00
Cris b70011436e Added column 'softwarestatus_kurzbz' to filtersupdate 2023-08-02 13:39:47 +02:00
Harald Bamberger 8eeb0d9ca7 gehaltsbestandteillib set uid to pgsql 2023-08-01 14:37:07 +02:00
Harald Bamberger c8703d3215 write current uid to pgsql settings variable 2023-08-01 13:03:05 +02:00
Paolo 043a2538b7 Updated 2023-07-31 12:12:59 +02:00
Cris 44182af5fa Formatted Tabulator Header: Abstaende vergroessert
Abstand Titel zu Actionbuttons und zwischen Actionbuttons untereinander vergroessert
2023-07-31 09:30:45 +02:00
KarpAlex 459f068765 bismeldestichtag gui: added icon to delete button, added id field 2023-07-26 20:59:05 +02:00
Harald Bamberger 270c9e1741 remove hasSequence again to avoid error, check vbs basedata and specialdata if not empty before update 2023-07-26 19:23:31 +02:00
Harald Bamberger 3eaefc88bd set hasSequence correct 2023-07-26 18:40:37 +02:00
Harald Bamberger bbe1fe2d49 refactor markDirty check 2023-07-26 17:41:23 +02:00
Harald Bamberger 18e82225ce handle vertragsbestandteil_kurzbz different for insert and update 2023-07-26 17:28:37 +02:00
Harald Bamberger ac5d6071cd extend VerttragsbestandteilLib to keep track on modified columns and only update dv, vbs and gbs when they differ from the status in the db 2023-07-26 16:27:34 +02:00
Cris 1aae75312e Merge remote-tracking branch 'origin/feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2023-07-19 10:30:31 +02:00
KarpAlex d88ff104a3 filter component: added property tabulatorAdditionalColumns for displaying additional columns not in filter 2023-07-18 19:11:10 +02:00
Paolo 6a7903ef05 - Changed the controller components/SearchBar.php constructor to _not_ start the authentication when the AuthLib is loaded and to check if the user is logged
- Added constant ERROR_NOT_AUTH to libraries/SearchBarLib.php
2023-07-18 16:01:03 +02:00
KarpAlex c2962f51e1 Bismeldestichtag gui: added vue date picker 2023-07-17 21:03:51 +02:00
KarpAlex c6fee48c8c bismeldestichtage GUI: correct date format on row click 2023-07-17 12:31:45 +02:00
Paolo 88b01075c4 Merge branch 'master' into feature-25563/PV21_Verschlüsselung_Gehaltsdaten 2023-07-17 12:13:45 +02:00
KarpAlex 7ab5d3add6 Bismeldestichtage Management GUI: added row delete button 2023-07-17 12:11:15 +02:00
Paolo 75fb0f2d4a - include/filter.class.php -> loadValues now calls the superclass protected method replaceSQLDecryptionPassword to replace password variables with their values
- include/statistik.class.php -> loadData now calls the superclass protected method replaceSQLDecryptionPassword to replace password variables with their values
- Added new functions hasSQLDecryption and isSQLDecryptionValid to include/functions.inc.php
- Script vilesci/statistik/filter_details.php and vilesci/stammdaten/statistik_details.php now do not allow to store SQL strings that contain PostgreSQL decryption functions using a clear password
2023-07-17 12:06:37 +02:00
Paolo 2cc0283d25 Added new protected method replaceSQLDecryptionPassword to include/basis_db.class.php 2023-07-17 12:04:26 +02:00
ma0068 073cd6cb23 neue Tags für Anzeige Semester in Anrechnungen 2023-07-14 14:17:05 +02:00
Harald Bamberger 2b4a4d12a9 handle empty teilzeittyp_kurzbz 2023-07-13 15:08:51 +02:00
Harald Bamberger 545b9cb0de modify searchbar add category for employess without kst and oe assignment 2023-07-13 11:35:42 +02:00
ma0048 533291bf33 - bug fix
- neue sortierung
- neue spalte
- sqls abfragen angepasst
2023-07-11 14:17:51 +02:00
Harald Bamberger 02291a51e9 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-07-10 17:21:48 +02:00
Cris 0d690b60b6 Merge remote-tracking branch 'origin/feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2023-07-10 11:28:31 +02:00
KarpAlex b7a1add2f3 bismeldestichtage gui: removed filters, now just simple tabulator 2023-07-07 02:12:14 +02:00
KarpAlex 8a1de56dc2 Merge branch 'feature-28886/Filter_Component_vs_Table_Component' into feature-29144/Prestudent_status_nach_Bismeldung_sperren 2023-07-06 22:54:48 +02:00
KarpAlex 539efcb6ec added Modal.js to Bootstrap components 2023-07-06 12:03:38 +02:00
Harald Bamberger c81404b210 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-07-04 18:12:23 +02:00
Werner Masik 800b490c62 added function to get chart data 2023-07-04 18:10:00 +02:00
KarpAlex ddf72af139 Merge branch 'feature-28886/Filter_Component_vs_Table_Component' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2023-07-04 14:43:28 +02:00
cgfhtw 3798720ee0 +emit: click:new 2023-07-04 14:38:20 +02:00
Cris 06b929381d Merge remote-tracking branch 'origin/feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software
# Conflicts:
#	system/filtersupdate.php
2023-07-04 13:48:21 +02:00
KarpAlex fc147f577a filter.js: fix for nested tabulator: set columns before set data, filtersupdate: renamed columns 2023-07-04 12:17:15 +02:00
KarpAlex 388400338e Merge branch 'feature-28886/Filter_Component_vs_Table_Component' into feature-28575/Softwarebereitstellung_GUI_zur_Verwaltung_von_Software 2023-07-04 12:16:06 +02:00
cgfhtw 16356d8a5c reverse order setColumns & setData 2023-07-04 10:42:06 +02:00
Andreas Österreicher 51d8a18565 MigrateSalary Problem behoben wodurch das Ende eines Gehaltsbestandteils
nicht korrekt gesetzt wurde wenn mehrere DVs vorhanden sind
2023-07-04 10:30:59 +02:00
Andreas Österreicher ee7fe0251d - Script fuer den einmaligen Import der Gehaelter hinzugefuegt
- Migration der Vertraege angepasst damit alle Mitarbeiter auf einmal
  migriert werden koennen. Anpassung zur Unterscheidung der Zuordnung zum
Unternehmen
2023-07-03 18:32:34 +02:00
KarpAlex 71e86cfcde filter.js bugfixes: saving customfilter, and set columns before data (necessary e.g. for nested tabulator) 2023-07-03 11:45:15 +02:00
Cris 7356b17688 Added SW-ID column to SW-Table 2023-07-03 09:37:32 +02:00
KarpAlex f6661fabea bismeldestichtage GUI: added delete button again (for now...) 2023-06-30 13:33:52 +02:00
KarpAlex 74814db900 Bismeldestichtag Management: improved GUI layout, studiensemester is optional for "bismeldestichtag reached" check 2023-06-29 19:19:00 +02:00
KarpAlex 18d25069f3 tbl_bismeldestichtag: removed edit permissions for web user 2023-06-29 19:17:38 +02:00
KarpAlex 097010290d Merge branch 'master' into feature-29144/Prestudent_status_nach_Bismeldung_sperren 2023-06-29 11:47:56 +02:00
Harald Bamberger fb8172eda1 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-06-22 12:54:48 +02:00
Harald Bamberger 24a29ca565 add validation, use correct function names, add vertragsbestandteil_id to stdclass 2023-06-21 16:47:51 +02:00
Harald Bamberger 1ffab39f05 match naming of properties and db columns 2023-06-21 15:21:42 +02:00
KarpAlex f29d5a7b50 Bismeldestichtage management: added menu entry, changed size of filter widget table to auto 2023-06-17 21:00:52 +02:00
KarpAlex f0d0c0837a added Filter for Software Management 2023-06-17 20:51:33 +02:00
ma0048 d9eb0f5704 - kennzeichen beim zusammenlegen uebernehmen 2023-06-16 11:30:03 +02:00
KarpAlex f865d09033 manage Bismeldestichtage: added possibility to delete a report target date 2023-06-13 16:14:38 +02:00
ma0048 e26ba1d219 - spalte gesamtstunden erteilt hinzugefuegt 2023-06-12 09:22:32 +02:00
KarpAlex fe9bf1dc8a Bismeldestichtag: prestudentstatus is displayed as inaktive in FAS list if Stichtag is reached, fixed comments 2023-06-11 11:07:28 +02:00
KarpAlex e6b47266b9 Added GUI for adding Bismeldestichtag 2023-06-10 21:40:28 +02:00
KarpAlex f95c5ec7cf added overview for editing Bismeldestichtage 2023-06-07 19:25:23 +02:00
KarpAlex df64ad30eb Merge branch 'master' into feature-29144/Prestudent_status_nach_Bismeldung_sperren 2023-06-07 18:48:38 +02:00
KarpAlex dd98434522 added new right for editing bismelden property, disabled bismelden checkbox in FAS if no right 2023-06-07 13:33:43 +02:00
KarpAlex c490aa0040 Revert "hide bismelden checkbox if no keine_studstatuspruefung right"
This reverts commit ae1817fc7b.
2023-06-07 13:31:30 +02:00
Harald Bamberger b33f890c62 fix freitext anmerkung, add validation to vbfreitext 2023-06-07 07:59:12 +02:00
Harald Bamberger 3d2dd25755 add condition for ending vbs and gbs 2023-06-06 17:21:05 +02:00
Werner Masik bcdf29f57f added method to display rudimentary chart data 2023-06-06 16:25:04 +02:00
Harald Bamberger ff6ddf8c46 add methods to end dv 2023-06-06 16:24:49 +02:00
KarpAlex ae1817fc7b hide bismelden checkbox if no keine_studstatuspruefung right 2023-06-05 16:36:01 +02:00
Harald Bamberger 42a6dd7508 current composer.lock 2023-06-05 16:18:29 +02:00
Harald Bamberger 88039c2327 Merge branch 'werner/vertragsbestandteile_delete' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-06-05 10:58:39 +02:00
Werner Masik 5b7a78e6d8 delete DV; improved GBT query 2023-06-05 10:42:59 +02:00
Harald Bamberger dd0ef74fe0 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-06-05 10:42:52 +02:00
KarpAlex 42197c39ed FAS prestudents status: check is Meldestichtag is reached and disable input if it is, bismeldestichtag table: added sequence primary key 2023-06-03 15:18:06 +02:00
ma0048 afebd44b78 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core into feature-15490/lehrauftragsliste_stammkostenstelle_bei_fix_angestellten 2023-06-01 10:21:26 +02:00
ma0048 9f13f876ef - swd.php entfernt 2023-06-01 07:39:56 +02:00
ma0048 bf344df8d6 - abgabetool anpassungen 2023-06-01 07:12:40 +02:00
Harald Bamberger ec000fbf83 changes for aenderung and korrektur 2023-05-30 19:13:27 +02:00
KarpAlex 0a179c963f bismeldestichtag: added meldestichtag_id to table, created bismeldestichtag class, improved comment for prestudentstatuschecks in studentDBML 2023-05-25 16:35:44 +02:00
Harald Bamberger a47a746940 add require for vertragsbestandteil_karenz 2023-05-25 15:53:40 +02:00
Harald Bamberger 92672aaacf adapt overlapping DVs Check to not consider current DV if edited, but consider karenzen 2023-05-25 15:47:16 +02:00
Cris 4f6c60af3a Merge remote-tracking branch 'origin/feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-05-25 12:18:48 +02:00
Cris e7571dffab Minor Adaptation: Suche statt Search, Settings button Layout korrigiert 2023-05-25 12:17:06 +02:00
Cris f08072133c Fixed: Suchcontainer nicht mehr verschoben
Groesse und Alignment an Suchfeld gebunden.
2023-05-25 12:15:24 +02:00
Cris 542b6cc985 Adapted: Image-Thumbnails entfernt
Stattdessen class 'rounded'. Passt besser zu FHC CD.
2023-05-25 12:13:40 +02:00
Cris b9e9399ca2 Adapted: Icon-Layout in Vertical Split
. etwas vergroessert um besser mit der Maus zu greifen
. Icon und Icon-Farbe geaendert
2023-05-25 12:12:37 +02:00
Harald Bamberger fce192cd3c remover popper from composer.lock 2023-05-25 11:08:37 +02:00
Harald Bamberger 80d194cfc0 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter
- remove popper from composer introduced in branch feature-25562, but master included bootstrap.bundle in the meanwhile to have popper available
2023-05-25 11:04:20 +02:00
Harald Bamberger 38509d530a prepare list of vbs with gbs 2023-05-24 17:54:04 +02:00
cgfhtw be331d6200 Styles 2023-05-24 12:05:36 +02:00
KarpAlex f6f2defc8c Bismeldestichtag: added table 2023-05-23 18:48:18 +02:00
Werner Masik 5f198114f7 added popperjs because bootstrap5 requires it 2023-05-23 17:03:13 +02:00
cgfhtw 94a15093ac New Button 2023-05-23 15:26:49 +02:00
Cris 9124422635 Merge branch 'feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter' of https://github.com/FH-Complete/FHC-Core into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-05-23 15:17:14 +02:00
cgfhtw d10a229b59 Slot for action buttons 2023-05-23 14:56:31 +02:00
cgfhtw 429c595e04 Reload Button 2023-05-22 11:59:26 +02:00
cgfhtw 4154df1704 Property to Enable/disable the download button 2023-05-19 14:47:05 +02:00
Werner Masik 24bf2f95a2 update vertragsbestandteile 2023-05-16 17:05:49 +02:00
Werner Masik a198a740f4 fix json_serialize 2023-05-16 17:04:37 +02:00
cgfhtw 76fd425027 assert valid nw-new-entry listener if side-menu is enabled 2023-05-16 14:12:46 +02:00
cgfhtw 38f2bb89a4 readability 2023-05-16 10:40:58 +02:00
cgfhtw 1568e619a5 Split the component to improve the quality, readability and maintainability 2023-05-16 10:33:31 +02:00
cgfhtw 2b363119c5 Split the component to improve the quality, readability and maintainability 2023-05-16 10:33:05 +02:00
Werner Masik 3940912830 fix attribute name valorisieren to valorisierung 2023-05-16 10:04:56 +02:00
Werner Masik cd66397740 add current date to DV selection query 2023-05-16 10:03:50 +02:00
ma0068 01046637fa merge master into feature-18571/Entwicklungsteam 2023-05-11 09:18:32 +02:00
ma0068 fe6746e6bc Ergänzung DB-update um Berechtigung stgv/edit Entwicklungsteam 2023-05-11 09:14:42 +02:00
Werner Masik 4786ff503a added organisation to current contract info 2023-05-09 17:24:18 +02:00
Harald Bamberger 7045827450 bufix Urlaubsanspruch 2023-05-09 16:14:01 +02:00
Harald Bamberger d361c4eb26 use img-thumbnail css class instead of rounded circle 2023-05-05 15:47:23 +02:00
Harald Bamberger d131212d22 composer update 2023-05-05 14:20:07 +02:00
Harald Bamberger de4c236817 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-05-05 13:11:16 +02:00
Harald Bamberger 2c0e815fe8 add validations 2023-05-05 11:43:02 +02:00
Harald Bamberger 42ff682700 add validations 2023-05-05 08:20:29 +02:00
Harald Bamberger f84a75af4e Merge branch 'feature-25563/PV21_Verschlüsselung_Gehaltsdaten' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-05-04 15:41:44 +02:00
Paolo defe4e2f93 Added new interface application/core/IEncryption.php 2023-05-04 15:33:08 +02:00
Paolo 1c0129466a Bugfix: added a check to DB_Model->_addEncrypt method on the parameter encryptedColumns 2023-05-04 15:23:51 +02:00
Harald Bamberger e713cdac64 Merge branch 'feature-25563/PV21_Verschlüsselung_Gehaltsdaten' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-05-04 15:03:13 +02:00
Harald Bamberger 2f07590461 Merge branch 'master' into feature-25563/PV21_Verschlüsselung_Gehaltsdaten 2023-05-04 14:59:12 +02:00
Harald Bamberger 7fb0c14555 Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-05-04 14:58:29 +02:00
ma0048 4f03b61c6e - stunden bestandteil bei karenz mit 0 stunden verlaengern 2023-05-04 13:43:54 +02:00
Cris d2b6aab881 Changed: AZG-relvant an neue Vertragsstruktur angepasst 2023-05-04 09:42:30 +02:00
Cris 8e73638931 Changed: Check homeoffice an neue Vertragsstruktur angepasst 2023-05-04 09:41:50 +02:00
Cris dbee8d9689 Changed: Check homeoffice an neue Vertragsstruktur angepasst 2023-05-04 09:39:12 +02:00
Cris b43b7fe95d Added new Vertragsbestandteil Class and few methods
. load()
. isZAPflichtig() -- Check ob im übergebenen Monat ZApflichtig.
. getZAPflichtig() -- Holt alle Vertragsbestandteile, die ZApflichtig sind
. isAllin() -- Check, ob im übergebenen Monat Vertragsbestandteil AllIn hat.
2023-05-04 09:38:18 +02:00
Harald Bamberger eb7b73fee9 cleanup according to current vertragsbestandteil db tables 2023-05-02 16:00:13 +02:00
Harald Bamberger e3ec4cd5aa fix method names, handle insertamum updateamum insertvon updatevon in libs 2023-05-01 20:50:07 +02:00
Harald Bamberger b4e4f91b22 more validation 2023-04-25 20:20:02 +02:00
Harald Bamberger 10fb68a532 Dienstverhaeltnis Class updated, VertragsbestandteilLib can save Dienstverhaeltnis 2023-04-25 17:23:57 +02:00
Paolo 08de013c23 Fixes: code quality checks 2023-04-25 16:07:42 +02:00
Harald Bamberger 7a4f55bb0c require interface IValidation 2023-04-25 09:27:40 +02:00
Harald Bamberger 2163ddcdf5 add Interface IValidation, implement validate stub in all Vertragsbestandteile and Gehaltsbestandteil and DV 2023-04-25 09:22:03 +02:00
Paolo 39137d1348 Load a model in the filter component controller to have the DB functionalities ready 2023-04-24 17:07:40 +02:00
Andreas Österreicher b726f2ca5e Vertragsstunden mit 0.00 werden wie NULL behandelt 2023-04-24 07:14:42 +02:00
ma0048 f54351c7a3 - added missing model 2023-04-20 16:38:56 +02:00
Werner Masik 138cfd662d added return 2023-04-18 13:50:07 +02:00
Harald Bamberger 535578c399 validation 2023-04-18 13:30:56 +02:00
Harald Bamberger c90da4b50e start to implement validation 2023-04-18 13:26:08 +02:00
Werner Masik 29485a090b removed remaining unit test for GUI 2023-04-14 15:51:58 +02:00
Harald Bamberger e462a71b6d call parent constructor 2023-04-12 16:50:00 +02:00
Harald Bamberger 9e6d78dd1d set Dienstverhaeltnis_id and Vertragsbestandteil_id on child Gehaltsbestandteile when added or changed 2023-04-12 16:26:55 +02:00
Harald Bamberger c2e956f7f3 use GehaltsbestandteilLib in VertragsbestandteilLib 2023-04-12 15:32:22 +02:00
Harald Bamberger 0061cf255c add GehaltsbestandteilLib 2023-04-12 15:22:10 +02:00
Werner Masik 2b03fcc930 removed GUI handling and renamed Gehaltsbestandteil to make it independend from Vertragsbestandteil 2023-04-12 09:41:07 +02:00
ma0068 f1402c439c Adaptierungen Rahmenvertrag FHG 2023-04-12 08:15:55 +02:00
Werner Masik fe6a8d5625 fixed wrong JSON-Mapping for GUIOptions 2023-04-11 17:07:20 +02:00
Harald Bamberger e7f23643d4 fix data property name 2023-04-11 17:05:20 +02:00
Harald Bamberger c929fa8702 add freitext require, adapt freitext to current db 2023-04-11 16:59:21 +02:00
Harald Bamberger 92e23ea585 add requires for vbs zeitaufzeichnung and kuendigungsfrist 2023-04-11 16:47:44 +02:00
Harald Bamberger 3ff024fc69 fix date format 2023-04-11 15:51:23 +02:00
Harald Bamberger 234820490c variable names 2023-04-11 15:44:34 +02:00
Harald Bamberger 12c712c1b4 changed property names to match gui input 2023-04-11 15:22:40 +02:00
Harald Bamberger b50ca57907 extend VertragsbestandteilFunktion to be able to create a Benutzerfunktion entry before being persited 2023-04-11 15:10:24 +02:00
Harald Bamberger ed2aa6620e vuedatepicker added 2023-04-11 12:53:56 +02:00
Harald Bamberger 025b58dee3 throw Exception when storeVertragsbestandteil is rolled back to handle rollback in possible outer transaction 2023-04-11 11:05:15 +02:00
Andreas Österreicher fca341ccf4 Migration von Verträgen speichert nun die Eintäge auch in der DB
Tippfehler in Models behoben
Berechtigungen für DV und VBS Sequence hinzugefügt
2023-04-06 07:34:26 +02:00
Werner Masik 783cb289cd added Unit-Tests; changed IDs of organisationseinheit in VertragsGUI 2023-04-04 18:51:06 +02:00
Werner Masik c613c6dc43 small fix to prevent error when $encryptedColumns is null 2023-04-03 13:37:12 +02:00
Werner Masik c52cd05436 Merge branch 'feature-25562/PV21_Vertraege_Encryption_Merge' 2023-03-28 20:12:40 +02:00
KarpAlex 903f3d2f37 generateESI Job bugfixes (correct models, Ids in error logs), added insertvon 2023-03-23 17:50:32 +01:00
Paolo 25313a8f52 Code quality check fixes 2023-03-23 14:34:37 +01:00
KarpAlex cd6443d9c0 -added scheduler for generating and saving ESI -first version of generateESI job 2023-03-22 17:41:15 +01:00
Paolo 1b53b17b48 Merge branch 'master' into feature-16354/TinyMCE_move_to_new_version 2023-03-22 16:43:56 +01:00
KarpAlex 230ebcaf9a added table public.tbl_kennzeichen and kennzeichentyp for managing person Ids 2023-03-20 17:01:58 +01:00
Andreas Österreicher 279ddddfc8 Wochenstunden auf numeric korrigiert, Diverse NOT NULL Constraints
hinzugefügt
2023-03-17 09:53:41 +01:00
Andreas Österreicher 8f37d24693 Fixed Typo in Column Dienstverhaeltnis 2023-03-17 08:29:21 +01:00
Andreas Österreicher b2a6db9ed3 Added NOTNULL Constrait to tbl_gehaltsabrechnung.gehaltsbestandteil_id 2023-03-15 17:26:04 +01:00
Andreas Österreicher 9d8adaba26 Ermittlung des Projektbetreuer Stundensatz an Config angepasst 2023-03-14 13:05:10 +01:00
Andreas Österreicher 1165f4407e Merge branch 'master' into feature-17727/FasDefaultStundensatzProjektbetreuungAnzeigen 2023-03-14 12:53:08 +01:00
Andreas Österreicher a413064d80 Erstversion für Vertragsmigration 2023-03-14 11:46:07 +01:00
Andreas Österreicher c85d98f681 Neues HR Schema und Vertragstabellen 2023-03-10 17:44:15 +01:00
Harald Bamberger 4f764b9dfa Merge branch 'master' into feature-25562/PV21_Datenbankstruktur_fuer_Vertraege_und_Gehaelter 2023-03-10 14:13:28 +01:00
ma0068 7a554b0d0c Adaptierung Berechnung ECTS 2023-03-10 12:49:34 +01:00
Harald Bamberger cca82d2961 problem with switching presets and problem with vanishing gehaltsbestandteile solved 2023-03-10 08:21:59 +01:00
Harald Bamberger c62d89d25c add default settings for childs, add option to hide fields 2023-03-09 16:46:15 +01:00
Harald Bamberger 6a65468bb0 refactored to allow grouping elements in tabs, while maintaining json structure 2023-03-09 14:59:07 +01:00
ma0068 345cc6cf83 Adaptierung Attribut studPlan 2023-03-09 08:19:05 +01:00
ma0068 eee4faa241 Adaptierungen Matr_nr als zusätzliches Feld, LVS statt ALVS, Herausfiltern von nicht studienplanrelevanten LVs 2023-03-07 17:47:40 +01:00
ma0068 83896113d8 Anpassungen rdf diplomasupplement 2023-03-06 15:02:44 +01:00
Harald Bamberger 220617f14f enhance guioptions to be able to disable selected fields and hide gehaltsbestandteile add link 2023-02-28 10:50:40 +01:00
Harald Bamberger 7ae41ac965 pass config to gueltigkeit in formheader 2023-02-22 10:27:39 +01:00
Harald Bamberger 2672ebc61c sharedstate for gueltigkeit, mode to set gueltigkeits reflect or ignore or set shared gueltigkeit, add vertragsbestandteil kuendigungsfrist 2023-02-22 09:36:45 +01:00
Paolo 2b9af86955 - Added examples to application/config/db_crypt.php
- core/DB_Model->_addDecryptLoad fixed when checking the condition if the used operator is made of two characters
2023-02-21 16:11:49 +01:00
Werner Masik 785b824d6f add missing extension .js 2023-02-20 16:25:19 +01:00
Paolo 2729b60b39 - Added new constants SESSION_ENCRYPTED_COLUMNS and ENCRYPTED_COLUMNS to libraries/TableWidgetLib
- Changed libraries/TableWidgetLib->getDataset to accept the new parameter encryptedColumns
- Added new private method _encryptedColumns to widgets/TableWidget
- widgets/TableWidget now calls tablewidgetlib->getDataset now giving the encryptedColumns parameter
- widgets/TableWidget stores in the session the encryptedColumns parameter
2023-02-20 11:31:19 +01:00
Harald Bamberger 0413528798 cleanup form, add preset functionality for structure and data, use same JSON for preset and formoutput - prepare for save and restore before persisting to db 2023-02-17 16:05:35 +01:00
Paolo 9b8a1ba096 - Added new constants SESSION_ENCRYPTED_COLUMNS and ENCRYPTED_COLUMNS to libraries/FilterCmptLib
- Added new private property _encryptedColumns to libraries/FilterCmptLib
- libraries/FilterCmptLib: execReadOnlyQuery is now called providing the parameter _encryptedColumns to read database encrypted columns
2023-02-17 14:01:09 +01:00
Werner Masik f80ecd9aa2 fix missing extension 2023-02-17 10:41:35 +01:00
Harald Bamberger facee3076d first guess vue vertragsbestandteil und gehaltsbestandteil components 2023-02-15 15:55:37 +01:00
Paolo c831355012 - FilterWidget: now it is possible to provide the encryptedColumns parameter to specify which columns of a database table are encrypted, how to cast them and which password to use to decrypt them
- Added new constants PGSQL_BYTEA_TYPE, CRYPT_CONF_PASSWORDS, CRYPT_CAST, CRYPT_PASSWORD_NAME, CRYPT_SELECT_TEMPLATE, CRYPT_WHERE_TEMPLATE and CRYPT_WRITE_TEMPLATE to application/core/DB_Model.php
- Added new optional parameter encryptedColumns to application/core/DB_Model insert, update, load, loadWhere, execQuery, execReadOnlyQuery and _toPhp
- Added new private methods _addEncrypt, _addDecryptQuery and _addDecryptLoad to application/core/DB_Model.php
- core/DB_Model: now it is possible to provide the encryptedColumns parameter to specify which columns  of a database table are encrypted, how to cast them and which password to use to decrypt them
- Adapted application/models/system/PersonLog_model.php
2023-02-08 13:33:40 +01:00
Werner Masik f7d315d4cc model classes for contract parts (Vertragsbestandteile) 2023-01-21 13:51:59 +01:00
Werner Masik fd5ce62b0e added timeline widget 2023-01-21 13:50:45 +01:00
ma0068 d59b3736a2 Test personalmeldung xml 2023-01-18 13:15:56 +01:00
Paolo 4fa1193948 - Added new CI config file application/config/db_crypt.php, it is loaded by core/DB_Model
- Added new constant ENCRYPTION_PASSWORDS to application/core/DB_Model.php
- Added new protected properties passwordName and encryptedColumns to core/DB_Model
- Added new private methods _isCryptoEnabledAndValid, _getCipher, _encrypt and _decrypt to core/DB_Model
- core/DB_Model properties insert and update now are making use of _encrypt()
- core/DB_Model properties loadWhere and loadTree now are making use of _decrypt()
2023-01-16 12:10:49 +01:00
Werner Masik 030b459b0a make Vertragbestandteil JsonSerializable (because json_encode would otherwise output null) 2022-12-30 18:36:10 +01:00
Harald Bamberger 3818d5221c first guess vertragsbestandteil library 2022-12-13 10:49:35 +01:00
ma0068 1aada9694e Anzeige EW-Team: nur aktuelle Eintraege oder Eintraege ohne Zeitraum 2022-12-02 12:44:53 +01:00
ma0068 1c0e74e828 Testvarianten zur Anzeige von EW-Team in Personalmeldung 2022-11-30 10:38:40 +01:00
ma0068 8baa5b74dd Revert "personalmeldung.php mit masterstand überschrieben, um letztes commit rückgängig zu machen"
This reverts commit 39572452a0.
2022-11-29 10:39:20 +01:00
ma0068 39572452a0 personalmeldung.php mit masterstand überschrieben, um letztes commit rückgängig zu machen 2022-11-29 10:26:31 +01:00
ma0068 561e4ea21a Erweiterung von Studiengangs_kz_Array um Start und Ende Entwicklungsteam 2022-11-28 10:56:20 +01:00
ma0068 a88e5cbdc2 Ergänzung Prüftabelle um entwicklungsteam_id 2022-11-22 12:22:48 +01:00
ma0068 f9d5a6a6a5 Adaptierungen fuer CheckSystem, dbupdate3.4 2022-11-22 12:14:54 +01:00
ma0068 01ad28021f Fix mergeErrors mitarbeiter.class und dbupdate3.3 2022-11-21 16:10:19 +01:00
ma0048 406e1bebfe Merge branch 'master' of https://github.com/FH-Complete/FHC-Core into feature-20037/reihungstestjob_neue_studienplaene_werden_nicht_korrekt_zugeordnet 2022-11-15 15:11:44 +01:00
ma0048 75f8c4e909 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core into feature-15490/lehrauftragsliste_stammkostenstelle_bei_fix_angestellten 2022-11-15 15:09:29 +01:00
Paolo ac1df7691a - Added new view application/views/system/messages/FAShtmlWriteTemplate.php to be used with FAS/SeaMonkey and TinyMCE3
- Replaced TinyMCE V4 with V5
- Dropped TinyMCE V4
- Added new JS public/js/messaging/fasMessageWrite.js to be included by application/views/system/messages/FAShtmlWriteTemplate.php
2022-11-11 13:54:25 +01:00
Paolo 9c0d70fe89 Removed version 4 of tinymce 2022-11-08 12:01:05 +01:00
ma0048 c3ff32a9d6 - unterschiedliche farbmarkierungen hinzugefuegt 2022-11-07 11:16:27 +01:00
ma0048 592fd7ac10 Merge remote-tracking branch 'origin/master' into feature-15490/lehrauftragsliste_stammkostenstelle_bei_fix_angestellten 2022-11-04 10:49:27 +01:00
ma0068 d7897d7129 Merge branch 'master' into feature-17727/FasDefaultStundensatzProjektbetreuungAnzeigen 2022-11-02 16:18:23 +01:00
ma0048 a2c2eddf0d - sql angepasst 2022-10-12 11:18:05 +02:00
ma0048 1b49ea2a20 - rt job angepasst 2022-10-11 08:23:49 +02:00
ma0068 d2e0f34d9e Reset Defaulstundensatz bei Neuanlage Projektbetreuer 2022-05-07 12:02:51 +02:00
ma0068 bdee476a74 Adaptierungen Stundensatz: Aktualisierung Anzeige Defaultstundensatz, Zuordnung externe Betreuer 2022-05-02 11:53:14 +02:00
ma0068 9dbf59d1a1 Adaptierungen Codesniffer 2022-04-26 12:27:58 +02:00
ma0068 a4378b4592 Add Default Stundensatz 2022-04-26 09:48:22 +02:00
ma0068 f94e9a3a15 Update Löschen alter Primary Key pk_tbl_entwicklungsteam_mitarbeiter_uid, studiengang_kz 2022-04-04 09:37:50 +02:00
ma0068 4676a0a7c1 Fix Bug: Übernahme Werte ins Detailfeld 2022-03-31 15:03:35 +02:00
ma0068 f0c40bf449 Adaptierungen Entwicklungsteam UID für FAS 2022-03-31 12:44:45 +02:00
ma0068 f29d838b7c Adaptierungen für checksystem entwicklungteam_id 2022-03-18 13:45:33 +01:00
ma0068 681385946a Adaptierungen Tabelle bis.tbl_entwicklungsteam aufgrund Erweiterung um entwicklungsteam_id 2022-03-17 12:24:18 +01:00
ma0068 67c9c79113 Änderung Klasse Entwicklungsteam auf neuen Key entwicklungsteam_id 2022-03-16 13:02:52 +01:00
ma0068 9c1b6bcd44 Entwicklungsteam: Adpatierungen für Sorierung und Anzeige Mitarbeiter Grid 2022-03-15 09:43:46 +01:00
ma0068 5838e1caa5 neue Funktion getAll für Entwicklungsteam STGV 2022-03-05 12:51:06 +01:00
ma0068 297172113d neue Funktion getAll() für Anzeige Entwicklungsteams 2022-02-10 11:04:31 +01:00
ma0048 4101929cd5 stammkostenstelle anzeigen bei fixangestellten / fallback falls keine eingetragen ist 2021-10-15 12:57:18 +02:00
379 changed files with 38407 additions and 5851 deletions
+14
View File
@@ -0,0 +1,14 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use CI3_Events as Events;
/**
* NOTE(chris): example:
Events::on('stv_conf_student', function (&$res) {
$res['test'] = [
'title' => 'TEST',
'component' => './Stv/Studentenverwaltung/Details/Notizen.js'
];
});
*/
+3
View File
@@ -21,3 +21,6 @@ $config['grades_blocking_application'] = array(
$config['fbl'] = FALSE;
//Enables Info Mails
$config['send_mail'] = TRUE;
// Display fields to explain equivalence of ECTS and LV-Inhalte
$config['explain_equivalence'] = TRUE;
+29
View File
@@ -0,0 +1,29 @@
<?php
/**
* Copyright (C) 2023 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');
// NOTE: if database encryption is _not_ used then leave this array empty!
$config['encryption_passwords'] = array(
// 'password name 1' => 'password 1'
// 'password name 2' => 'password 2'
// 'password name ...' => 'password ...'
// 'password name N' => 'password N'
);
+36
View File
@@ -0,0 +1,36 @@
<?php
/**
* Copyright (C) 2023 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
$config['migratecontract_oe_default'] = 'TODO_OE_DEFAULT';
$config['migratecontract_matching_ba1_vertragsart'] = array(
'101'=>'dvbund',
'102'=>'dvanderengk',
'103'=>'echterdv',
'104'=>'studentischehilfskr',
'105'=>'externerlehrender',
'106'=>'dvanderenbet',
'107'=>'werkvertrag',
'108'=>'studentischehilfskr',
'109'=>'ueberlassungsvertrag',
'110'=>'echterfreier',
'111'=>'echterdv' //All-In
);
+8
View File
@@ -31,6 +31,14 @@ $config['navigation_header'] = array(
'expand' => true,
'sort' => 20,
'requiredPermissions' => 'admin:w'
),
'bismeldestichtagsverwaltung' => array(
'link' => site_url('codex/Bismeldestichtag'),
'icon' => '',
'description' => 'BIS-Meldestichtagsverwaltung',
'expand' => true,
'sort' => 30,
'requiredPermissions' => 'admin:w'
)
)
),
@@ -126,6 +126,7 @@ $config['antrag_job_systemuser'] = '';
* @var array Array of tbl_status.status_kurzbz's
*/
$config['antrag_prestudentstatus_whitelist'] = ['Student', 'Diplomand'];
$config['antrag_prestudentstatus_whitelist_abmeldung'] = ['Student', 'Diplomand', 'Unterbrecher'];
/**
@@ -159,3 +160,11 @@ $config['stgkz_blacklist_unterbrechung'] = [];
* @var array An array of tbl_studiengang.studiengang_kz's
*/
$config['stgkz_blacklist_wiederholung'] = [];
/**
* Blacklisted noten for negative committee exams
* noten with this ids won't be seen as negative
*
* @var array An array of noten ids
*/
$config['note_blacklist_wiederholung'] = [];
+16
View File
@@ -0,0 +1,16 @@
<?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,163 @@
<?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 (FAS) and the AntragLib (back-end)
* This controller works with calls on the HTTP GET or POST and the output is always RDF
*/
class Wiederholung extends Auth_Controller
{
/**
* Calls the parent's constructor and loads the FilterCmptLib
*/
public function __construct()
{
parent::__construct([
'getLvs' => ['student/studierendenantrag:r', 'student/noten:r'],
'moveLvsToZeugnis' => ['student/studierendenantrag:w', 'student/noten:w']
]);
// Libraries
$this->load->library('AntragLib');
// Load language phrases
$this->loadPhrases([
'global',
'studierendenantrag'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getLvs($prestudent_id)
{
// header für no cache
$this->output->set_header("Cache-Control: no-cache");
$this->output->set_header("Cache-Control: post-check=0, pre-check=0", false);
$this->output->set_header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
$this->output->set_header("Pragma: no-cache");
$this->output->set_header("Content-type: application/xhtml+xml");
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$sem_akt = $this->variablelib->getVar('semester_aktuell');
$result = $this->antraglib->getLvsForPrestudent($prestudent_id, $sem_akt);
if (isError($result))
return $result;
$lvs = $result->retval;
$rdf_url = 'http://www.technikum-wien.at/antragnote';
$this->load->view('lehre/Antrag/Wiederholung/getLvs.rdf.php', [
'url' => $rdf_url,
'lvs' => $lvs
]);
}
public function moveLvsToZeugnis()
{
$anzahl = $this->input->post('anzahl');
$student_uid = $this->input->post('student_uid');
$this->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel');
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$errormsg = array();
for($i=0; $i<$anzahl; $i++)
{
$id = $this->input->post('studierendenantrag_lehrveranstaltung_id_' . $i);
$result =$this->StudierendenantraglehrveranstaltungModel->load($id);
if(isError($result))
{
$errormsg[] = getError($result);
}
elseif(!hasData($result))
{
$errormsg[] = $this->p->t('studierendenantrag', 'error_no_lv_in_application');
}
else
{
$antragLv = getData($result)[0];
$result= $this->ZeugnisnoteModel->load([
'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
'student_uid'=> $student_uid,
'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz
]);
if(isError($result))
{
$errormsg[] = getError($result);
}
else
{
if (hasData($result))
{
$result = $this->ZeugnisnoteModel->update(
[
'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
'student_uid'=> $student_uid,
'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz
],
[
'note'=> $antragLv->note,
'uebernahmedatum' => date('c'),
'benotungsdatum' => $antragLv->insertamum,
'updateamum' => date('c'),
'bemerkung'=>$antragLv->anmerkung,
'updatevon'=>getAuthUID()
]
);
}
else
{
$result = $this->ZeugnisnoteModel->insert([
'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
'student_uid'=> $student_uid,
'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz,
'note'=> $antragLv->note,
'uebernahmedatum' => date('c'),
'benotungsdatum' => $antragLv->insertamum,
'insertamum' => date('c'),
'bemerkung'=>$antragLv->anmerkung,
'insertvon'=>getAuthUID()
]);
}
if(isError($result))
{
$errormsg[] = getError($result);
}
}
}
}
if($errormsg)
$return = false;
else
$return = true;
$this->load->view('lehre/Antrag/Wiederholung/moveLvs.rdf.php', [
'return' => $return,
'errormsg' => $errormsg
]);
}
}
@@ -0,0 +1,231 @@
<?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 FilterCmptLib (back-end)
* Provides data to the ajax get calls about the filter component
* Listens to ajax post calls to change the filter data
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Filter extends FHCAPI_Controller
{
const FILTER_UNIQUE_ID = 'filterUniqueId'; // Name of the filter cmpt unique id (mandatory)
const FILTER_TYPE = 'filterType'; // The filter type (PHP filter definition) used (mandatory)
const FILTER_ID = 'filterId'; // The id of the used filter (optional)
/**
* Calls the parent's constructor and loads the FilterCmptLib
*/
public function __construct()
{
// NOTE: FilterCmpt has its own permissions checks
parent::__construct([
'getFilter' => self::PERM_LOGGED,
'removeFilterField' => self::PERM_LOGGED,
'addFilterField' => self::PERM_LOGGED,
'applyFilterFields' => self::PERM_LOGGED,
'removeCustomFilter' => self::PERM_LOGGED,
'saveCustomFilter' => self::PERM_LOGGED,
'reloadDataset' => self::PERM_LOGGED
]);
// Loads the FiltersModel
$this->load->model('system/Filters_model', 'FiltersModel');
// Loads the FilterCmptLib with HTTP GET/POST parameters
$this->_startFilterCmptLib();
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Retrieves data about the current filter from the session and will be written on the output in JSON format
*/
public function getFilter()
{
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$session = $this->filtercmptlib->getSession();
if (is_object($session)) {
// If stdClass it is an retval object
$session = $this->getDataOrTerminateWithError($session);
}
$this->terminateWithSuccess($session);
}
/**
* Remove an applied filter (SQL where condition) from the current filter
*/
public function removeFilterField()
{
$this->form_validation->set_rules('filterField', 'filterField', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$result = $this->filtercmptlib->removeFilterField($this->input->post('filterField'));
if (!$result)
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$this->terminateWithSuccess('Field removed');
}
/**
* Add a filter (SQL where clause) to be applied to the current filter
*/
public function addFilterField()
{
$this->form_validation->set_rules('filterField', 'filterField', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$result = $this->filtercmptlib->addFilterField($this->input->post('filterField'));
if (!$result)
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$this->terminateWithSuccess('Field added');
}
/**
* Apply the filter changes
*/
public function applyFilterFields()
{
$this->form_validation->set_rules('filterFields', 'filterFields', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$result = $this->filtercmptlib->applyFilterFields($this->input->post('filterFields'));
if (!$result)
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$this->terminateWithSuccess('Applied');
}
/**
* Save the current filter as a custom filter for this user with the given description
*/
public function saveCustomFilter()
{
$this->form_validation->set_rules('customFilterName', 'customFilterName', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$result = $this->filtercmptlib->saveCustomFilter($this->input->post('customFilterName'));
if (!$result)
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$this->terminateWithSuccess('Saved');
}
/**
* Remove a custom filter by its filterId
*/
public function removeCustomFilter()
{
$this->form_validation->set_rules('filterId', 'filterId', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$result = $this->filtercmptlib->removeCustomFilter($this->input->post('filterId'));
if (!$result)
$this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
$this->terminateWithSuccess('Removed');
}
/**
* Reloads the dataset
*/
public function reloadDataset()
{
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$this->filtercmptlib->reloadDataset();
$this->terminateWithSuccess('Success');
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Loads the FilterCmptLib with the FILTER_UNIQUE_ID parameter
* If the parameter FILTER_UNIQUE_ID is not given then the execution of the controller is terminated and
* an error message is printed
*/
private function _startFilterCmptLib()
{
$filterUniqueId = null;
$filterType = null;
$filterId = null;
$validations = [
[
'field' => self::FILTER_UNIQUE_ID,
'label' => self::FILTER_UNIQUE_ID,
'rules' => 'required'
],
[
'field' => self::FILTER_TYPE,
'label' => self::FILTER_TYPE,
'rules' => 'required'
],
];
$this->load->library('form_validation');
if ($this->input->method() == 'get')
$this->form_validation->set_data($this->input->get());
$this->form_validation->set_rules($validations);
if ($this->form_validation->run()) {
$filterUniqueId = $this->input->post_get(self::FILTER_UNIQUE_ID);
$filterType = $this->input->post_get(self::FILTER_TYPE);
$filterId = $this->input->post_get(self::FILTER_ID);
// Loads the FilterCmptLib that contains all the used logic
$this->load->library(
'FilterCmptLib',
array(
'filterUniqueId' => $filterUniqueId,
'filterType' => $filterType,
'filterId' => $filterId
)
);
// Start the component
$this->filtercmptlib->start();
}
}
}
@@ -0,0 +1,101 @@
<?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 NavigationLib (back-end)
* Provides data to the ajax get calls about the filter
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Navigation extends FHCAPI_Controller
{
const NAVIGATION_PAGE_PARAM = 'navigation_page'; // Navigation page parameter name
/**
* Loads the NavigationLib where the used logic lies
*/
public function __construct()
{
parent::__construct([
'menu' => self::PERM_LOGGED,
'header' => self::PERM_LOGGED
]);
$this->_loadNavigationLib(); // Loads the NavigationLib with parameters
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* This function creates the left Menu for each Page
* @param NAVIGATION_PAGE_PARAM GET Parameter witch holds the currently called Page
* @return JSON object with the Menu Entries
*/
public function menu()
{
$menuArray = $this->navigationlib->getMenuArray($this->input->get(self::NAVIGATION_PAGE_PARAM));
$this->terminateWithSuccess($menuArray);
}
/**
* This function creates the Top Menu for each Page
* @param NAVIGATION_PAGE_PARAM GET Parameter witch holds the currently called Page
* @return JSON object with the Menu Entries
*/
public function header()
{
$headerArray = $this->navigationlib->getHeaderArray($this->input->get(self::NAVIGATION_PAGE_PARAM));
$this->terminateWithSuccess($headerArray);
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Loads the NavigationLib with the NAVIGATION_PAGE_PARAM parameter
* If the parameter NAVIGATION_PAGE_PARAM is not given then the execution of the controller is terminated and
* an error message is printed
*/
private function _loadNavigationLib()
{
// If the parameter NAVIGATION_PAGE_PARAM is present in the HTTP GET or POST
if (isset($_GET[self::NAVIGATION_PAGE_PARAM]) || isset($_POST[self::NAVIGATION_PAGE_PARAM]))
{
// If it is present in the HTTP GET
if (isset($_GET[self::NAVIGATION_PAGE_PARAM]))
{
$navigationPage = $this->input->get(self::NAVIGATION_PAGE_PARAM); // is retrieved from the HTTP GET
}
elseif (isset($_POST[self::NAVIGATION_PAGE_PARAM])) // Else if it is present in the HTTP POST
{
$navigationPage = $this->input->post(self::NAVIGATION_PAGE_PARAM); // is retrieved from the HTTP POST
}
// Loads the NavigationLib that contains all the used logic
$this->load->library('NavigationLib', array(self::NAVIGATION_PAGE_PARAM => $navigationPage));
}
else // Otherwise an error will be written in the output
{
show_error('Parameter "' . self::NAVIGATION_PAGE_PARAM . '" not provided!');
}
}
}
@@ -0,0 +1,46 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the PhrasesLib (back-end)
* Provides data to the ajax get calls about the Phrasen plugin
* This controller works with JSON calls on the HTTP GET and the output is always JSON
*/
class Phrasen extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'loadModule' => self::PERM_ANONYMOUS
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* @param string $module
*/
public function loadModule($module)
{
$this->load->library('PhrasesLib', [$module], 'pj');
$this->terminateWithSuccess(json_decode($this->pj->getJSON()));
}
}
@@ -0,0 +1,69 @@
<?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 Searchbar extends FHCAPI_Controller
{
const SEARCHSTR_PARAM = 'searchstr';
const TYPES_PARAM = 'types';
/**
* Object initialization
*/
public function __construct()
{
// NOTE(chris): additional permission checks will be done in SearchBarLib
parent::__construct([
'search' => self::PERM_LOGGED
]);
// Load the library SearchBarLib
$this->load->library('SearchBarLib');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Gets a JSON body via HTTP POST and provides the parameters
*/
public function search()
{
$this->load->library('form_validation');
// Checks if the searchstr and the types parameters are in the POSTed JSON
$this->form_validation->set_rules(self::SEARCHSTR_PARAM, null, 'required');
$this->form_validation->set_rules(self::TYPES_PARAM . '[]', null, 'required');
if (!$this->form_validation->run())
$this->terminateWithError(SearchBarLib::ERROR_WRONG_JSON, self::ERROR_TYPE_GENERAL);
// Convert to json the result from searchbarlib->search
$result = $this->searchbarlib->search($this->input->post(self::SEARCHSTR_PARAM), $this->input->post(self::TYPES_PARAM));
if (property_exists($result, 'error'))
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
$this->terminateWithSuccess($result);
}
}
@@ -0,0 +1,387 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class BetriebsmittelP extends FHCAPI_Controller
{
private $person_id = null;
public function __construct()
{
parent::__construct([
'getAllBetriebsmittel' => ['admin:r', 'assistenz:r'],
'addNewBetriebsmittel' => self::PERM_LOGGED,
'updateBetriebsmittel' => self::PERM_LOGGED,
'loadBetriebsmittel' => ['admin:r', 'assistenz:r'],
'deleteBetriebsmittel' => self::PERM_LOGGED,
'getTypenBetriebsmittel' => ['admin:r', 'assistenz:r'],
'loadInventarliste' => ['admin:r', 'assistenz:r']
]);
//Load Models
$this->load->model('ressource/Betriebsmittel_model', 'BetriebsmittelModel');
$this->load->model('ressource/Betriebsmittelperson_model', 'BetriebsmittelpersonModel');
// Additional Permission Checks
if ($this->router->method == 'addNewBetriebsmittel') {
$this->person_id = current(array_slice($this->uri->rsegments, 2));
$this->checkPermissionsForPerson(
$this->person_id,
['admin:rw', 'mitarbeiter:rw', 'basis/betriebsmittel:rw'],
['admin:rw', 'assistenz:rw', 'basis/betriebsmittel:rw']
);
} elseif ($this->router->method == 'updateBetriebsmittel' || $this->router->method == 'deleteBetriebsmittel') {
$betriebsmittelperson_id = current(array_slice($this->uri->rsegments, 2));
$result = $this->BetriebsmittelpersonModel->load($betriebsmittelperson_id);
if (!hasData($result))
show_404();
$this->person_id = current(getData($result))->person_id;
$this->checkPermissionsForPerson(
$this->person_id,
['admin:rw', 'mitarbeiter:rw', 'basis/betriebsmittel:rw'],
['admin:rw', 'assistenz:rw', 'basis/betriebsmittel:rw']
);
}
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
'wawi'
]);
}
public function getAllBetriebsmittel($type_id, $id)
{
$result = $this->BetriebsmittelpersonModel->getBetriebsmittelData($id, $type_id);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
protected function validateNewOrUpdate()
{
$this->form_validation->set_rules('betriebsmitteltyp', 'Typ', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired')
]);
$this->form_validation->set_rules('kaution', 'Kaution', 'numeric|less_than_equal_to[9999.99]', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric')
]);
$this->form_validation->set_rules('ausgegebenam', 'Ausgegeben am', 'required|is_valid_date', [
'required' => $this->p->t('ui', 'error_fieldRequired')
]);
if ($this->input->post('ausgegebenam') && $this->input->post('retouram')) {
$this->form_validation->set_rules('retouram', 'Retour am', [
'is_valid_date',
['is_not_before_ausgegebenam', function ($value) {
return (new DateTime($value) >= new DateTime($this->input->post('ausgegebenam')));
}]
], [
'is_not_before_ausgegebenam' => $this->p->t('wawi', 'error_retourdatumVorAusgabe')
]);
} else {
$this->form_validation->set_rules('retouram', 'Retour am', 'is_valid_date');
}
$this->form_validation->set_rules('anmerkung', 'Anmerkung', 'max_length[256]');
if ($this->input->post('betriebsmitteltyp') == 'Inventar') {
// Inventar
$this->form_validation->set_rules('betriebsmittel_id', 'Inventarnummer', 'required');
} elseif ($this->input->post('betriebsmitteltyp') == 'Zutrittskarte') {
// Zutrittskarte
if ($this->input->post('nummer') === null && $this->input->post('nummer') === null) {
$this->form_validation->set_rules('nummer', 'Nummer', 'required', [
'required' => $this->p->t('wawi', 'error_zutrittskarteOhneNummer')
]);
$this->form_validation->set_rules('nummer2', 'Nummer2', 'required', [
'required' => $this->p->t('wawi', 'error_zutrittskarteOhneNummer')
]);
} else {
if ($this->input->post('nummer') === null) {
$result = $this->BetriebsmittelpersonModel->loadViewWhere([
'betriebsmitteltyp' => $this->input->post('betriebsmitteltyp'),
'nummer2' => $this->input->post('nummer2'),
'person_id !=' => $this->person_id,
'retouram IS NULL' => null
]);
if (hasData($result))
$this->form_validation->set_rules('nummer2', 'Nummer2', 'is_array', [
'is_array' => $this->p->t('wawi', 'error_bmZutrittskarteOccupied', (array)current(getData($result)))
]);
} else {
$result = $this->BetriebsmittelpersonModel->loadViewWhere([
'betriebsmitteltyp' => $this->input->post('betriebsmitteltyp'),
'nummer' => $this->input->post('nummer'),
'person_id !=' => $this->person_id,
'retouram IS NULL' => null
]);
if (hasData($result))
$this->form_validation->set_rules('nummer', 'Nummer', 'is_array', [
'is_array' => $this->p->t('wawi', 'error_bmZutrittskarteOccupied', (array)current(getData($result)))
]);
}
}
}
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
public function addNewBetriebsmittel($person_id)
{
$this->form_validation->set_rules('uid', 'UID', [
['uid_in_person', function ($value) use ($person_id) {
if ($value === null)
return true;
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$result = $this->BenutzerModel->loadWhere([
'uid' => $value,
'person_id' => $person_id
]);
return hasData($result);
}]
], [
'uid_in_person' => $this->p->t('person', 'error_uidNotInPerson')
]);
$this->validateNewOrUpdate();
$betriebsmitteltyp = $this->input->post('betriebsmitteltyp');
$nummer = $this->input->post('nummer');
$nummer2 = $this->input->post('nummer2');
$beschreibung = $this->input->post('beschreibung');
$betriebsmittel_id = $this->input->post('betriebsmittel_id');
$anmerkung = $this->input->post('anmerkung');
$kaution = $this->input->post('kaution');
$ausgegebenam = $this->input->post('ausgegebenam');
$retouram = $this->input->post('retouram');
$uid = $this->input->post('uid');
// NOTE(chris): transform_kartennummer
if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer)
$nummer = is_numeric($nummer) ? ltrim($nummer, "0") : hexdec(implode("", array_reverse(str_split(trim($nummer)))));
$this->db->trans_start();
if ($betriebsmitteltyp != 'Inventar') {
$this->BetriebsmittelModel->addOrder('updateamum', 'DESC');
if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer === null) {
$result = $this->BetriebsmittelModel->loadWhere([
'betriebsmitteltyp' => $betriebsmitteltyp,
'nummer2' => $nummer2
]);
} else {
$result = $this->BetriebsmittelModel->loadWhere([
'betriebsmitteltyp' => $betriebsmitteltyp,
'nummer' => $nummer
]);
}
$data = $this->getDataOrTerminateWithError($result);
if ($data) {
$data = current($data);
if ($data->nummer !== $nummer || $data->nummer2 !== $nummer2 || $data->beschreibung !== $beschreibung) {
$result = $this->BetriebsmittelModel->update($data->betriebsmittel_id, [
'nummer' => $nummer,
'nummer2' => $nummer2,
'beschreibung' => $beschreibung,
'updateamum' => date('c'),
'updatevon' => getAuthUID()
]);
$this->getDataOrTerminateWithError($result);
}
$betriebsmittel_id = $data->betriebsmittel_id;
} else {
$result = $this->BetriebsmittelModel->insert([
'betriebsmitteltyp' => $betriebsmitteltyp,
'nummer' => $nummer,
'nummer2' => $nummer2,
'beschreibung' => $beschreibung,
'reservieren' => false,
'ort_kurzbz' => null,
'insertamum' => date('c'),
'insertvon' => getAuthUID(),
]);
$betriebsmittel_id = $this->getDataOrTerminateWithError($result);
}
}
$result = $this->BetriebsmittelpersonModel->insert([
'person_id' => $person_id,
'betriebsmittel_id' => $betriebsmittel_id,
'anmerkung' => $anmerkung,
'kaution' => $kaution,
'ausgegebenam' => $ausgegebenam,
'retouram' => $retouram,
'uid' => $uid,
'insertamum' => date('c'),
'insertvon' => getAuthUID()
]);
$data = $this->getDataOrTerminateWithError($result);
$this->db->trans_complete();
$this->terminateWithSuccess(true);
}
public function updateBetriebsmittel($betriebsmittelperson_id)
{
$this->validateNewOrUpdate();
$betriebsmitteltyp = $this->input->post('betriebsmitteltyp');
$nummer = $this->input->post('nummer');
$nummer2 = $this->input->post('nummer2');
$beschreibung = $this->input->post('beschreibung');
$betriebsmittel_id = $this->input->post('betriebsmittel_id');
$anmerkung = $this->input->post('anmerkung');
$kaution = $this->input->post('kaution');
$ausgegebenam = $this->input->post('ausgegebenam');
$retouram = $this->input->post('retouram');
// NOTE(chris): transform_kartennummer
if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer)
$nummer = is_numeric($nummer) ? ltrim($nummer, "0") : hexdec(implode("", array_reverse(str_split(trim($nummer)))));
$this->db->trans_start();
if ($betriebsmitteltyp != 'Inventar') {
$found = false;
if ($nummer !== null && $betriebsmittel_id !== null) {
$result = $this->BetriebsmittelModel->load($betriebsmittel_id);
$data = $this->getDataOrTerminateWithError($result);
if ($data && current($data)->nummer == $nummer) {
$found = true;
}
}
if (!$found) {
$this->BetriebsmittelModel->addOrder('updateamum', 'DESC');
if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer === null) {
$result = $this->BetriebsmittelModel->loadWhere([
'betriebsmitteltyp' => $betriebsmitteltyp,
'nummer2' => $nummer2
]);
} else {
$result = $this->BetriebsmittelModel->loadWhere([
'betriebsmitteltyp' => $betriebsmitteltyp,
'nummer' => $nummer
]);
}
$data = $this->getDataOrTerminateWithError($result);
}
if ($data) {
$data = current($data);
if ($data->nummer !== $nummer || $data->nummer2 !== $nummer2 || $data->beschreibung !== $beschreibung) {
$result = $this->BetriebsmittelModel->update($data->betriebsmittel_id, [
'nummer' => $nummer,
'nummer2' => $nummer2,
'beschreibung' => $beschreibung,
'updateamum' => date('c'),
'updatevon' => getAuthUID()
]);
$this->getDataOrTerminateWithError($result);
}
$betriebsmittel_id = $data->betriebsmittel_id;
} else {
$result = $this->BetriebsmittelModel->insert([
'betriebsmitteltyp' => $betriebsmitteltyp,
'nummer' => $nummer,
'nummer2' => $nummer2,
'beschreibung' => $beschreibung,
'reservieren' => false,
'ort_kurzbz' => null,
'insertamum' => date('c'),
'insertvon' => getAuthUID(),
]);
$betriebsmittel_id = $this->getDataOrTerminateWithError($result);
}
}
$result = $this->BetriebsmittelpersonModel->update($betriebsmittelperson_id, [
'betriebsmittel_id' => $betriebsmittel_id,
'anmerkung' => $anmerkung,
'kaution' => $kaution,
'ausgegebenam' => $ausgegebenam,
'retouram' => $retouram,
'updateamum' => date('c'),
'updatevon' => getAuthUID()
]);
$data = $this->getDataOrTerminateWithError($result);
$this->db->trans_complete();
$this->terminateWithSuccess(true);
}
public function loadBetriebsmittel($betriebsmittelperson_id)
{
$result = $this->BetriebsmittelpersonModel->getBetriebsmittelData($betriebsmittelperson_id, 'betriebsmittelperson_id');
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
if (!hasData($result)) {
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess(current(getData($result)));
}
public function deleteBetriebsmittel($betriebsmittelperson_id)
{
$result = $this->BetriebsmittelpersonModel->delete(
array('betriebsmittelperson_id' => $betriebsmittelperson_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' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(current(getData($result)));
}
public function getTypenBetriebsmittel()
{
$this->load->model('ressource/Betriebsmitteltyp_model', 'BetriebsmitteltypModel');
$this->BetriebsmitteltypModel->addOrder('beschreibung', 'ASC');
$result = $this->BetriebsmitteltypModel->load(); // load All
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result) ?: []);
}
public function loadInventarliste($searchString)
{
$result = $this->BetriebsmittelModel->loadInventarliste($searchString);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
}
@@ -0,0 +1,187 @@
<?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 \REST_Controller as REST_Controller;
use \Studierendenantrag_model as Studierendenantrag_model;
/**
* This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Abmeldung extends FHCAPI_Controller
{
/**
* Calls the parent's constructor and loads the AntragLib
*/
public function __construct()
{
parent::__construct([
'getDetailsForNewAntrag' => self::PERM_LOGGED,
'getDetailsForAntrag' => self::PERM_LOGGED,
'createAntrag' => self::PERM_LOGGED,
'cancelAntrag' => self::PERM_LOGGED
]);
// Libraries
$this->load->library('AntragLib');
// Load language phrases
$this->loadPhrases([
'studierendenantrag'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Retrieves data of the current studiengang for the current user
*/
public function getDetailsForNewAntrag($prestudent_id)
{
if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, true))
$this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
$result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id);
$result = $this->getDataOrTerminateWithError($result);
if (!$result) {
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_no_student'),
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
} elseif ($result == -3) {
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_stg_blacklist'),
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
} elseif ($result == -1) {
$result = $this->antraglib->getDetailsForLastAntrag(
$prestudent_id,
[
Studierendenantrag_model::TYP_ABMELDUNG,
Studierendenantrag_model::TYP_ABMELDUNG_STGL
]
);
$data = $this->getDataOrTerminateWithError($result);
$data->canCancel = (
$data->status == Studierendenantragstatus_model::STATUS_CREATED &&
$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id)
);
$this->terminateWithSuccess($data);
}
$result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getDetailsForAntrag($studierendenantrag_id)
{
if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id))
return show_404();
$result = $this->antraglib->getDetailsForAntrag($studierendenantrag_id);
$data = $this->getDataOrTerminateWithError($result);
if ($data->typ !== Studierendenantrag_model::TYP_ABMELDUNG_STGL && $data->typ !== Studierendenantrag_model::TYP_ABMELDUNG)
return show_404();
$data->canCancel = (
$data->status == Studierendenantragstatus_model::STATUS_CREATED &&
$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id)
);
$this->terminateWithSuccess($data);
}
public function createAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
$this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required');
$this->form_validation->set_rules('grund', 'Grund', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$grund = $this->input->post('grund');
$studiensemester = $this->input->post('studiensemester');
$prestudent_id = $this->input->post('prestudent_id');
$result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id);
$result = $this->getDataOrTerminateWithError($result);
if (!$result)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
elseif ($result == -3)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL);
elseif ($result < 0)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL);
$result = $this->antraglib->createAbmeldung($prestudent_id, $studiensemester, getAuthUID(), $grund);
$data = $this->getDataOrTerminateWithError($result);
$result = $this->antraglib->getDetailsForAntrag($data);
if (!hasData($result))
return $this->terminateWithSuccess(true);
$data = getData($result);
$data->canCancel = (boolean)$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id);
$this->terminateWithSuccess($data);
}
public function cancelAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('antrag_id', 'Antrag ID', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$antrag_id = $this->input->post('antrag_id');
if (!$this->antraglib->isEntitledToCancelAntrag($antrag_id))
$this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
$result = $this->antraglib->cancelAntrag($antrag_id, getAuthUID());
$this->getDataOrTerminateWithError($result);
$result = $this->antraglib->getDetailsForAntrag($antrag_id);
if (!hasData($result))
$this->terminateWithSuccess($antrag_id);
$data = getData($result);
$this->terminateWithSuccess($data);
}
}
@@ -0,0 +1,428 @@
<?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 \stdClass as stdClass;
use \Studierendenantrag_model as Studierendenantrag_model;
/**
* This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Leitung extends FHCAPI_Controller
{
/**
* Calls the parent's constructor and loads the AntragLib
*/
public function __construct()
{
parent::__construct([
'getActiveStgs' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'],
'getAntraege' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'],
'getHistory' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'],
'getPrestudents' => 'student/studierendenantrag:w',
'approveAntrag' => 'student/antragfreigabe:w',
'rejectAntrag' => 'student/antragfreigabe:w',
'reopenAntrag' => 'student/studierendenantrag:w',
'pauseAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
'unpauseAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
'objectAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
'approveObjection' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
'denyObjection' => ['student/antragfreigabe:w', 'student/studierendenantrag:w']
]);
// Libraries
$this->load->library('AntragLib');
// Load language phrases
$this->loadPhrases([
'studierendenantrag'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getActiveStgs()
{
$studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: [];
$studiengaenge = array_merge($studiengaenge, $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: []);
$result = $this->StudierendenantragModel->loadStgsWithAntraege($studiengaenge);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getAntraege($studiengang = null, $extra = null)
{
if ($studiengang && $studiengang == 'todo') {
$studiengang = $extra;
$extra = true;
} else {
$extra = false;
}
$studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe');
if(!is_array($studiengaenge))
$studiengaenge = [];
$stgsNeuanlage = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
if(!is_array($stgsNeuanlage))
$stgsNeuanlage = [];
$studiengaenge = array_unique(array_merge($studiengaenge, $stgsNeuanlage));
if ($studiengang) {
if (!in_array($studiengang, $studiengaenge))
$this->terminateWithError(
'Forbidden',
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
$studiengaenge = [$studiengang];
}
$antraege = [];
if ($studiengaenge) {
$result = $extra
? $this->StudierendenantragModel->loadActiveForStudiengaenge($studiengaenge)
: $this->StudierendenantragModel->loadForStudiengaenge($studiengaenge);
$antraege = $this->getDataOrTerminateWithError($result);
}
$this->terminateWithSuccess($antraege ?: []);
}
public function getHistory($studierendenantrag_id)
{
if (!$this->antraglib->isEntitledToSeeHistoryForAntrag($studierendenantrag_id))
$this->terminateWithError(
'Forbidden',
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
$result = $this->antraglib->getAntragHistory($studierendenantrag_id);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data ?: []);
}
public function getPrestudents()
{
$query = $this->input->post('query');
$studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
$result = $this->antraglib->getAktivePrestudentenInStgs($studiengaenge, $query);
$result = $this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($result ?: []);
}
public function approveAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToApproveAntrag', [$this->antraglib, 'isEntitledToApproveAntrag']],
],
[
'isEntitledToApproveAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
$this->form_validation->set_rules(
'typ',
'Typ',
'required|in_list[' . implode(',', [
Studierendenantrag_model::TYP_ABMELDUNG,
Studierendenantrag_model::TYP_ABMELDUNG_STGL,
Studierendenantrag_model::TYP_UNTERBRECHUNG,
Studierendenantrag_model::TYP_WIEDERHOLUNG
]) . ']'
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
switch ($this->input->post('typ')) {
case Studierendenantrag_model::TYP_ABMELDUNG:
case Studierendenantrag_model::TYP_ABMELDUNG_STGL:
$result = $this->antraglib->approveAbmeldung([$studierendenantrag_id], getAuthUID());
break;
case Studierendenantrag_model::TYP_UNTERBRECHUNG:
$result = $this->antraglib->approveUnterbrechung([$studierendenantrag_id], getAuthUID());
break;
case Studierendenantrag_model::TYP_WIEDERHOLUNG:
$result = $this->antraglib->approveWiederholung($studierendenantrag_id, getAuthUID());
break;
}
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
public function rejectAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToRejectAntrag', [$this->antraglib, 'isEntitledToRejectAntrag']],
],
[
'isEntitledToRejectAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
$this->form_validation->set_rules('grund', 'Grund', 'required');
$this->form_validation->set_rules(
'typ',
'Typ',
'required|in_list[' . implode(',', [
Studierendenantrag_model::TYP_UNTERBRECHUNG
]) . ']'
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$grund = $this->input->post('grund');
$result = $this->antraglib->rejectUnterbrechung([$studierendenantrag_id], getAuthUID(), $grund);
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
public function reopenAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToReopenAntrag', [$this->antraglib, 'isEntitledToReopenAntrag']],
],
[
'isEntitledToReopenAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
$this->form_validation->set_rules(
'typ',
'Typ',
'required|in_list[' . implode(',', [
Studierendenantrag_model::TYP_WIEDERHOLUNG
]) . ']'
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->reopenWiederholung($studierendenantrag_id, getAuthUID());
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
public function pauseAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToPauseAntrag', [$this->antraglib, 'isEntitledToPauseAntrag']],
['antragCanBeManualPaused', [$this->antraglib, 'antragCanBeManualPaused']]
],
[
'isEntitledToPauseAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'antragCanBeManualPaused' => $this->p->t(
'studierendenantrag',
'error_not_pauseable',
['id' => $this->input->post('studierendenantrag_id')]
)
]
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->pauseAntrag($studierendenantrag_id, getAuthUID());
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
public function unpauseAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToUnpauseAntrag', [$this->antraglib, 'isEntitledToUnpauseAntrag']],
['antragCanBeManualUnpaused', [$this->antraglib, 'antragCanBeManualUnpaused']]
],
[
'isEntitledToUnpauseAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'antragCanBeManualUnpaused' => $this->p->t(
'studierendenantrag',
'error_not_paused',
['id' => $this->input->post('studierendenantrag_id')]
)
]
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->unpauseAntrag($studierendenantrag_id, getAuthUID());
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
public function objectAntrag()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']],
['canBeObjected', function ($a) {
return $this->antraglib->hasType($a, Studierendenantrag_model::TYP_ABMELDUNG_STGL);
}]
],
[
'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'canBeObjected' => $this->p->t(
'studierendenantrag',
'error_no_objection'
)
]
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->objectAbmeldung($studierendenantrag_id, getAuthUID());
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
public function approveObjection()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']],
['isObjected', function ($a) {
return $this->antraglib->hasStatus($a, Studierendenantragstatus_model::STATUS_OBJECTED);
}]
],
[
'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'isObjected' => $this->p->t(
'studierendenantrag',
'error_not_objected'
)
]
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->cancelAntrag($studierendenantrag_id, getAuthUID());
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
public function denyObjection()
{
$this->load->library('form_validation');
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
[
'required',
['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']],
['isObjected', function ($a) {
return $this->antraglib->hasStatus($a, Studierendenantragstatus_model::STATUS_OBJECTED);
}]
],
[
'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'isObjected' => $this->p->t(
'studierendenantrag',
'error_not_objected'
)
]
);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$grund = $this->input->post('grund');
$result = $this->antraglib->denyObjectionAbmeldung($studierendenantrag_id, getAuthUID(), $grund);
$this->getDataOrTerminateWithError($result);
return $this->terminateWithSuccess($studierendenantrag_id);
}
}
@@ -1,4 +1,20 @@
<?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');
@@ -6,23 +22,28 @@ use \Studierendenantrag_model as Studierendenantrag_model;
use \DateTime as DateTime;
/**
*
* This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Unterbrechung extends FHC_Controller
class Unterbrechung extends FHCAPI_Controller
{
/**
* Calls the parent's constructor and loads the FilterCmptLib
* Calls the parent's constructor and loads the AntragLib
*/
public function __construct()
{
parent::__construct();
parent::__construct([
'getDetailsForNewAntrag' => self::PERM_LOGGED,
'getDetailsForAntrag' => self::PERM_LOGGED,
'createAntrag' => self::PERM_LOGGED,
'cancelAntrag' => self::PERM_LOGGED
]);
// Configs
$this->load->config('studierendenantrag');
// Libraries
$this->load->library('AuthLib');
$this->load->library('AntragLib');
// Load language phrases
@@ -38,74 +59,62 @@ class Unterbrechung extends FHC_Controller
public function getDetailsForNewAntrag($prestudent_id)
{
if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false)) {
$this->output->set_status_header(403);
return $this->outputJsonError('Forbidden');
}
if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false))
$this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
$result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($prestudent_id);
if (isError($result)) {
$this->output->set_status_header(500);
return $this->outputJsonError(getError($result));
}
$result = $result->retval;
$result = $this->getDataOrTerminateWithError($result);
if (!$result) {
$this->output->set_status_header(403);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_no_student'));
}
elseif ($result == -1)
{
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_no_student'),
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
} elseif ($result == -1) {
$result = $this->antraglib->getDetailsForLastAntrag($prestudent_id, Studierendenantrag_model::TYP_UNTERBRECHUNG);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$data = $this->getDataOrTerminateWithError($result);
return $this->outputJsonSuccess(getData($result));
}
elseif ($result == -2)
{
return $this->terminateWithSuccess($data);
} elseif ($result == -2) {
$result = $this->antraglib->getDetailsForLastAntrag($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$result = getData($result);
$this->output->set_status_header(400);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_antrag_pending', [
$data = $this->getDataOrTerminateWithError($result);
return $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_pending', [
'typ' => $this->p->t('studierendenantrag', 'antrag_typ_' . $result->typ)
]));
} elseif ($result == -3) {
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_stg_blacklist'),
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
}
elseif ($result == -3)
{
$this->output->set_status_header(403);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_stg_blacklist'));
}
$result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$data = getData($result);
$data = $this->getDataOrTerminateWithError($result);
$data->studiensemester = $this->antraglib->getSemesterForUnterbrechung($data->studiensemester_kurzbz);
$data->studiensemester = $this->antraglib->getSemesterForUnterbrechung($prestudent_id, null);
$this->outputJsonSuccess($data);
$this->terminateWithSuccess($data);
}
public function getDetailsForAntrag($studierendenantrag_id)
{
if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id)) return show_404();
if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id))
return show_404();
$result = $this->antraglib->getDetailsForAntrag($studierendenantrag_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$data = getData($result);
$data = $this->getDataOrTerminateWithError($result);
if ($data->typ !== Studierendenantrag_model::TYP_UNTERBRECHUNG)
return show_404();
$this->outputJsonSuccess($data);
$this->terminateWithSuccess($data);
}
public function createAntrag()
@@ -125,9 +134,8 @@ class Unterbrechung extends FHC_Controller
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
if (!$this->form_validation->run()) {
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$grund = $this->input->post('grund');
@@ -136,26 +144,18 @@ class Unterbrechung extends FHC_Controller
$datum_wiedereinstieg = $this->input->post('datum_wiedereinstieg');
$dms_id = null;
$result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(['db' => getError($result)]);
}
$result = $result->retval;
if (!$result)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_no_student')]);
}
elseif ($result == -3)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_stg_blacklist')]);
}
elseif ($result < 0)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_antrag_exists')]);
}
$result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($prestudent_id, $studiensemester, $datum_wiedereinstieg);
if(isset($_FILES['attachment']) && (!isset($_FILES['attachment']['error']) || $_FILES['attachment']['error'] != UPLOAD_ERR_NO_FILE))
{
$result = $this->getDataOrTerminateWithError($result);
if (!$result)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
elseif ($result == -3)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL);
elseif ($result < 0)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL);
if (isset($_FILES['attachment']) && (!isset($_FILES['attachment']['error']) || $_FILES['attachment']['error'] != UPLOAD_ERR_NO_FILE)) {
$this->load->library('DmsLib');
$dms = $this->config->item('unterbrechung_dms');
@@ -167,53 +167,46 @@ class Unterbrechung extends FHC_Controller
$allowed_filetypes = $this->config->item('unterbrechung_dms_filetypes') ?: ['*'];
$result = $this->dmslib->upload($dms, 'attachment', $allowed_filetypes);
if(isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
$dms_id = getData($result)['dms_id'];
$data = $this->getDataOrTerminateWithError($result);
$dms_id = $data['dms_id'];
}
$result = $this->antraglib->createUnterbrechung($prestudent_id, $studiensemester, getAuthUID(), $grund, $datum_wiedereinstieg, $dms_id);
if(isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
$antragId = getData($result);
$antragId = $this->getDataOrTerminateWithError($result);
$result = $this->antraglib->getDetailsForAntrag($antragId);
if(!hasData($result))
return $this->outputJsonSuccess($antragId);
$this->outputJsonSuccess(getData($result));
if (!hasData($result))
$this->terminateWithSuccess($antragId);
$this->terminateWithSuccess(getData($result));
}
public function cancelAntrag()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules('antrag_id', 'Antrag ID', 'required');
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
if (!$this->form_validation->run()) {
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$antrag_id = $this->input->post('antrag_id');
$result = $this->antraglib->cancelAntrag($antrag_id, getAuthUID());
if (isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
$this->getDataOrTerminateWithError($result);
$result = $this->antraglib->getDetailsForAntrag($antrag_id);
if (!hasData($result))
return $this->outputJsonSuccess($antrag_id);
$this->outputJsonSuccess(getData($result));
return $this->terminateWithSuccess($antrag_id);
$this->terminateWithSuccess(getData($result));
}
public function isValidDate($date)
@@ -0,0 +1,258 @@
<?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 \REST_Controller as REST_Controller;
use \Studierendenantragstatus_model as Studierendenantragstatus_model;
/**
* This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Wiederholung extends FHCAPI_Controller
{
/**
* Calls the parent's constructor and loads the FilterCmptLib
*/
public function __construct()
{
parent::__construct([
'getDetailsForNewAntrag' => self::PERM_LOGGED,
'createAntrag' => self::PERM_LOGGED,
'cancelAntrag' => self::PERM_LOGGED,
'getLvs' => self::PERM_LOGGED,
'saveLvs' => ['student/studierendenantrag:w']
]);
// Libraries
$this->load->library('AntragLib');
// Load language phrases
$this->loadPhrases([
'global',
'studierendenantrag'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Retrieves data of the current studiengang for the current user
*/
public function getDetailsForNewAntrag($prestudent_id)
{
if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false))
$this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
$result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id);
$result = $this->getDataOrTerminateWithError($result);
if (!$result) {
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_no_student_no_failed_exam'),
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
} elseif ($result == -1) {
$result = $this->antraglib->getDetailsForLastAntrag($prestudent_id, Studierendenantrag_model::TYP_WIEDERHOLUNG);
$data = $this->getDataOrTerminateWithError($result);
$result = $this->antraglib->getFailedExamForPrestudent($prestudent_id, $data->datum, $data->studiensemester_kurzbz);
// NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
$pruefungsdata = current(getData($result));
$data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
$data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
$data->pruefungsdatum = $pruefungsdata->datum;
$this->terminateWithSuccess($data);
} elseif ($result == -2) {
$result = $this->antraglib->getDetailsForLastAntrag($prestudent_id);
$result = $this->getDataOrTerminateWithError($result);
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_antrag_pending', [
'typ' => $this->p->t('studierendenantrag', 'antrag_typ_' . $result->typ)
]),
self::ERROR_TYPE_GENERAL,
REST_Controller::HTTP_BAD_REQUEST
);
} elseif ($result == -3) {
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_stg_blacklist'),
self::ERROR_TYPE_GENERAL,
REST_Controller::HTTP_BAD_REQUEST
);
}
$result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
$data = $this->getDataOrTerminateWithError($result);
$result = $this->antraglib->getFailedExamForPrestudent($prestudent_id);
// NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
$pruefungsdata = current(getData($result));
$data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
$data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
$data->pruefungsdatum = $pruefungsdata->datum;
$this->terminateWithSuccess($data);
}
public function createAntrag()
{
$this->createAntragWithStatus(true);
}
public function cancelAntrag()
{
$this->createAntragWithStatus(false);
}
protected function createAntragWithStatus($repeat)
{
$this->load->library('form_validation');
$this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required');
$this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$prestudent_id = $this->input->post('prestudent_id');
$studiensemester = $this->input->post('studiensemester');
$result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id);
$result = $this->getDataOrTerminateWithError($result);
if (!$result) {
$this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
} elseif ($result == -1) {
$result = $this->PrestudentstatusModel->getLastStatus($prestudent_id);
$result = $this->getDataOrTerminateWithError($result);
if (!$result)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_no_prestudentstatus', [
'prestudent_id' => $prestudent_id
]), self::ERROR_TYPE_GENERAL);
if (!in_array(current($result)->status_kurzbz, $this->config->item('antrag_prestudentstatus_whitelist')))
$this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
} elseif ($result == -2) {
$this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL);
} elseif ($result == -3) {
$this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL);
}
$result = $this->antraglib->createWiederholung($prestudent_id, $studiensemester, getAuthUID(), $repeat);
$antragId = $this->getDataOrTerminateWithError($result);
$result = $this->antraglib->getDetailsForAntrag($antragId);
if (!hasData($result))
$this->terminateWithSuccess(true);
$data = getData($result);
$result = $this->antraglib->getFailedExamForPrestudent($prestudent_id);
// NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
$pruefungsdata = current(getData($result));
$data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
$data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
$data->pruefungsdatum = $pruefungsdata->datum;
$this->terminateWithSuccess($data);
}
public function getLvs($antrag_id)
{
$result = $this->antraglib->getLvsForAntrag($antrag_id);
if (isError($result)) {
$error = getError($result);
if ($error == 'Forbidden')
$this->terminateWithError(
$error,
self::ERROR_TYPE_AUTH,
REST_Controller::HTTP_FORBIDDEN
);
$this->terminateWithError(
$error,
self::ERROR_TYPE_GENERAL
);
}
$lvs = getData($result);
$this->terminateWithSuccess($lvs);
}
public function saveLvs()
{
$forbiddenLvs = $this->input->post('forbiddenLvs');
$mandatoryLvs = $this->input->post('mandatoryLvs');
$antragsLvs = array_merge($forbiddenLvs, $mandatoryLvs);
if (!$antragsLvs)
$this->terminateWithError($this->p->t('studierendenantrag', 'error_no_lv'), self::ERROR_TYPE_GENERAL);
$insert = array_map(function ($lv) {
return [
'studierendenantrag_id' => $lv['studierendenantrag_id'],
'lehrveranstaltung_id' => $lv['lehrveranstaltung_id'],
'note' => $lv['zugelassen']
? ($lv['zugelassen'] == 1 ? 0 : $this->config->item('wiederholung_note_angerechnet'))
: $this->config->item('wiederholung_note_nicht_zugelassen'),
'anmerkung' => $lv['anmerkung'],
'insertvon' => getAuthUID(),
'studiensemester_kurzbz' => $lv['studiensemester_kurzbz']
];
}, $antragsLvs);
$antrag_ids = array_unique(array_map(function ($lv) {
return $lv['studierendenantrag_id'];
}, $insert));
foreach ($antrag_ids as $antrag_id) {
$result = $this->StudierendenantragModel->loadIdAndStatusWhere([
'studierendenantrag_id' => $antrag_id
]);
$antrag = $this->getDataOrTerminateWithError($result);
if (!$antrag)
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id]),
self::ERROR_TYPE_GENERAL
);
$antrag = current($antrag);
if ($antrag->status != Studierendenantragstatus_model::STATUS_CREATED
&& $antrag->status != Studierendenantragstatus_model::STATUS_LVSASSIGNED)
$this->terminateWithError(
$this->p->t('studierendenantrag', 'error_antrag_locked'),
self::ERROR_TYPE_GENERAL
);
}
$result = $this->antraglib->saveLvs($insert);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
}
@@ -0,0 +1,140 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Overview on Bismeldestichtage
*/
class Bismeldestichtag extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'admin:r',
'getStudiensemester' => 'admin:r',
'getBismeldestichtage' => 'admin:r',
'addBismeldestichtag' => 'admin:rw',
'deleteBismeldestichtag' => 'admin:rw'
)
);
// Load models
$this->load->model('codex/Bismeldestichtag_model', 'BismeldestichtagModel');
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
// Loads phrases system
$this->loadPhrases(
array(
'bismeldestichtag'
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Everything has a beginning
*/
public function index()
{
$this->load->view('codex/bismeldestichtag.php');
}
public function getStudiensemester()
{
// load semester list
$semList = array();
$this->StudiensemesterModel->addSelect('studiensemester_kurzbz');
$this->StudiensemesterModel->addOrder('start', 'DESC');
$semRes = $this->StudiensemesterModel->load();
if (hasData($semRes))
{
$semList = getData($semRes);
}
// load current semester
$currSem = null;
$semRes = $this->StudiensemesterModel->getAkt();
if (hasData($semRes))
{
$currSem = getData($semRes)[0]->studiensemester_kurzbz;
}
// output data
$this->outputJsonSuccess(
array('semList' => $semList, 'currSem' => $currSem)
);
}
public function getBismeldestichtage()
{
$this->BismeldestichtagModel->addSelect(
'meldestichtag_id, meldestichtag,
tbl_bismeldestichtag.studiensemester_kurzbz, sem.start AS semester_start,
tbl_bismeldestichtag.insertamum, tbl_bismeldestichtag.insertvon, tbl_bismeldestichtag.updateamum, tbl_bismeldestichtag.updatevon'
);
$this->BismeldestichtagModel->addJoin('public.tbl_studiensemester sem', 'studiensemester_kurzbz', 'LEFT');
$this->BismeldestichtagModel->addOrder('semester_start');
$this->BismeldestichtagModel->addOrder('meldestichtag', 'DESC');
$this->BismeldestichtagModel->addOrder('meldestichtag_id', 'DESC');
$this->outputJson($this->BismeldestichtagModel->load());
}
public function addBismeldestichtag()
{
// get request data
$request = $this->getPostJSON();
// check request data
if (!property_exists($request, 'meldestichtag') || isEmptyString($request->meldestichtag))
$this->terminateWithJsonError('Error occured: Meldestichtag missing');
if (!property_exists($request, 'studiensemester_kurzbz') || isEmptyString($request->studiensemester_kurzbz))
$this->terminateWithJsonError('Error occured: Studiensemester missing');
$meldestichtag = $request->meldestichtag;
$studiensemester_kurzbz = $request->studiensemester_kurzbz;
// check if Bismeldestichtag already exists
$this->BismeldestichtagModel->addSelect('1');
$bismeldestichtagRes = $this->BismeldestichtagModel->loadWhere(
array('meldestichtag' => $meldestichtag, 'studiensemester_kurzbz' => $studiensemester_kurzbz)
);
// return success if already exists
if (hasData($bismeldestichtagRes))
$this->outputJsonSuccess('Bismeldestichtag already exists');
else
{
// insert new if Stichtag does not exist
$this->outputJson($this->BismeldestichtagModel->insert(
array(
'meldestichtag' => $request->meldestichtag,
'studiensemester_kurzbz' => $request->studiensemester_kurzbz,
'insertvon' => getAuthUID()
)
));
}
}
public function deleteBismeldestichtag()
{
// get request data
$request = $this->getPostJSON();
// check request data
if (!property_exists($request, 'meldestichtag_id'))
$this->terminateWithJsonError('Error occured: Meldestichtag Id missing');
$meldestichtag_id = $request->meldestichtag_id;
// deletetion
$this->outputJson($this->BismeldestichtagModel->delete($meldestichtag_id));
}
}
@@ -1,218 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \Studierendenantrag_model as Studierendenantrag_model;
/**
*
*/
class Abmeldung extends FHC_Controller
{
/**
* Calls the parent's constructor and loads the FilterCmptLib
*/
public function __construct()
{
parent::__construct();
// Libraries
$this->load->library('AuthLib');
$this->load->library('AntragLib');
// Load language phrases
$this->loadPhrases([
'studierendenantrag'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Retrieves data of the current studiengang for the current user
*/
public function getDetailsForNewAntrag($prestudent_id)
{
if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, true)) {
$this->output->set_status_header(403);
return $this->outputJsonError('Forbidden');
}
$result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id);
if (isError($result)) {
$this->output->set_status_header(500);
return $this->outputJsonError(getError($result));
}
$result = $result->retval;
if (!$result) {
$this->output->set_status_header(403);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_no_student'));
}
elseif ($result == -3)
{
$this->output->set_status_header(403);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_stg_blacklist'));
}
elseif ($result == -1)
{
$result = $this->antraglib->getDetailsForLastAntrag(
$prestudent_id,
[
Studierendenantrag_model::TYP_ABMELDUNG,
Studierendenantrag_model::TYP_ABMELDUNG_STGL
]
);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$data = getData($result);
$data->canCancel = (
$data->status == Studierendenantragstatus_model::STATUS_CREATED &&
$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id)
);
return $this->outputJsonSuccess($data);
}
$result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$this->outputJsonSuccess(getData($result));
}
public function getDetailsForAntrag($studierendenantrag_id)
{
if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id)) return show_404();
$result = $this->antraglib->getDetailsForAntrag($studierendenantrag_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$data = getData($result);
if ($data->typ !== Studierendenantrag_model::TYP_ABMELDUNG_STGL && $data->typ !== Studierendenantrag_model::TYP_ABMELDUNG)
return show_404();
$data->canCancel = (
$data->status == Studierendenantragstatus_model::STATUS_CREATED &&
$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id)
);
$this->outputJsonSuccess($data);
}
public function createAntrag()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
$this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required');
$this->form_validation->set_rules('grund', 'Grund', 'required');
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$grund = $this->input->post('grund');
$studiensemester = $this->input->post('studiensemester');
$prestudent_id = $this->input->post('prestudent_id');
$result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(['db' => getError($result)]);
}
$result = $result->retval;
if (!$result)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_no_student')]);
}
elseif ($result == -3)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_stg_blacklist')]);
}
elseif ($result < 0)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_antrag_exists')]);
}
$result = $this->antraglib->createAbmeldung($prestudent_id, $studiensemester, getAuthUID(), $grund);
if (isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
$result = $this->antraglib->getDetailsForAntrag(getData($result));
if (!hasData($result))
return $this->outputJsonSuccess(true);
$data = getData($result);
$data->canCancel = (boolean)$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id);
$this->outputJsonSuccess($data);
}
public function cancelAntrag()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules('antrag_id', 'Antrag ID', 'required');
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$antrag_id = $this->input->post('antrag_id');
if(!$this->antraglib->isEntitledToCancelAntrag($antrag_id))
{
$this->output->set_status_header(403);
return $this->outputJsonError('Forbidden');
}
$result = $this->antraglib->cancelAntrag($antrag_id, getAuthUID());
if(isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
$result = $this->antraglib->getDetailsForAntrag($antrag_id);
if (!hasData($result))
return $this->outputJsonSuccess($antrag_id);
$this->outputJsonSuccess(getData($result));
}
public function getStudiengaengeAssistenz()
{
$this->load->library('PermissionLib');
$_POST = json_decode($this->input->raw_input_stream, true);
$query = $this->input->post('query');
$studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
$result = $this->antraglib->getAktivePrestudentenInStgs($studiengaenge, $query);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$result = getData($result);
if (!$result) {
return $this->outputJsonSuccess([]);
}
return $this->outputJsonSuccess($result);
}
}
@@ -1,413 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \stdClass as stdClass;
/**
*
*/
class Leitung extends FHC_Controller
{
/**
* Calls the parent's constructor and loads the FilterCmptLib
*/
public function __construct()
{
parent::__construct();
// Libraries
$this->load->library('AuthLib');
$this->load->library('AntragLib');
// Load language phrases
$this->loadPhrases([
'studierendenantrag'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getActiveStgs()
{
$studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe');
$stgsNeuanlage = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
$stgs = [];
if ($studiengaenge) {
$result = $this->StudierendenantragModel->loadForStudiengaenge($studiengaenge);
if (isError($result))
return $this->outputJson($result);
$antraege = getData($result) ?: [];
foreach ($antraege as $antrag) {
if (!isset($stgs[$antrag->studiengang_kz])) {
$stgs[$antrag->studiengang_kz] = new stdClass();
$stgs[$antrag->studiengang_kz]->bezeichnung = $antrag->bezeichnung;
$stgs[$antrag->studiengang_kz]->orgform = $antrag->orgform;
$stgs[$antrag->studiengang_kz]->studiengang_kz = $antrag->studiengang_kz;
}
}
}
if ($stgsNeuanlage) {
$result = $this->StudierendenantragModel->loadForStudiengaenge($stgsNeuanlage);
if (isError($result))
return $this->outputJson($result);
$antraege = getData($result) ?: [];
foreach ($antraege as $antrag) {
if (!isset($stgs[$antrag->studiengang_kz])) {
$stgs[$antrag->studiengang_kz] = new stdClass();
$stgs[$antrag->studiengang_kz]->bezeichnung = $antrag->bezeichnung;
$stgs[$antrag->studiengang_kz]->orgform = $antrag->orgform;
$stgs[$antrag->studiengang_kz]->studiengang_kz = $antrag->studiengang_kz;
}
}
}
$this->outputJsonSuccess($stgs);
}
public function getAntraege($studiengang = null)
{
if($studiengang)
$studiengaenge = [$studiengang];
else {
$studiengaenge =$this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe');
if(!is_array($studiengaenge))
$studiengaenge = [];
$stgsNeuanlage = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
if(!is_array($stgsNeuanlage))
$stgsNeuanlage = [];
$studiengaenge = array_unique(array_merge($studiengaenge, $stgsNeuanlage));
}
$antraege = [];
if ($studiengaenge) {
$result = $this->StudierendenantragModel->loadForStudiengaenge($studiengaenge);
if (isError($result)) {
$this->output->set_status_header(500);
return $this->outputJson('Internal Server Error');
}
if(hasData($result))
{
$antraege = getData($result);
}
}
$this->outputJson($antraege);
}
public function reopenAntrag()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToReopenAntrag',
[
'isEntitledToReopenAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->reopenWiederholung($studierendenantrag_id, getAuthUID());
if (isError($result))
return $this->outputJsonError(['studierendenantrag_id' => getError($result)]);
$this->outputJsonSuccess($studierendenantrag_id);
}
public function objectAntrag()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToObjectAntrag|callback_canBeObjected',
[
'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'canBeObjected' => $this->p->t('studierendenantrag', 'error_no_objection')
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->objectAbmeldung($studierendenantrag_id, getAuthUID());
if (isError($result))
return $this->outputJsonError(['studierendenantrag_id' => getError($result)]);
$this->outputJsonSuccess($studierendenantrag_id);
}
public function objectionDeny()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToObjectAntrag|callback_isObjected',
[
'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'isObjected' => $this->p->t('studierendenantrag', 'error_not_objected')
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$grund = $this->input->post('grund');
$result = $this->antraglib->denyObjectionAbmeldung($studierendenantrag_id, getAuthUID(), $grund);
if (isError($result))
return $this->outputJsonError(['studierendenantrag_id' => getError($result)]);
$this->outputJsonSuccess($studierendenantrag_id);
}
public function objectionApprove()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToObjectAntrag|callback_isObjected',
[
'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
'isObjected' => $this->p->t('studierendenantrag', 'error_not_objected')
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->cancelAntrag($studierendenantrag_id, getAuthUID());
if (isError($result))
return $this->outputJsonError(['studierendenantrag_id' => getError($result)]);
$this->outputJsonSuccess($studierendenantrag_id);
}
public function isEntitledToReopenAntrag($studierendenantrag_id)
{
return $this->antraglib->isEntitledToReopenAntrag($studierendenantrag_id);
}
public function isEntitledToObjectAntrag($studierendenantrag_id)
{
return $this->antraglib->isEntitledToObjectAntrag($studierendenantrag_id);
}
public function isEntitledToRejectAntrag($studierendenantrag_id)
{
return $this->antraglib->isEntitledToRejectAntrag($studierendenantrag_id);
}
public function canBeObjected($studierendenantrag_id)
{
return $this->antraglib->hasType($studierendenantrag_id, Studierendenantrag_model::TYP_ABMELDUNG_STGL);
}
public function isObjected($studierendenantrag_id)
{
return $this->antraglib->hasStatus($studierendenantrag_id, Studierendenantragstatus_model::STATUS_OBJECTED);
}
public function approveAbmeldung()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToApproveAntrag',
[
'isEntitledToApproveAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->approveAbmeldung([$studierendenantrag_id], getAuthUID());
if (isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
return $this->outputJsonSuccess($studierendenantrag_id);
}
public function approveAbmeldungStgl()
{
return $this->approveAbmeldung();
}
public function approveUnterbrechung()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToApproveAntrag',
[
'isEntitledToApproveAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->approveUnterbrechung([$studierendenantrag_id], getAuthUID());
if (isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
return $this->outputJsonSuccess($studierendenantrag_id);
}
public function rejectUnterbrechung()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToRejectAntrag',
[
'isEntitledToRejectAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
$this->form_validation->set_rules('grund', 'Grund', 'required');
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$grund = $this->input->post('grund');
$result = $this->antraglib->rejectUnterbrechung([$studierendenantrag_id], getAuthUID(), $grund);
if (isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
return $this->outputJsonSuccess($studierendenantrag_id);
}
public function approveWiederholung()
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules(
'studierendenantrag_id',
'Studierenden Antrag',
'required|callback_isEntitledToApproveAntrag',
[
'isEntitledToApproveAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
]
);
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$studierendenantrag_id = $this->input->post('studierendenantrag_id');
$result = $this->antraglib->approveWiederholung($studierendenantrag_id, getAuthUID());
if (isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
return $this->outputJsonSuccess($studierendenantrag_id);
}
public function isEntitledToApproveAntrag($studierendenantrag_id)
{
return $this->antraglib->isEntitledToApproveAntrag($studierendenantrag_id);
}
public function getHistory($studierendenantrag_id)
{
if (!$this->antraglib->isEntitledToSeeHistoryForAntrag($studierendenantrag_id)) {
$this->output->set_status_header(403);
return $this->outputJson('Forbidden');
}
$result = $this->antraglib->getAntragHistory($studierendenantrag_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$this->outputJsonSuccess(getData($result) ?: []);
}
}
@@ -1,372 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \REST_Controller as REST_Controller;
/**
*
*/
class Wiederholung extends FHC_Controller
{
/**
* Calls the parent's constructor and loads the FilterCmptLib
*/
public function __construct()
{
parent::__construct();
// Configs
$this->load->config('studierendenantrag');
// Libraries
$this->load->library('AuthLib');
$this->load->library('PermissionLib');
$this->load->library('AntragLib');
$requiredPermissions = [
'saveLvs' => ['student/studierendenantrag:w'],
'getLvsAsRdf' => ['student/studierendenantrag:r', 'student/noten:r'],
'moveLvsToZeugnis' => ['student/studierendenantrag:w', 'student/noten:w']
];
if (isset($requiredPermissions[$this->router->method])) {
if (!$this->permissionlib->isEntitled($requiredPermissions, $this->router->method)) {
$this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
$this->outputJson('Forbidden');
exit;
}
}
// Load language phrases
$this->loadPhrases([
'global',
'studierendenantrag'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Retrieves data of the current studiengang for the current user
*/
public function getDetailsForNewAntrag($prestudent_id)
{
if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false)) {
$this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
return $this->outputJsonError('Forbidden');
}
$result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id);
if (isError($result)) {
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
return $this->outputJsonError(getError($result));
}
$result = $result->retval;
if (!$result) {
$this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_no_student_no_failed_exam'));
}
elseif ($result == -1)
{
$result = $this->antraglib->getDetailsForLastAntrag($prestudent_id, Studierendenantrag_model::TYP_WIEDERHOLUNG);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$data = getData($result);
$result = $this->antraglib->getFailedExamForPrestudent($prestudent_id);
// NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
$pruefungsdata = current(getData($result));
$data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
$data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
$data->pruefungsdatum = $pruefungsdata->datum;
return $this->outputJsonSuccess($data);
}
elseif ($result == -2)
{
$result = $this->antraglib->getDetailsForLastAntrag($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$result = getData($result);
$this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_antrag_pending', [
'typ' => $this->p->t('studierendenantrag', 'antrag_typ_' . $result->typ)
]));
}
elseif ($result == -3)
{
$this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_stg_blacklist'));
}
$result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$data = getData($result);
$result = $this->antraglib->getFailedExamForPrestudent($prestudent_id);
// NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
$pruefungsdata = current(getData($result));
$data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
$data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
$data->pruefungsdatum = $pruefungsdata->datum;
$this->outputJsonSuccess($data);
}
public function createAntrag()
{
$this->createAntragWithStatus(true);
}
public function cancelAntrag()
{
$this->createAntragWithStatus(false);
}
protected function createAntragWithStatus($repeat)
{
$this->load->library('form_validation');
$_POST = json_decode($this->input->raw_input_stream, true);
$this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required');
$this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
if ($this->form_validation->run() == false)
{
return $this->outputJsonError($this->form_validation->error_array());
}
$prestudent_id = $this->input->post('prestudent_id');
$studiensemester = $this->input->post('studiensemester');
$result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id);
if (isError($result)) {
return $this->outputJsonError(['db' => getError($result)]);
}
$result = $result->retval;
if (!$result)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_no_student')]);
}
elseif ($result == -2)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_antrag_exists')]);
}
elseif ($result == -3)
{
return $this->outputJsonError(['db' => $this->p->t('studierendenantrag', 'error_stg_blacklist')]);
}
$result = $this->antraglib->createWiederholung($prestudent_id, $studiensemester, getAuthUID(), $repeat);
if(isError($result))
{
return $this->outputJsonError(['db' => getError($result)]);
}
$antragId = getData($result);
$result = $this->antraglib->getDetailsForAntrag($antragId);
if(!hasData($result))
return $this->outputJsonSuccess(true);
$data = getData($result);
$result = $this->antraglib->getFailedExamForPrestudent($prestudent_id);
// NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
$pruefungsdata = current(getData($result));
$data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
$data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
$data->pruefungsdatum = $pruefungsdata->datum;
$this->outputJsonSuccess($data);
}
public function getLvs($antrag_id)
{
$result = $this->antraglib->getLvsForAntrag($antrag_id);
if (isError($result)) {
$error = getError($result);
if ($error == 'Forbidden')
$this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
return $this->outputJsonError(getError($result));
}
$lvs = getData($result);
$this->outputJsonSuccess($lvs);
}
public function saveLvs()
{
$result = $this->getPostJSON();
$antragsLvs = array_merge($result->forbiddenLvs, $result->mandatoryLvs);
$insert = array_map(function ($lv) {
return [
'studierendenantrag_id' => $lv->studierendenantrag_id,
'lehrveranstaltung_id' => $lv->lehrveranstaltung_id,
'note' => $lv->zugelassen
? ($lv->zugelassen == 1 ? 0 : $this->config->item('wiederholung_note_angerechnet'))
: $this->config->item('wiederholung_note_nicht_zugelassen'),
'anmerkung' => $lv->anmerkung,
'insertvon' => getAuthUID(),
'studiensemester_kurzbz' => $lv->studiensemester_kurzbz
];
}, $antragsLvs);
$antrag_ids = array_unique(array_map(function ($lv) {
return $lv['studierendenantrag_id'];
}, $insert));
foreach ($antrag_ids as $antrag_id) {
$result = $this->StudierendenantragModel->loadIdAndStatusWhere([
'studierendenantrag_id' => $antrag_id
]);
if (isError($result))
return $this->outputJsonError(getError($result));
if (!hasData($result))
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id]));
$antrag = current(getData($result));
if ($antrag->status != Studierendenantragstatus_model::STATUS_CREATED && $antrag->status != Studierendenantragstatus_model::STATUS_LVSASSIGNED)
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_antrag_locked'));
}
if(!$antragsLvs)
return $this->outputJsonError($this->p->t('studierendenantrag', 'error_no_lv'));
$result = $this->antraglib->saveLvs($insert);
if (isError($result))
return $this->outputJsonError(getError($result));
$this->outputJsonSuccess(getData($result));
}
public function getLvsAsRdf($prestudent_id)
{
// header für no cache
$this->output->set_header("Cache-Control: no-cache");
$this->output->set_header("Cache-Control: post-check=0, pre-check=0", false);
$this->output->set_header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
$this->output->set_header("Pragma: no-cache");
$this->output->set_header("Content-type: application/xhtml+xml");
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$sem_akt = $this->variablelib->getVar('semester_aktuell');
$result = $this->antraglib->getLvsForPrestudent($prestudent_id, $sem_akt);
if (isError($result)) {
return $this->outputJsonError(getError($result));
}
$lvs = getData($result) ?: [];
$rdf_url = 'http://www.technikum-wien.at/antragnote';
$this->load->view('lehre/Antrag/Wiederholung/getLvs.rdf.php', [
'url' => $rdf_url,
'lvs' => $lvs
]);
}
public function moveLvsToZeugnis()
{
$anzahl = $this->input->post('anzahl');
$student_uid = $this->input->post('student_uid');
$this->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel');
$this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
$errormsg = array();
for($i=0; $i<$anzahl; $i++)
{
$id = $this->input->post('studierendenantrag_lehrveranstaltung_id_' . $i);
$result =$this->StudierendenantraglehrveranstaltungModel->load($id);
if(isError($result))
{
$errormsg[] = getError($result);
}
elseif(!hasData($result))
{
$errormsg[] = $this->p->t('studierendenantrag', 'error_no_lv_in_application');
}
else
{
$antragLv = getData($result)[0];
$result= $this->ZeugnisnoteModel->load([
'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
'student_uid'=> $student_uid,
'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz
]);
if(isError($result))
{
$errormsg[] = getError($result);
}
else
{
if (hasData($result))
{
$result = $this->ZeugnisnoteModel->update(
[
'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
'student_uid'=> $student_uid,
'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz
],
[
'note'=> $antragLv->note,
'uebernahmedatum' => date('c'),
'benotungsdatum' => $antragLv->insertamum,
'updateamum' => date('c'),
'bemerkung'=>$antragLv->anmerkung,
'updatevon'=>getAuthUID()
]
);
}
else
{
$result = $this->ZeugnisnoteModel->insert([
'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
'student_uid'=> $student_uid,
'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz,
'note'=> $antragLv->note,
'uebernahmedatum' => date('c'),
'benotungsdatum' => $antragLv->insertamum,
'insertamum' => date('c'),
'bemerkung'=>$antragLv->anmerkung,
'insertvon'=>getAuthUID()
]);
}
if(isError($result))
{
$errormsg[] = getError($result);
}
}
}
}
if($errormsg)
$return = false;
else
$return = true;
$this->load->view('lehre/Antrag/Wiederholung/moveLvs.rdf.php', [
'return' => $return,
'errormsg' => $errormsg
]);
}
}
@@ -9,6 +9,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
* NOTE: extends the FHC_Controller instead of the Auth_Controller because the FilterCmpt has its
* own permissions check
* TODO(chris): deprecated
*/
class Filter extends FHC_Controller
{
@@ -26,6 +27,9 @@ class Filter extends FHC_Controller
// Loads authentication library and starts authentication
$this->load->library('AuthLib');
// Loads the FiltersModel
$this->load->model('system/Filters_model', 'FiltersModel');
// Loads the FilterCmptLib with HTTP GET/POST parameters
$this->_startFilterCmptLib();
}
@@ -3,7 +3,7 @@
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
* TODO(chris): deprecated
*/
class Phrasen extends FHC_Controller
{
@@ -3,7 +3,7 @@
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
* TODO(chris): deprecated
*/
class SearchBar extends FHC_Controller
{
@@ -17,11 +17,17 @@ class SearchBar extends FHC_Controller
{
parent::__construct();
// Loads the AuthLib and starts the authentication
// Loads the AuthLib _without_ starting the authentication
// NOTE:
// - A user must be authenticated via another controller to access this one
// - It is loaded to be able to call the isLogged function later
$this->load->library('AuthLib');
// Load the library SearchBarLib
$this->load->library('SearchBarLib');
// Checks if the user is authenticated, otherwise returns an error code in JSON format
if (!isLogged()) $this->terminateWithJsonError(SearchBarLib::ERROR_NOT_AUTH);
}
//------------------------------------------------------------------------------------------------------------------
+141 -58
View File
@@ -19,6 +19,8 @@ class AntragJob extends JOB_Controller
// Loads SanchoHelper
$this->load->helper('hlp_sancho_helper');
$this->load->library('AntragLib');
// Load Model
$this->load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
$this->load->model('education/Studierendenantragstatus_model', 'StudierendenantragstatusModel');
@@ -96,7 +98,7 @@ class AntragJob extends JOB_Controller
}
$stgLeitungen[$leitung->uid]['stgs'][] = $antrag->studiengang_kz;
$result = $this->StudiengangModel->load($antrag->studiengang_kz);
$result = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
if (isError($result))
{
$this->logError(getError($result));
@@ -165,9 +167,23 @@ class AntragJob extends JOB_Controller
}
$data['table'] = $data['table_' . DEFAULT_LANGUAGE];
$data['leitungLink'] = APP_ROOT. 'index.ci.php/lehre/Studierendenantrag/leitung';
//Mail an Stgl und Assistenz
$to = $leitung['Details']->uid . '@' . DOMAIN;
$cc = $leitung['Details']->email;
// NOTE(chris): Sancho mail
if (sendSanchoMail("Sancho_Mail_Antrag_Stgl", $data, $leitung['Details']->uid . '@' . DOMAIN, 'Anträge - Aktion(en) erforderlich'))
if (sendSanchoMail(
"Sancho_Mail_Antrag_Stgl",
$data,
$to,
'Anträge - Aktion(en) erforderlich',
DEFAULT_SANCHO_HEADER_IMG,
DEFAULT_SANCHO_FOOTER_IMG,
'',
$cc
))
$count++;
}
@@ -209,8 +225,7 @@ class AntragJob extends JOB_Controller
$count = 0;
foreach ($antraege as $antrag)
{
$this->StudiengangModel->addJoin('public.tbl_prestudent ps','studiengang_kz');
$res = $this->StudiengangModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]);
$res = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
$stg = '';
$orgform = '';
if (hasData($res)) {
@@ -282,7 +297,6 @@ class AntragJob extends JOB_Controller
$result = $this->PruefungModel->getAllPrestudentsWhereCommitteeExamFailed(
[
null,
Studierendenantragstatus_model::STATUS_REQUESTSENT_1,
Studierendenantragstatus_model::STATUS_REQUESTSENT_2
],
@@ -303,11 +317,64 @@ class AntragJob extends JOB_Controller
foreach ($prestudents as $prestudent)
{
$result = $this->prestudentlib->setAbbrecher($prestudent->prestudent_id, $prestudent->studiensemester_kurzbz, $insertvon);
if (isError($result))
$result = $this->StudierendenantragstatusModel->insert([
'studierendenantrag_id' => $prestudent->studierendenantrag_id,
'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED,
'insertvon' => 'AntragJob'
]);
if (isError($result)) {
$this->logError(getError($result));
else
$count++;
} else {
$deregisterStatus = getData($result);
$result = $this->antraglib->pauseAntrag(
$prestudent->studierendenantrag_id,
Studierendenantragstatus_model::INSERTVON_DEREGISTERED
);
if (isError($result))
$this->logError(getError($result));
$result = $this->prestudentlib->setAbbrecher($prestudent->prestudent_id, '', $insertvon);
if (isError($result)) {
$this->StudierendenantragstatusModel->delete($deregisterStatus);
$this->logError(getError($result));
} else {
$count++;
$datum_kp = new DateTime($prestudent->datum);
$dataMail = array(
'name'=> trim($prestudent->vorname . ' '. $prestudent->nachname),
'vorname' => $prestudent->vorname,
'nachname' => $prestudent->nachname,
'pers_kz'=> $prestudent->matrikelnr,
'stg' => $prestudent->bezeichnung,
'lvbezeichnung' => $prestudent->lvbezeichnung,
'datum_kp' => $datum_kp->format('d.m.Y'),
'studiensemester'=> $prestudent->studiensemester_kurzbz,
'Orgform'=> $prestudent->orgform,
'prestudent_id' => $prestudent->prestudent_id,
'fristablauf' => $dateDeadline->format('d.m.Y')
);
$email = $this->StudentModel->getEmailFH($this->StudentModel->getUID($prestudent->prestudent_id));
// Mail to Student
if (!sendSanchoMail('Sancho_Mail_Antrag_W_DL_Stud', $dataMail, $email, 'Wiederholung: Frist abgelaufen')) {
$this->logWarning("Failed to send Notification to " . $email);
}
$result = $this->StudiengangModel->load($prestudent->studiengang_kz);
if (!hasData($result)) {
$this->logWarning('No Studiengang found');
continue;
}
$studiengang = current(getData($result));
$email = $studiengang->email;
// Mail to Assistenz
if (!sendSanchoMail('Sancho_Mail_Antrag_W_DL_Assist', $dataMail, $email, 'Wiederholung: Frist abgelaufen')) {
$this->logWarning("Failed to send Notification to " . $email);
}
}
}
}
$this->logInfo($count . " Students set to Abbrecher");
}
@@ -323,8 +390,6 @@ class AntragJob extends JOB_Controller
{
$this->logInfo('Start Job handleAbmeldungenStglDeadline');
$this->load->library('AntragLib');
$insertvon = $this->config->item('antrag_job_systemuser');
if (!$insertvon) {
$this->logError('Config "antrag_job_systemuser" nicht gesetzt');
@@ -342,11 +407,18 @@ class AntragJob extends JOB_Controller
$dateDeadline = new DateTime();
$dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline));
$this->StudierendenantragModel->addSelect('tbl_studierendenantrag.studierendenantrag_id');
$this->StudierendenantragModel->addSelect('prestudent_id');
$this->StudierendenantragModel->addSelect('studiensemester_kurzbz');
$this->StudierendenantragModel->addSelect('s.insertamum');
$this->StudierendenantragModel->addSelect('s.insertvon');
$this->StudierendenantragModel->addJoin('public.tbl_student pts', 'prestudent_id');
$this->StudierendenantragModel->addSelect('pts.student_uid');
$this->StudierendenantragModel->db->where_in('public.get_rolle_prestudent(prestudent_id, studiensemester_kurzbz)', $this->config->item('antrag_prestudentstatus_whitelist'));
$this->StudierendenantragModel->db->where_in(
'public.get_rolle_prestudent(prestudent_id, studiensemester_kurzbz)',
$this->config->item('antrag_prestudentstatus_whitelist')
);
$result = $this->StudierendenantragModel->getWithLastStatusWhere([
'typ' => Studierendenantrag_model::TYP_ABMELDUNG_STGL,
@@ -365,51 +437,68 @@ class AntragJob extends JOB_Controller
foreach ($antraege as $antrag)
{
$result = $this->prestudentlib->setAbbrecher(
$antrag->prestudent_id,
$antrag->studiensemester_kurzbz,
$insertvon,
'abbrecherStgl',
$antrag->insertamum
);
$result = $this->StudierendenantragstatusModel->insert([
'studierendenantrag_id' => $antrag->studierendenantrag_id,
'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED,
'insertvon' => 'AntragJob'
]);
if (isError($result))
$this->logError(getError($result));
else
{
$count++;
$result = $this->PrestudentModel->load($antrag->prestudent_id);
if(!hasData($result)) {
$this->logWarning('No Prestudent found');
continue;
}
$prestudent = current(getData($result));
$result = $this->StudiengangModel->load($prestudent->studiengang_kz);
if(!hasData($result)) {
$this->logWarning('No Studiengang found');
continue;
}
$studiengang = current(getData($result));
$result = $this->PersonModel->loadPrestudent($antrag->prestudent_id);
if(!hasData($result))
{
$this->logWarning('No Person found');
continue;
}
$person = current(getData($result));
$email = $studiengang->email;
$dataMail = array(
'prestudent' => $antrag->prestudent_id,
'studiensemester' => $antrag->studiensemester_kurzbz,
'name' => trim($person->vorname . ' '. $person->nachname),
);
else {
$deregisterStatus = getData($result);
if(!sendSanchoMail('Sancho_Mail_Antrag_A_Assist', $dataMail, $email, 'Einspruchsfrist abgelaufen'))
{
$this->logWarning("Failed to send Notification to " . $email);
$result = $this->antraglib->pauseAntrag($antrag->studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_DEREGISTERED);
if (isError($result))
$this->logError(getError($result));
$result = $this->prestudentlib->setAbbrecher(
$antrag->prestudent_id,
$antrag->studiensemester_kurzbz,
'AntragJob',
'abbrecherStgl',
$antrag->insertamum,
null,
$antrag->insertvon ?: $insertvon
);
if (isError($result)) {
$this->StudierendenantragstatusModel->delete($deregisterStatus);
$this->logError(getError($result));
} else {
$count++;
$result = $this->PrestudentModel->load($antrag->prestudent_id);
if(!hasData($result)) {
$this->logWarning('No Prestudent found');
continue;
}
$prestudent = current(getData($result));
$result = $this->StudiengangModel->load($prestudent->studiengang_kz);
if(!hasData($result)) {
$this->logWarning('No Studiengang found');
continue;
}
$studiengang = current(getData($result));
$result = $this->PersonModel->loadPrestudent($antrag->prestudent_id);
if(!hasData($result))
{
$this->logWarning('No Person found');
continue;
}
$person = current(getData($result));
$email = $studiengang->email;
$dataMail = array(
'prestudent' => 'UID: ' . $antrag->student_uid . ', PreStudentId: ' . $antrag->prestudent_id,
'studiensemester' => $antrag->studiensemester_kurzbz,
'name' => trim($person->vorname . ' '. $person->nachname),
);
if(!sendSanchoMail('Sancho_Mail_Antrag_A_Assist', $dataMail, $email, 'Einspruchsfrist abgelaufen'))
{
$this->logWarning("Failed to send Notification to " . $email);
}
}
}
}
$this->logInfo($count . " Students set to Abbrecher");
$this->logInfo($count . "/" . count($antraege) . " Students set to Abbrecher");
}
$this->logInfo('Ende Job handleAbmeldungenStglDeadline');
}
@@ -537,12 +626,6 @@ class AntragJob extends JOB_Controller
}
}
$this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
$result = $this->PrestudentstatusModel->loadLastWithStgDetails($prestudent->prestudent_id, $prestudent->studiensemester_kurzbz);
if (hasData($result)) {
$ausbildungssemester = current(getData($result))->semester;
}
$dataMail = array(
'name'=> trim($prestudent->vorname . ' '. $prestudent->nachname),
'vorname' => $prestudent->vorname,
@@ -559,7 +642,7 @@ class AntragJob extends JOB_Controller
'fristablauf' => $fristende->format('d.m.Y'),
'pre_wiederholer_sem' => $next_sem,
'wiederholer_sem' => $sem_after_next_sem,
'sem' => $ausbildungssemester
'sem' => $prestudent->ausbildungssemester
);
// NOTE(chris): Sancho mail
+165
View File
@@ -0,0 +1,165 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
require_once('schedulers/ESIScheduler.php');
/**
* Controller for initialising generateESI job
*/
class ESIJob extends JQW_Controller
{
const ESI_PREFIX = 'urn:schac:personalUniqueCode:int:esi:at:';
const INSERT_VON = 'generateEsiJob';
/**
* Controller initialization
*/
public function __construct()
{
parent::__construct();
// load models
$this->load->model('person/Person_model', 'PersonModel');
$this->load->model('person/Kennzeichen_model', 'KennzeichenModel');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Initialises generateESI job, handles job queue, logs infos/errors
*/
public function generateESI()
{
//$jobType = 'DVUHSendPruefungsaktivitaeten';
$this->logInfo(ESIScheduler::JOB_TYPE_GENERATE_ESI.' job start');
// Gets the latest jobs
$lastJobs = $this->getLastJobs(ESIScheduler::JOB_TYPE_GENERATE_ESI);
if (isError($lastJobs))
{
$this->logError(getCode($lastJobs).': '.getError($lastJobs), ESIScheduler::JOB_TYPE_GENERATE_ESI);
}
else
{
$this->updateJobs(
getData($lastJobs), // Jobs to be updated
array(JobsQueueLib::PROPERTY_START_TIME), // Job properties to be updated
array(date('Y-m-d H:i:s')) // Job properties new values
);
$person_arr = $this->_getInputObjArray(getData($lastJobs));
foreach ($person_arr as $persobj)
{
if (!isset($persobj->person_id))
$this->logError("Error when generating ESI: invalid parameters");
else
{
$person_id = $persobj->person_id;
// check if there already is an active ESI
$this->KennzeichenModel->addSelect('1');
$activeKennzeichenRes = $this->KennzeichenModel->loadWhere(
array('person_id' => $person_id, 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ, 'aktiv' => true)
);
if (hasData($activeKennzeichenRes))
{
$this->logError("Active ESI for person Id $person_id already exists");
continue;
}
// get Matrikelnr for person for which ESI should be generated
$this->PersonModel->addSelect('matr_nr');
$personRes = $this->PersonModel->load($person_id);
if (!hasData($personRes))
{
$this->logError("Person with Id $person_id not found");
continue;
}
$matr_nr = getData($personRes)[0]->matr_nr;
if (isEmptyString($matr_nr))
{
$this->logError("Matrikelnummer for person with Id $person_id is empty");
continue;
}
$esi = self::ESI_PREFIX.$matr_nr;
// check if ESI was already used
$this->KennzeichenModel->addSelect('1');
$existingKennzeichenRes = $this->KennzeichenModel->loadWhere(
array('person_id' => $person_id, 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ, 'inhalt' => $esi)
);
if (hasData($existingKennzeichenRes))
{
$this->logError("ESI $esi for person Id $person_id already exists");
continue;
}
// if everything ok, save the esi for the person
$saveEsiResult = $this->KennzeichenModel->insert(
array(
'person_id' => $person_id,
'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ,
'inhalt' => $esi,
'aktiv' => true,
'insertvon' => self::INSERT_VON
)
);
if (isError($saveEsiResult))
{
$this->logError("Error when sending ESI, person Id $person_id ".getError($saveEsiResult));
}
}
}
// Update jobs properties values
$this->updateJobs(
getData($lastJobs), // Jobs to be updated
array(JobsQueueLib::PROPERTY_STATUS, JobsQueueLib::PROPERTY_END_TIME), // Job properties to be updated
array(JobsQueueLib::STATUS_DONE, date('Y-m-d H:i:s')) // Job properties new values
);
if (hasData($lastJobs)) $this->updateJobsQueue(ESIScheduler::JOB_TYPE_GENERATE_ESI, getData($lastJobs));
}
$this->logInfo(ESIScheduler::JOB_TYPE_GENERATE_ESI.' job stop');
}
// --------------------------------------------------------------------------------------------
// Private methods
/**
* Extracts input data from jobs.
* @param $jobs
* @return array with jobinput
*/
private function _getInputObjArray($jobs)
{
$mergedUsersArray = array();
if (count($jobs) == 0) return $mergedUsersArray;
foreach ($jobs as $job)
{
$decodedInput = json_decode($job->input);
if ($decodedInput != null)
{
foreach ($decodedInput as $el)
{
$mergedUsersArray[] = $el;
}
}
}
return $mergedUsersArray;
}
}
@@ -45,6 +45,7 @@ class IssueResolver extends IssueResolver_Controller
'CORE_STUDENTSTATUS_0013' => 'CORE_STUDENTSTATUS_0013',
'CORE_STUDENTSTATUS_0014' => 'CORE_STUDENTSTATUS_0014',
'CORE_STUDENTSTATUS_0015' => 'CORE_STUDENTSTATUS_0015',
'CORE_STUDENTSTATUS_0016' => 'CORE_STUDENTSTATUS_0016',
'CORE_PERSON_0001' => 'CORE_PERSON_0001',
'CORE_PERSON_0002' => 'CORE_PERSON_0002',
'CORE_PERSON_0003' => 'CORE_PERSON_0003',
@@ -467,7 +467,7 @@ class ReihungstestJob extends JOB_Controller
$this->PrestudentstatusModel->addJoin('public.tbl_person', 'person_id');
$yesterdays_applicants_arr = $this->PrestudentstatusModel->loadWhere('
status_kurzbz = \'Interessent\' AND
status_kurzbz IN (\'Interessent\', \'Bewerber\') AND
typ = \'b\' AND
bestaetigtam = current_date - 1
');
@@ -730,33 +730,27 @@ class ReihungstestJob extends JOB_Controller
tbl_reihungstest.reihungstest_id,
tbl_studienplan.studienplan_id,
tbl_reihungstest.studiensemester_kurzbz,
tbl_studienordnung.studiengang_kz
tbl_studienordnung.studiengang_kz,
tbl_studienplan.orgform_kurzbz
FROM
public.tbl_reihungstest
JOIN public.tbl_rt_studienplan ON(tbl_rt_studienplan.reihungstest_id=tbl_reihungstest.reihungstest_id)
JOIN lehre.tbl_studienplan USING(studienplan_id)
JOIN lehre.tbl_studienordnung USING(studienordnung_id)
JOIN public.tbl_rt_studienplan ON(tbl_rt_studienplan.reihungstest_id=tbl_reihungstest.reihungstest_id)
JOIN lehre.tbl_studienplan USING(studienplan_id)
JOIN lehre.tbl_studienordnung USING(studienordnung_id)
WHERE
NOT EXISTS(
SELECT 1 FROM lehre.tbl_studienplan_semester
WHERE studienplan_id=tbl_rt_studienplan.studienplan_id
AND tbl_studienplan_semester.studiensemester_kurzbz=tbl_reihungstest.studiensemester_kurzbz
EXISTS (
SELECT studienplan_id
FROM lehre.tbl_studienordnung sordnung
JOIN lehre.tbl_studienplan USING (studienordnung_id)
JOIN lehre.tbl_studienplan_semester USING (studienplan_id)
WHERE sordnung.studiengang_kz = tbl_studienordnung.studiengang_kz
AND tbl_studienplan_semester.studiensemester_kurzbz = tbl_reihungstest.studiensemester_kurzbz
AND tbl_studienplan.studienplan_id NOT IN
(
SELECT studienplan_id FROM tbl_rt_studienplan WHERE reihungstest_id = tbl_reihungstest.reihungstest_id
)
)
AND tbl_reihungstest.datum >= now()
AND NOT EXISTS(
SELECT
1
FROM
public.tbl_rt_studienplan rtstp
JOIN lehre.tbl_studienplan stp USING(studienplan_id)
JOIN lehre.tbl_studienordnung sto USING(studienordnung_id)
JOIN lehre.tbl_studienplan_semester stpsem USING(studienplan_id)
WHERE
sto.studiengang_kz=tbl_studienordnung.studiengang_kz
AND rtstp.reihungstest_id=tbl_reihungstest.reihungstest_id
AND stpsem.studiensemester_kurzbz=tbl_reihungstest.studiensemester_kurzbz
)
";
AND tbl_reihungstest.datum >= now()";
$db = new DB_Model();
$result_rt = $db->execReadOnlyQuery($qry);
@@ -766,7 +760,9 @@ class ReihungstestJob extends JOB_Controller
// find an active studyplan for the same degree program with is valid in this semester
$result_stpl = $this->StudienplanModel->getStudienplaeneBySemester(
$row_rt->studiengang_kz,
$row_rt->studiensemester_kurzbz
$row_rt->studiensemester_kurzbz,
null,
$row_rt->orgform_kurzbz
);
if (hasData($result_stpl)) {
@@ -1027,7 +1023,7 @@ class ReihungstestJob extends JOB_Controller
{
$studiengang = $this->StudiengangModel->load($stg);
$mailcontent = '';
$content = false;
foreach ($orgform AS $art=>$value)
{
// Orgform nur dazu schreiben, wenn es mehr als Eine gibt
@@ -1048,6 +1044,7 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '<tr><td style="font-family: verdana, sans-serif; border: 1px solid grey; padding: 3px">'.$bewerber.'</td></tr>';
}
$mailcontent .= '</tbody></table><br><br>';
$content = true;
}
if (isset($value['AufnahmeHoeherePrio']) && !isEmptyArray($value['AufnahmeHoeherePrio']))
{
@@ -1062,6 +1059,7 @@ class ReihungstestJob extends JOB_Controller
$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']))
{
@@ -1075,6 +1073,7 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '<tr><td style="font-family: verdana, sans-serif; border: 1px solid grey; padding: 3px">'.$bewerber.'</td></tr>';
}
$mailcontent .= '</tbody></table>';
$content = true;
}
if ($bcc != '' && isset($value['AbgewiesenWeilBewerber']) && !isEmptyArray($value['AbgewiesenWeilBewerber']))
{
@@ -1089,13 +1088,14 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '<tr><td style="font-family: verdana, sans-serif; border: 1px solid grey; padding: 3px">'.$bewerber.'</td></tr>';
}
$mailcontent .= '</tbody></table>';
$content = true;
}
}
$mailcontent_data_arr['table'] = $mailcontent;
// Send email in Sancho design
if (!isEmptyString($mailcontent))
if (!isEmptyString($mailcontent) && $content === true)
{
sendSanchoMail(
'Sancho_ReihungstestteilnehmerJob',
@@ -0,0 +1,108 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Scheduler for generating ESI (European Student Identifier)
*/
class ESIScheduler extends JQW_Controller
{
const JOB_TYPE_GENERATE_ESI = 'generateESI';
const KENNZEICHENTYP_KURZBZ = 'esi';
private $_active_status_kurzbz = array('Student', 'Diplomand');
/**
* Controller initialization
*/
public function __construct()
{
parent::__construct();
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Creates jobs queue entries for generateESI job.
* @param string $studiensemester_kurzbz semester for which ESIs should be generated
*/
public function generateESI($studiensemester_kurzbz = null)
{
// if no semester given, get current studiensemester
if (!isset($studiensemester_kurzbz))
{
$semRes = $this->StudiensemesterModel->getAkt();
if (hasData($semRes))
{
$studiensemester_kurzbz = getData($semRes)[0]->studiensemester_kurzbz;
}
}
if (isset($studiensemester_kurzbz))
{
$this->logInfo('Start job queue scheduler '.self::JOB_TYPE_GENERATE_ESI);
$qry = "
SELECT
DISTINCT person_id
FROM
public.tbl_person pers
JOIN public.tbl_prestudent ps USING (person_id)
JOIN public.tbl_prestudentstatus pss USING (prestudent_id)
WHERE
pss.studiensemester_kurzbz = ?
AND pers.matr_nr IS NOT NULL
AND pss.status_kurzbz IN ?
AND NOT EXISTS ( -- has no ESI yet
SELECT 1
FROM
public.tbl_kennzeichen
WHERE
person_id = pers.person_id
AND kennzeichentyp_kurzbz = ?
AND aktiv
)
AND NOT EXISTS ( -- making sure it's not an incoming
SELECT 1
FROM
public.tbl_prestudentstatus
WHERE
prestudent_id = ps.prestudent_id
AND status_kurzbz = 'Incoming'
)";
$db = new DB_Model();
$jobInputResult = $db->execReadOnlyQuery($qry, array($studiensemester_kurzbz, $this->_active_status_kurzbz, self::KENNZEICHENTYP_KURZBZ));
// If an error occured then log it
if (isError($jobInputResult))
{
$this->logError(getError($jobInputResult));
}
elseif (hasData($jobInputResult)) // if persons found
{
// Add the new job to the jobs queue
$addNewJobResult = $this->addNewJobsToQueue(
self::JOB_TYPE_GENERATE_ESI, // job type
$this->generateJobs( // gnerate the structure of the new job
JobsQueueLib::STATUS_NEW,
json_encode(getData($jobInputResult))
)
);
// If error occurred return it
if (isError($addNewJobResult)) $this->logError(getError($addNewJobResult));
}
}
else
{
$this->logError('Error when getting Studiensemester');
}
$this->logInfo('End job queue scheduler '.self::JOB_TYPE_GENERATE_ESI);
}
}
@@ -0,0 +1,114 @@
<?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);
}
}
@@ -81,42 +81,9 @@ class Studierendenantrag extends FHC_Controller
public function leitung()
{
$studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe');
$stgsNeuanlage = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
$stgL = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: [];
$stgL = [];
if ($studiengaenge) {
$result = $this->StudiengangModel->loadWithOrgform($studiengaenge);
if (isError($result))
return show_error(getError($result));
$antraege = getData($result) ?: [];
foreach ($antraege as $antrag) {
if (!isset($stgL[$antrag->studiengang_kz])) {
$stgL[$antrag->studiengang_kz] = new stdClass();
$stgL[$antrag->studiengang_kz]->bezeichnung = $antrag->bezeichnung;
$stgL[$antrag->studiengang_kz]->orgform = $antrag->orgform;
$stgL[$antrag->studiengang_kz]->studiengang_kz = $antrag->studiengang_kz;
}
}
}
$stgA = [];
if ($stgsNeuanlage) {
$result = $this->StudiengangModel->loadWithOrgform($stgsNeuanlage);
if (isError($result))
return show_error(getError($result));
$antraege = getData($result) ?: [];
foreach ($antraege as $antrag) {
if (!isset($stgA[$antrag->studiengang_kz])) {
$stgA[$antrag->studiengang_kz] = new stdClass();
$stgA[$antrag->studiengang_kz]->bezeichnung = $antrag->bezeichnung;
$stgA[$antrag->studiengang_kz]->orgform = $antrag->orgform;
$stgA[$antrag->studiengang_kz]->studiengang_kz = $antrag->studiengang_kz;
}
}
}
$stgA = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: [];
$this->load->view('lehre/Antrag/Leitung/List', [
'stgA' => $stgA,
@@ -111,8 +111,13 @@ class requestAnrechnung extends Auth_Controller
$lehrveranstaltung_id = $this->input->post('lv_id');
$studiensemester_kurzbz = $this->input->post('studiensemester');
$bestaetigung = $this->input->post('bestaetigung');
$begruendung_ects = $this->input->post('begruendung_ects');
$begruendung_lvinhalt = $this->input->post('begruendung_lvinhalt');
$begruendung_ects = $this->config->item('explain_equivalence') === TRUE
? $this->input->post('begruendung_ects')
: NULL;
$begruendung_lvinhalt = $this->config->item('explain_equivalence') === TRUE
? $this->input->post('begruendung_lvinhalt')
: NULL;
// Validate data
if (empty($_FILES['uploadfile']['name']))
@@ -124,8 +129,8 @@ class requestAnrechnung extends Auth_Controller
isEmptyString($anmerkung) ||
isEmptyString($lehrveranstaltung_id) ||
isEmptyString($studiensemester_kurzbz) ||
isEmptyString($begruendung_ects) ||
isEmptyString($begruendung_lvinhalt))
($this->config->item('explain_equivalence') === TRUE && isEmptyString($begruendung_ects)) ||
($this->config->item('explain_equivalence') === TRUE && isEmptyString($begruendung_lvinhalt)))
{
return $this->outputJsonError($this->p->t('ui', 'errorFelderFehlen'));
}
@@ -152,10 +157,10 @@ class requestAnrechnung extends Auth_Controller
return $this->outputJsonError($this->p->t('anrechnung', 'antragBereitsGestellt'));
}
// Exit if application is not for actual studysemester
if (!self::_applicationIsForActualSS($studiensemester_kurzbz))
// Exit if application is a past ( < actual ) studysemester
if (self::_applicationIsPastSS($studiensemester_kurzbz))
{
return $this->outputJsonError($this->p->t('anrechnung', 'antragNurImAktSS'));
return $this->outputJsonError($this->p->t('anrechnung', 'antragNichtFuerVerganganeSS'));
}
// Upload document
@@ -168,7 +173,7 @@ class requestAnrechnung extends Auth_Controller
// Hold just inserted DMS ID
$lastInsert_dms_id = $result->retval['dms_id'];
// Save Anrechnung and Anrechnungstatus
$result = $this->AnrechnungModel->createAnrechnungsantrag(
$prestudent_id,
@@ -312,18 +317,21 @@ class requestAnrechnung extends Auth_Controller
}
/**
* Check if applications' study semester is actual study semester.
* Check if applications' study semester is < actual study semester.
*
* @param $studiensemester_kurzbz
* @return bool
*/
private function _applicationIsForActualSS($studiensemester_kurzbz)
private function _applicationIsPastSS($studiensemester_kurzbz)
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->StudiensemesterModel->getNearest();
$actual_ss = getData($result)[0]->studiensemester_kurzbz;
$actual_ss = getData($result)[0];
return $studiensemester_kurzbz == $actual_ss;
$result = $this->StudiensemesterModel->load($studiensemester_kurzbz);
$anrechnung_ss = getData($result)[0];
return $anrechnung_ss->ende < $actual_ss->start;
}
private function _LVhasBlockingGrades($studiensemester_kurzbz, $lehrveranstaltung_id)
@@ -35,6 +35,7 @@ class LehrauftragAkzeptieren extends Auth_Controller
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('codex/Bisverwendung_model', 'BisverwendungModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('vertragsbestandteil/Dienstverhaeltnis_model', 'DienstverhaeltnisModel');
// Load libraries
$this->load->library('WidgetLib');
@@ -94,9 +95,9 @@ class LehrauftragAkzeptieren extends Auth_Controller
'lektor' => true,
'aktiv' => true
));
$is_external_lector = hasData($result) ? true : false;
$view_data = array(
'studiensemester_selected' => $studiensemester_kurzbz,
'is_external_lector' => $is_external_lector
@@ -207,15 +208,41 @@ class LehrauftragAkzeptieren extends Auth_Controller
*/
public function checkInkludierteLehre()
{
$result = $this->BisverwendungModel->getLast($this->_uid, false);
if (hasData($result))
if(defined('DIENSTVERHAELTNIS_SUPPORT') && DIENSTVERHAELTNIS_SUPPORT)
{
$this->outputJsonSuccess(!is_null($result->retval[0]->inkludierte_lehre) && $result->retval[0]->inkludierte_lehre != 0);
// Bei neuer Vertragsstruktur wird nur anhand des echten DVs entschieden ob eine Anzeige
// des Stundensatzes erfolgt oder nicht.
$result = $this->DienstverhaeltnisModel->getDVByPersonUID($this->_uid, null, date('Y-m-d'));
if (hasData($result))
{
$data = getData($result);
foreach($data as $row)
{
if($row->vertragsart_kurzbz == 'echterdv')
$this->outputJsonSuccess(true);
else
$this->outputJsonSuccess(false);
}
}
else
{
$this->outputJsonError(getError($result));
}
}
else
{
$this->outputJsonError(getError($result));
// DEPRECATED
$result = $this->BisverwendungModel->getLast($this->_uid, false);
if (hasData($result))
{
$this->outputJsonSuccess(!is_null($result->retval[0]->inkludierte_lehre) && $result->retval[0]->inkludierte_lehre != 0);
}
else
{
$this->outputJsonError(getError($result));
}
}
}
@@ -0,0 +1,43 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Components extends FHC_Controller
{
/**
* @return void
*/
public function primevue(...$args)
{
$path = implode('/', $args);
$target = FHCPATH . 'vendor/npm-asset/primevue/' . $path;
if (!file_exists($target))
return show_404();
$newUrl = str_repeat('../', count($args));
$ext = substr($path, -7) == '.min.js' ? '.esm.min.js' : '.esm.js';
$contents = file_get_contents($target);
$contents = preg_replace_callback('/import([^;]*)from\s*[\'"]vue[\'"];/i', function ($matches) {
return 'let ' . str_replace(' as ', ': ', $matches[1]) . ' = Vue;';
}, $contents);
$contents = preg_replace_callback('/(import[^;]*[\'"])(primevue[^\'"]+)([\'"])/i', function ($matches) use ($ext, $newUrl) {
if (is_file(FHCPATH . 'vendor/npm-asset/' . $matches[2])) {
$newUrl .= $matches[2];
} else {
$testfile = $matches[2] . '/index' . $ext;
if (file_exists(FHCPATH . 'vendor/npm-asset/' . $testfile))
$newUrl .= $testfile;
else
$newUrl .= $matches[2] . strrchr($matches[2], '/') . $ext;
}
return $matches[1] . $newUrl . $matches[3];
}, $contents);
$this->output->set_content_type('text/javascript');
$this->output->set_output($contents);
}
}
@@ -0,0 +1,759 @@
<?php
/*
* Job zur einmaligen Migration der Mitarbeiterverträge aus der tbl_bisverwendung in die neue
* Vertragsstruktur im HR Schema
*
* Aufruf pro Person
* php index.ci.php system/MigrateContract/index/oesi
*
* Aufruf fuer Alle
* php index.ci.php system/MigrateContract/index
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class MigrateContract extends CLI_Controller
{
private $matching_ba1_vertragsart;
private $OE_DEFAULT;
protected $configerrors;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->load->model('codex/bisverwendung_model', 'BisVerwendungModel');
$this->load->model('person/benutzerfunktion_model', 'BenutzerfunktionModel');
$this->load->config('migratecontract');
$this->OE_DEFAULT = $this->config->item('migratecontract_oe_default');
$this->matching_ba1_vertragsart = $this->config->item('migratecontract_matching_ba1_vertragsart');
$this->configerrors = array();
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function checkConfig()
{
echo "OE_DEFAULT: " . $this->OE_DEFAULT . "\n";
echo "matching_ba1_vertragsart: " . print_r($this->matching_ba1_vertragsart, true);
$this->checkOE_DEFAULT();
$this->checkMatching_ba1_vertragsart();
if( count($this->configerrors) > 0 )
{
foreach($this->configerrors AS $configerror)
{
echo $configerror . "\n";
}
die("Fehler in der Konfiguration. Abbruch!\n");
}
else
{
echo "Konfiguration OK.\n";
}
}
protected function checkOE_DEFAULT()
{
$db = new DB_Model();
$oesql = 'SELECT * FROM public.tbl_organisationseinheit WHERE oe_kurzbz = ?';
$oeres = $db->execReadOnlyQuery($oesql, array($this->OE_DEFAULT));
if( !hasData($oeres) )
{
$this->configerrors[] = 'Default Organisationseinheit: "'
. $this->OE_DEFAULT . '" nicht gefunden.';
}
}
protected function checkMatching_ba1_vertragsart() {
$db = new DB_Model();
foreach( $this->matching_ba1_vertragsart AS $vertragsart_kurzbz )
{
$vasql = 'SELECT * FROM hr.tbl_vertragsart WHERE vertragsart_kurzbz = ?';
$vares = $db->execReadOnlyQuery($vasql, array($vertragsart_kurzbz));
if( !hasData($vares) )
{
$this->configerrors[] = 'Vertragsart "' . $vertragsart_kurzbz
. '" nicht gefunden.';
}
}
}
/**
* Everything has a beginning
*/
public function index($user = null)
{
$this->checkConfig();
if (!is_null($user))
{
$contracts = $this->_transformUser($user);
/*
Format:
$contracts['dv'][]['vbs'][]
*/
//$this->outputJson($contracts);
var_dump($contracts);
$this->_saveJSON($contracts);
}
else
{
$qry = "SELECT distinct mitarbeiter_uid FROM bis.tbl_bisverwendung";
$db = new DB_Model();
$resultUser = $db->execReadOnlyQuery($qry);
if (hasData($resultUser))
{
$users = getData($resultUser);
foreach($users as $user)
{
$contracts = $this->_transformUser($user->mitarbeiter_uid);
$this->_saveJSON($contracts);
}
}
}
}
private function _saveJSON($contracts)
{
$this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel');
$this->load->model('vertragsbestandteil/Vertragsbestandteil_model','VertragsbestandteilModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilStunden_model','VertragsbestandteilStundenModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model','VertragsbestandteilZeitaufzeichnungModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model','VertragsbestandteilFreitextModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model','VertragsbestandteilFunktionModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilKarenz_model','VertragsbestandteilKarenzModel');
$failed = false;
$this->db->trans_begin();
foreach($contracts['dv'] as $row_dv)
{
// Dienstvertrag erstellen
$resultDV = $this->DienstverhaeltnisModel->insert(
array(
'mitarbeiter_uid' => $row_dv['mitarbeiter_uid'],
'vertragsart_kurzbz' => $row_dv['vertragsart_kurzbz'],
'oe_kurzbz' => $row_dv['oe_kurzbz'],
'von' => $row_dv['von'],
'bis' => $row_dv['bis'],
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => 'MigrateContract'
)
);
if (isSuccess($resultDV) && hasData($resultDV))
{
$dv_id = getData($resultDV);
// Vertragsbetandteile erstellen
foreach($row_dv['vbs'] as $row_vbs)
{
$resultVBS = $this->VertragsbestandteilModel->insert(
array(
'dienstverhaeltnis_id' => $dv_id,
'vertragsbestandteiltyp_kurzbz' => $row_vbs['vertragsbestandteiltyp_kurzbz'],
'von' => $row_vbs['von'],
'bis' => $row_vbs['bis'],
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => 'MigrateContract'
)
);
if (isSuccess($resultVBS) && hasData($resultVBS))
{
$vbs_id = getData($resultVBS);
echo 'VBS:'.$vbs_id;
switch($row_vbs['vertragsbestandteiltyp_kurzbz'])
{
case 'stunden':
$resultVBS = $this->_insertVBSStunden($vbs_id, $row_vbs);
break;
case 'zeitaufzeichnung':
$resultVBS = $this->_insertVBSZeitaufzeichnung($vbs_id, $row_vbs);
break;
case 'funktion':
$resultVBS = $this->_insertVBSFunktion($vbs_id, $row_vbs);
break;
case 'freitext':
$resultVBS = $this->_insertVBSFreitext($vbs_id, $row_vbs);
break;
case 'karenz':
$resultVBS = $this->_insertVBSKarenz($vbs_id, $row_vbs);
break;
}
if (isError($resultVBS))
{
echo "FAILED:".getError($resultVBS);
$failed = true;
}
}
else
{
$failed = true;
}
}
}
else
{
$failed = true;
}
}
if(!$failed)
{
$this->db->trans_commit();
}
else
{
echo "ROLLBACK";
$this->db->trans_rollback();
}
}
private function _insertVBSKarenz($vbs_id, $row_vbs)
{
return $this->VertragsbestandteilKarenzModel->insert(
array(
'vertragsbestandteil_id' => $vbs_id,
'karenztyp_kurzbz' => $row_vbs['karenztyp_kurzbz']
)
);
}
private function _insertVBSFreitext($vbs_id, $row_vbs)
{
return $this->VertragsbestandteilFreitextModel->insert(
array(
'vertragsbestandteil_id' => $vbs_id,
'freitexttyp_kurzbz' => $row_vbs['freitexttyp_kurzbz'],
'titel' => $row_vbs['titel'],
'anmerkung' => $row_vbs['anmerkung']
)
);
}
private function _insertVBSFunktion($vbs_id, $row_vbs)
{
return $this->VertragsbestandteilFunktionModel->insert(
array(
'vertragsbestandteil_id' => $vbs_id,
'benutzerfunktion_id' => $row_vbs['benutzerfunktion_id']
)
);
}
private function _insertVBSZeitaufzeichnung($vbs_id, $row_vbs)
{
return $this->VertragsbestandteilZeitaufzeichnungModel->insert(
array(
'vertragsbestandteil_id' => $vbs_id,
'zeitaufzeichnung' => $row_vbs['zeitaufzeichnung'],
'azgrelevant' => $row_vbs['azgrelevant'],
'homeoffice' => $row_vbs['homeoffice']
)
);
}
private function _insertVBSStunden($vbs_id, $row_vbs)
{
return $this->VertragsbestandteilStundenModel->insert(
array(
'vertragsbestandteil_id' => $vbs_id,
'wochenstunden' => $row_vbs['wochenstunden'],
'teilzeittyp_kurzbz' => $row_vbs['teilzeittyp_kurzbz']
)
);
}
/**
* Ermittelt die neue Vertragsstruktur fuer einen User
*/
private function _transformUser($user)
{
$contracts = array();
$this->BisVerwendungModel->addOrder('beginn');
$result_verwendung = $this->BisVerwendungModel->loadWhere(array("mitarbeiter_uid" => $user));
if (isError($result_verwendung))
die("Failed to load Verwendung");
if (hasData($result_verwendung))
{
$verwendung = getData($result_verwendung);
foreach ($verwendung as $row_verwendung)
{
$dv = $this->_getOrCreateDV($contracts, $row_verwendung);
// Ende des DV aktualisieren
if ($contracts['dv'][$dv]['bis'] < $row_verwendung->ende || $row_verwendung->ende == '')
$contracts['dv'][$dv]['bis'] = $row_verwendung->ende;
// Stundenbestandteil pruefen
$this->_addVertragsbestandteilStunden($contracts, $dv, $row_verwendung);
// Befristung
$this->_addVertragsbestandteilFreitextBefristung($contracts, $dv, $row_verwendung);
// All-In
$this->_addVertragsbestandteilFreitextAllIn($contracts, $dv, $row_verwendung);
// Zeitaufzeichnung
$this->_addVertragsbestandteilZeitaufzeichnung($contracts, $dv, $row_verwendung);
// Karenz
$this->_addVertragsbestandteilKarenz($contracts, $dv, $row_verwendung);
// Inkludierte Lehre
// Kuendigungsfrist
// Urlaubsanspruch
}
// Funktion
$this->_addVertragsbestandteilFunktion($contracts, $user);
}
return $contracts;
}
/**
* Fuegt Karenzierungseintraege zu bestehenden Dienstverhaeltnissen hinzu
*/
private function _addVertragsbestandteilKarenz(&$contracts, $dv, $row_verwendung)
{
if ($row_verwendung->beschausmasscode == 5)
{
$dtstart = new DateTime($row_verwendung->beginn);
$dtende = new DateTime($row_verwendung->ende);
$interval = $dtende->diff($dtstart);
$dauer = $interval->format('%a');
// TODO: klären ob das so machbar ist
if ($dauer < 65)
$karenztyp = 'papamonat';
elseif ($dauer < 120)
$karenztyp = 'bildungskarenz';
else
$karenztyp = 'elternkarenz';
// VBS anlegen und Funktion zuweisen
$newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'karenz';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['karenztyp_kurzbz'] = $karenztyp;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['geplanter_geburtstermin'] = null;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['tatsaechlicher_geburtstermin'] = null;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['hint'] = 'Dauer:'.$dauer;
}
}
/**
* Holt die Funktionen die Vertragsrelevant sind und verknüpft diese
*/
private function _addVertragsbestandteilFunktion(&$contracts, $user)
{
// Alle Funktionen holen die Vertragsrelevant sind
$this->BenutzerfunktionModel->addOrder('datum_von');
$this->BenutzerfunktionModel->addJoin('public.tbl_funktion','funktion_kurzbz');
$resultFunktionen = $this->BenutzerfunktionModel->loadWhere(array('uid' => $user, 'vertragsrelevant' => true));
if (isSuccess($resultFunktionen) && hasData($resultFunktionen))
{
$funktionen = getData($resultFunktionen);
foreach ($funktionen as $row_funktion)
{
$funktion_added = 0;
$dv = '';
// Passendes DV suchen
foreach ($contracts['dv'] as $key_dv => $row_contract)
{
// Eine Funktion kann zu mehreren DV zugeordnet sein
// es werden daher alle durchsucht ob es reinfaellt und ggf mehrfach zugeordnet
if ((isset($row_funktion->datum_von) && $row_funktion->datum_von >= $row_contract['von'])
&& ($row_contract['bis'] == '' || $row_contract['bis'] >= $row_funktion->datum_von)
&& (
(
isset($row_funktion->datum_bis) && isset($row_contract['bis'])
&& $row_funktion->datum_bis <= $row_contract['bis']
)
|| $row_funktion->datum_bis == ''
|| (isset($row_funktion->datum_bis) && !isset($row_contract['bis']))
)
)
{
$dv = $key_dv;
// Startdatum und Endedatum ermitteln wenn die Funktion ueber das DV hinausgeht
// Wenn die Dauer laenger ist, wird beim Beginn/Ende des DV abgegrenzt
$dtstart_fkt = new DateTime($row_funktion->datum_von);
$dtstart_dv = new DateTime($row_contract['von']);
if ($dtstart_fkt < $dtstart_dv)
$startdatum = $row_contract['von'];
else
$startdatum = $row_funktion->datum_von;
$dtende_fkt = new DateTime($row_funktion->datum_bis);
$dtende_dv = new DateTime($row_contract['bis']);
if ($dtende_fkt < $dtende_dv)
$endedatum = $row_funktion->datum_bis;
else
$endedatum = $row_contract['bis'];
// VBS anlegen und Funktion zuweisen
$newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'funktion';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $startdatum;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $endedatum;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['benutzerfunktion_id'] = $row_funktion->benutzerfunktion_id;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['hint'] = $row_funktion->funktion_kurzbz.' '.$row_funktion->datum_von.' - '.$row_funktion->datum_bis;
$funktion_added++;
}
}
if ($funktion_added == 0)
{
echo "\nFunktion nicht zugeordnet: ".$row_funktion->funktion_kurzbz.' '.$row_funktion->datum_von.' - '.$row_funktion->datum_bis;
}
}
}
}
/**
* Prueft ob schon ein Vertragsbestandteil fuer Zeitaufzeichnung vorhanden ist das in den Zeitraum passt
* bzw direkt anschließt. Wenn es direkt anschließend ist und die Art gleich sind wird die Laufzeit verlaengert
* Ansonsten wird ein neuer VBS angelegt
*/
private function _addVertragsbestandteilZeitaufzeichnung(&$contracts, $dv, $row_verwendung)
{
if( is_null($row_verwendung->zeitaufzeichnungspflichtig) || is_null($row_verwendung->azgrelevant) )
{
return;
}
if (isset($contracts['dv'][$dv]['vbs']))
{
foreach ($contracts['dv'][$dv]['vbs'] as $index_vbs=>$row_vbs)
{
if ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'zeitaufzeichnung')
{
if ($this->_isVBSAngrenzend($row_verwendung, $row_vbs)
&& $row_vbs['zeitaufzeichnung'] == $row_verwendung->zeitaufzeichnungspflichtig
&& $row_vbs['azgrelevant'] == $row_verwendung->azgrelevant
&& $row_vbs['homeoffice'] == $row_verwendung->homeoffice
)
{
// Zeitaufzeichnungsarten bleiben gleich - Ende des VBS verlaengern
$contracts['dv'][$dv]['vbs'][$index_vbs]['bis'] = $row_verwendung->ende;
return true;
}
}
}
}
// kein passender VBS gefunden - neuen anlegen
$newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'zeitaufzeichnung';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['zeitaufzeichnung'] = $row_verwendung->zeitaufzeichnungspflichtig;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['azgrelevant'] = $row_verwendung->azgrelevant;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['homeoffice'] = $row_verwendung->homeoffice;
return true;
}
/**
* Fueg einen Freitextbestandteil fuer All-In zum DV hinzu
*/
private function _addVertragsbestandteilFreitextAllIn(&$contracts, $dv, $row_verwendung)
{
if ($row_verwendung->ba1code == 111) // All-In
{
$newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'freitext';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['freitexttyp_kurzbz'] = 'allin';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['titel'] = 'allin';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['anmerkung'] = 'allin';
}
return true;
}
/**
* Fueg einen Freitextbestandteil fuer die Berfristung zum DV hinzu
*/
private function _addVertragsbestandteilFreitextBefristung(&$contracts, $dv, $row_verwendung)
{
if ($row_verwendung->ba2code == 1) // Befristung
{
$newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'freitext';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['freitexttyp_kurzbz'] = 'befristung';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['titel'] = 'befristung';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['anmerkung'] = 'befristung';
}
return true;
}
/**
* Prueft ob schon ein Vertragsbestandteil mit diesem Stundenausmass vorhanden ist das in den Zeitraum passt
* bzw direkt anschließt. Wenn es direkt anschließend ist und die Stunden gleich sind wird die Laufzeit verlaengert
* Ansonsten wird ein neuer VBS angelegt
*/
private function _addVertragsbestandteilStunden(&$contracts, $dv, $row_verwendung)
{
// Nur anlegen wenn im aktuellen Eintrag auch Stunden eingetragen sind
if ($row_verwendung->vertragsstunden != '')
{
if (isset($contracts['dv'][$dv]['vbs']))
{
foreach ($contracts['dv'][$dv]['vbs'] as $index_vbs=>$row_vbs)
{
if ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'stunden' || ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'karenz' && $row_verwendung->vertragsstunden === '0.00'))
{
if ($this->_isVBSAngrenzend($row_verwendung, $row_vbs) && ((isset($row_vbs['wochenstunden']) && $row_vbs['wochenstunden'] == $row_verwendung->vertragsstunden) || $row_verwendung->vertragsstunden === '0.00'))
{
// stunden bleiben gleich - Ende des VBS verlaengern
$contracts['dv'][$dv]['vbs'][$index_vbs]['bis'] = $row_verwendung->ende;
return true;
}
}
}
}
// kein passender VBS gefunden - neuen anlegen
$newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'stunden';
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['wochenstunden'] = $row_verwendung->vertragsstunden;
$contracts['dv'][$dv]['vbs'][$newVBSIndex]['teilzeittyp_kurzbz'] = null;
}
return true;
}
/**
* Prueft ob die Verwendung direkt an den Vertragsbestandteil angrenzt
* @return boolean true wenn ja, sonst false
*/
private function _isVBSAngrenzend($verwendung, $vbs)
{
// Beginn Minus 1 Tag
$dtstart = new DateTime($verwendung->beginn);
$dtstartMinus1 = $dtstart->sub(new DateInterval('P1D'))->format('Y-m-d');
if ($vbs['bis'] == ''
|| $vbs['bis'] == $dtstartMinus1)
{
return true;
}
return false;
}
/**
* Create a new DV or Returns the Index of an existing
*/
private function _getOrCreateDV(&$contracts, $row_verwendung)
{
$unternehmen = $this->OE_DEFAULT;
$resultUnternehmen = $this->_getUnternehmen($row_verwendung);
if(hasData($resultUnternehmen))
{
$unternehmen = getData($resultUnternehmen)[0]->oe_kurzbz;
}
else
{
// Fallback Unternehmen wird verwendet falls keine Zuordnung ermittelt werden kann
}
if (isset($contracts['dv']) && is_array($contracts['dv']))
{
foreach($contracts['dv'] as $indexdv => $row_dv)
{
// Vertragsart ist die selbe und selbes Unternehmen
if ($row_dv['vertragsart_kurzbz'] == $this->matching_ba1_vertragsart[$row_verwendung->ba1code]
&& $row_dv['oe_kurzbz'] == $unternehmen
)
{
$dtstart = new DateTime($row_verwendung->beginn);
// Zeitraum passt zur Verwendung
if ($row_dv['von'] <= $row_verwendung->beginn // Beginn Datum Pruefen
&& ( // Ende innerhalb des DV
(isset($row_dv['bis']) && $row_verwendung->ende != '' && ($row_dv['bis'] == '' || $row_dv['bis'] >= $row_verwendung->ende)
)
|| // direkt angrenzend an dieses DV
(isset($row_dv['bis'])
&& ($row_dv['bis'] == ''
|| $row_dv['bis'] == $dtstart->sub(new DateInterval('P1D'))->format('Y-m-d')
)
)
)
)
{
return $indexdv;
}
}
}
}
$newDvIndex = $this->_getNewDVIndex($contracts);
$contracts['dv'][$newDvIndex]['mitarbeiter_uid'] = $row_verwendung->mitarbeiter_uid;
$contracts['dv'][$newDvIndex]['von'] = $row_verwendung->beginn;
$contracts['dv'][$newDvIndex]['bis'] = $row_verwendung->ende;
$contracts['dv'][$newDvIndex]['oe_kurzbz'] = $unternehmen;
$contracts['dv'][$newDvIndex]['vertragsart_kurzbz'] = $this->matching_ba1_vertragsart[$row_verwendung->ba1code];
return $newDvIndex;
}
/**
* Ermittelt in welchem Unternehmen die Person zum betreffenden Zeitpunkt ist.
*/
private function _getUnternehmen($row_verwendung)
{
$resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung'", $row_verwendung->beginn);
// Wenn zeitlich keine passende Unternehmenszuordnung vorhanden ist, dann suchen ob generell eine Zuordnung ermittelt werden kann
if(!hasData($resultUnternehmen))
{
$resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung'");
// Falls nicht wird nach erweiterten Funktionen gesucht um die Zuordnung zu ermitteln.
if(!hasData($resultUnternehmen))
{
$resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung','hilfskraft','Leitung','fbk','fbl'");
}
}
return $resultUnternehmen;
}
/**
* Detailsuche fuer die Ermittlung des Unternehmenszuordnung einer Person
*/
private function _findUnternehmen($uid, $fkt=null, $datum=null)
{
$db = new DB_Model();
$qry = "
WITH RECURSIVE meine_oes(oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz) as
(
SELECT
oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz
FROM
public.tbl_organisationseinheit
WHERE
oe_kurzbz=(SELECT
oe_kurzbz
FROM
public.tbl_benutzerfunktion
WHERE
uid=".$db->escape($uid);
if(!is_null($datum))
$qry.=" AND ".$db->escape($datum)." BETWEEN datum_von AND COALESCE(datum_bis, '2999-12-31')";
if(!is_null($fkt))
$qry.=" AND funktion_kurzbz in ($fkt)";
$qry.="
ORDER BY funktion_kurzbz, datum_von LIMIT 1)
UNION ALL
SELECT
o.oe_kurzbz, o.oe_parent_kurzbz, o.organisationseinheittyp_kurzbz
FROM
public.tbl_organisationseinheit o, meine_oes
WHERE
o.oe_kurzbz=meine_oes.oe_parent_kurzbz
)
SELECT
oe_kurzbz
FROM
meine_oes
WHERE
oe_parent_kurzbz is null
LIMIT 1
";
$resultUnternehmen = $db->execReadOnlyQuery($qry);
return $resultUnternehmen;
}
/**
* Ermittelt den nächsten (freien) Index für den Vertragsbetandteil
*/
private function _getNewVBSIndex($contracts, $dv)
{
if (isset($contracts['dv'][$dv]['vbs']))
return max(array_keys($contracts['dv'][$dv]['vbs'])) + 1;
else
return 0;
}
/**
* Ermittelt den nächsten (freien) Index für das Dienstverhältnis
*/
private function _getNewDVIndex($contracts)
{
if (isset($contracts['dv']) && is_array($contracts['dv']))
return max(array_keys($contracts['dv'])) + 1;
else
return 0;
}
/**
* Habilitation wird aus der Tabelle bis.tbl_bisverwendung in die Tabelle public.tbl_mitarbeiter uebernommen
* Sofern die Person einmal in den Verwendungen eine habiliation eingetragen hat wird diese in den MA-Datensatz übernommen
* Da es in der regel öfter vorkommt dass das hakerl vergessen wurde beim Vertragswechsel als dass die person die habiliation verliert.
*/
public function migrateHabilitation()
{
$this->load->model('ressource/Mitarbeiter_model','MitarbeiterModel');
$db = new DB_Model();
$qry = "
SELECT
distinct mitarbeiter_uid
FROM
bis.tbl_bisverwendung
WHERE
habilitation=true";
$resultHabilitation = $db->execReadOnlyQuery($qry);
if (isSuccess($resultHabilitation) && hasData($resultHabilitation))
{
$habilitationen = getData($resultHabilitation);
foreach ($habilitationen as $row_habilitationen)
{
$this->MitarbeiterModel->update($row_habilitationen->mitarbeiter_uid, array('habilitation'=>true));
}
}
}
}
@@ -0,0 +1,268 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class MigrateHourlyRate extends CLI_Controller
{
CONST DEFAULT_DATE = '1970-01-01';
CONST STUNDENSTAZTYP_LEHRE = 'lehre';
CONST STUNDENSTAZTYP_KALKULATORISCH = 'kalkulatorisch';
private $OE_DEFAULT;
private $_ci;
protected $configerrors;
public function __construct()
{
parent::__construct();
$this->_ci = & get_instance();
$this->load->model('codex/Bisverwendung_model', 'BisVerwendungModel');
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$this->load->model('ressource/Stundensatz_model', 'StundensatzModel');
$this->load->config('migratecontract');
$this->OE_DEFAULT = $this->config->item('migratecontract_oe_default');
$this->configerrors = array();
}
public function checkConfig()
{
echo "OE_DEFAULT: " . $this->OE_DEFAULT . "\n";
$this->checkOE_DEFAULT();
if( count($this->configerrors) > 0 )
{
foreach($this->configerrors AS $configerror)
{
echo $configerror . "\n";
}
die("Fehler in der Konfiguration. Abbruch!\n");
}
else
{
echo "Konfiguration OK.\n";
}
}
public function index($user = null)
{
$this->checkConfig();
echo "Lehre Stundensaetze werden migriert.\n";
$mitarbeiterResult = $this->_getMitarbeiterStunden($user);
if (isError($mitarbeiterResult)) return $mitarbeiterResult;
if (!hasData($mitarbeiterResult)) return error('Keine Mitarbeiterstunden gefunden');
$mitarbeiterArray = getData($mitarbeiterResult);
foreach ($mitarbeiterArray as $mitarbeiter)
{
$this->_getUnternehmen($mitarbeiter);
$insertResult = $this->_addStundensatz($mitarbeiter, self::STUNDENSTAZTYP_LEHRE, self::DEFAULT_DATE);
if (isError($insertResult)) return $insertResult;
}
if( $this->checkIfSAPSyncTableExists() )
{
echo "SAP Sync Tabelle gefunden. SAP Stundensaetze werden migriert.\n";
$sapResult = $this->_getSapStunden($user);
if (isError($sapResult)) return $sapResult;
if (!hasData($sapResult)) return error('Keinen kalkulatorischen Stundensaetze gefunden');
$mitarbeiterArray = getData($sapResult);
foreach ($mitarbeiterArray as $mitarbeiter)
{
$this->_getUnternehmen($mitarbeiter);
$insertResult = $this->_addStundensatz($mitarbeiter, self::STUNDENSTAZTYP_KALKULATORISCH, date_format(date_create($mitarbeiter->beginn), 'Y-m-d'));
if (isError($insertResult)) return $insertResult;
}
}
else
{
echo "SAP Sync Tabelle nicht gefunden. Ignoriere SAP Stundensaetze.\n";
}
}
protected function checkOE_DEFAULT()
{
$db = new DB_Model();
$oesql = 'SELECT * FROM public.tbl_organisationseinheit WHERE oe_kurzbz = ?';
$oeres = $db->execReadOnlyQuery($oesql, array($this->OE_DEFAULT));
if( !hasData($oeres) )
{
$this->configerrors[] = 'Default Organisationseinheit: "'
. $this->OE_DEFAULT . '" nicht gefunden.';
}
}
protected function checkIfSAPSyncTableExists()
{
$dbModel = new DB_Model();
$params = array(
DB_NAME,
'sync',
'tbl_sap_stundensatz'
);
$sql = "SELECT
1 AS exists
FROM
information_schema.tables
WHERE
table_catalog = ? AND
table_schema = ? AND
table_name = ?";
$res = $dbModel->execReadOnlyQuery($sql, $params);
if( hasData($res) )
{
return true;
}
else
{
return false;
}
}
private function _getSapStunden($user = null)
{
$dbModel = new DB_Model();
$params = array();
$qry = "SELECT ss.mitarbeiter_uid as uid,
ss.sap_kalkulatorischer_stundensatz as stundensatz,
ss.insertamum as beginn
FROM sync.tbl_sap_stundensatz ss
WHERE ss.sap_kalkulatorischer_stundensatz IS NOT NULL";
if (!is_null($user))
{
$qry .= " AND ss.mitarbeiter_uid = ? ";
$params[] = $user;
}
$qry .= " ORDER BY ss.mitarbeiter_uid";
return $dbModel->execReadOnlyQuery($qry, $params);
}
private function _getMitarbeiterStunden($user = null)
{
$dbModel = new DB_Model();
$params = array();
$qry = "SELECT mitarbeiter.mitarbeiter_uid as uid,
stundensatz
FROM public.tbl_mitarbeiter mitarbeiter
WHERE mitarbeiter.stundensatz != 0.00
AND mitarbeiter.stundensatz IS NOT NULL";
if (!is_null($user))
{
$qry .= " AND mitarbeiter.mitarbeiter_uid = ?";
$params[] = $user;
}
$qry .= " ORDER BY mitarbeiter.mitarbeiter_uid";
return $dbModel->execReadOnlyQuery($qry, $params);
}
private function _addStundensatz($mitarbeiter, $stundensatztyp, $gueltig_von)
{
return $this->_ci->StundensatzModel->insert(
array(
'uid' => $mitarbeiter->uid,
'stundensatztyp' => $stundensatztyp,
'stundensatz' => $mitarbeiter->stundensatz,
'oe_kurzbz' => $mitarbeiter->unternehmen,
'gueltig_von' => $gueltig_von,
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => 'MigrateHours'
)
);
}
private function _getUnternehmen(&$mitarbeiter)
{
$bvResult = $this->_ci->BisVerwendungModel->getLast($mitarbeiter->uid);
$beginn = null;
if (hasData($bvResult))
{
$beginn = getData($bvResult)[0]->beginn;
}
$unternehmenResult = $this->_findUnternehmen($mitarbeiter->uid, "'kstzuordnung', 'oezuordnung'", $beginn);
if(!hasData($unternehmenResult)) //&& hasData($bvResult)
{
$unternehmenResult = $this->_findUnternehmen($mitarbeiter->uid, "'kstzuordnung', 'oezuordnung'");
}
$unternehmen = $this->OE_DEFAULT;
if (hasData($unternehmenResult))
$unternehmen = getData($unternehmenResult)[0]->oe_kurzbz;
$mitarbeiter->unternehmen = $unternehmen;
}
/**
* Detailsuche fuer die Ermittlung des Unternehmenszuordnung einer Person
*/
private function _findUnternehmen($uid, $fkt=null, $datum=null)
{
$dbModel = new DB_Model();
$qry = "
WITH RECURSIVE meine_oes(oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz) as
(
SELECT
oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz
FROM
public.tbl_organisationseinheit
WHERE
oe_kurzbz=(SELECT
oe_kurzbz
FROM
public.tbl_benutzerfunktion
WHERE
uid=".$dbModel->escape($uid);
if(!is_null($datum))
$qry.=" AND ".$dbModel->escape($datum)." BETWEEN datum_von AND COALESCE(datum_bis, '2999-12-31')";
if(!is_null($fkt))
$qry.=" AND funktion_kurzbz in ($fkt)";
$qry.="
ORDER BY funktion_kurzbz, datum_von LIMIT 1)
UNION ALL
SELECT
o.oe_kurzbz, o.oe_parent_kurzbz, o.organisationseinheittyp_kurzbz
FROM
public.tbl_organisationseinheit o, meine_oes
WHERE
o.oe_kurzbz=meine_oes.oe_parent_kurzbz
)
SELECT
oe_kurzbz
FROM
meine_oes
WHERE
oe_parent_kurzbz is null
LIMIT 1
";
return $dbModel->execReadOnlyQuery($qry);
}
}
@@ -0,0 +1,495 @@
<?php
/*
* Job zur einmaligen Import der Gehälter
*
* Aufruf (Encode / im Filenmae mit %2F):
* php index.ci.php system/MigrateSalary/import filename
*
*/
/*
AUFBAU CSV:
SVNR;Pers-Nr;Name;Dienstverhältnis;LA-Nr;Bezeichnung;2022-09-01;2022-10-01;2022-11-01;2022-12-01;2023-01-01;2023-02-01;2023-03-01
XXXX XXXXXX;00;Name;5;1000;Gehalt;1.111,10;1.211,10;1.311,10;1.411,10;1.511,10;1.611,10;1.711,10
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class MigrateSalary extends CLI_Controller
{
private $OE_DEFAULT = 'gst';
private $GEHALT_BEGINN_SPALTE = 6; // Beginnend mit 0 => G
private $INDEX_LOHNART = 4;
private $INDEX_BEZEICHNUNG = 5;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->load->model('vertragsbestandteil/Gehaltsbestandteil_model', 'GehaltsbestandteilModel');
$this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel');
$this->load->model('vertragsbestandteil/Vertragsbestandteil_model','VertragsbestandteilModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilStunden_model','VertragsbestandteilStundenModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model','VertragsbestandteilFreitextModel');
$this->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model','VertragsbestandteilFunktionModel');
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Everything has a beginning
*/
public function import($file)
{
// CSV Laden
$file = urldecode($file);
if($handle = fopen($file, "r"))
{
$csvrow = -1;
$lastuser = '';
$monate = array();
$gehaltsarr = array();
$gehaltsindex = 0;
while (($data = fgetcsv($handle, null, ';')) !== FALSE)
{
$csvrow++;
// Kopfzeile ueberspringen
if($csvrow == 0)
{
for($i = $this->GEHALT_BEGINN_SPALTE; $i < count($data); $i++)
{
$monate[] = $data[$i];
}
continue;
}
// User zur SVNR ermitteln
$svnr = str_replace(' ', '',$data[0]);
$resultuser = $this->_getUser($svnr);
if(!hasData($resultuser))
{
echo getError($resultuser);
break;
}
$user = getData($resultuser)[0]->mitarbeiter_uid;
echo "\nUser:".$user;
if($user != $lastuser && $lastuser != '')
{
$this->_saveGehalt($lastuser, $gehaltsarr);
$gehaltsarr = array();
$gehaltsindex = 0;
$lastuser = $user;
}
else
{
$lastuser = $user;
}
// Gehalt Clustern
$monat = 0;
for ($i = $this->GEHALT_BEGINN_SPALTE; $i < count($data); $i++)
{
if (count($gehaltsarr) == 0 && $data[$i] != '')
{
$gehaltsarr[$gehaltsindex]['betrag'] = $data[$i];
$gehaltsarr[$gehaltsindex]['lohnart'] = $data[$this->INDEX_LOHNART];
$gehaltsarr[$gehaltsindex]['bezeichnung'] = $data[$this->INDEX_BEZEICHNUNG];
$gehaltsarr[$gehaltsindex]['beginn'] = $monate[$monat];
}
else
{
if ($data[$i] != ''
&& isset($gehaltsarr[$gehaltsindex]) && isset($gehaltsarr[$gehaltsindex]['betrag'])
&& $gehaltsarr[$gehaltsindex]['betrag'] == $data[$i])
{
// Gehalt bleibt gleich
}
else
{
if ($data[$i] != '')
{
// Gehalt hat sich geändert
if ($monat != 0 && isset($gehaltsarr[$gehaltsindex]))
$gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1];
$gehaltsindex++;
$gehaltsarr[$gehaltsindex]['betrag'] = $data[$i];
$gehaltsarr[$gehaltsindex]['lohnart'] = $data[$this->INDEX_LOHNART];
$gehaltsarr[$gehaltsindex]['bezeichnung'] = $data[$this->INDEX_BEZEICHNUNG];
$gehaltsarr[$gehaltsindex]['beginn'] = $monate[$monat];
}
elseif(isset($gehaltsarr[$gehaltsindex]))
{
// Gehalt wurde beendet
if($monat!=0)
$gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1];
$gehaltsindex++;
}
}
}
$monat++;
}
// Zeile zu Ende - Ende Datum setzen wenn nicht für alle Monate ein Eintrag vorhanden ist
if($monat < count($monate) && isset($gehaltsarr[$gehaltsindex]))
$gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1];
}
$this->_saveGehalt($lastuser, $gehaltsarr);
}
}
/**
* Ermittelt das passende Dienstverhaeltnis uns speichert den
* Gehaltsbestandteil
*/
private function _saveGehalt($uid, $gehaltsarr)
{
$failed = false;
$this->db->trans_begin();
foreach($gehaltsarr as $row_gehalt)
{
//var_dump($row_gehalt);
$auszahlungen = 14;
$dvid = '';
$vbsid = '';
$typ = '';
$allin = false;
//DV und VBS Ermitteln
$dv = $this->DienstverhaeltnisModel->getDVByPersonUID($uid, $this->OE_DEFAULT, $row_gehalt['beginn']);
// Wenn keiner gefunden wird oder mit Monatsersteln nur ein externer gefunden wird, weitersuchen ob im Monat noch ein
// "richtiger" Vertrag startet
if (!hasData($dv) || getData($dv)[0]->vertragsart_kurzbz='externerLehrender')
{
$date = new DateTime($row_gehalt['beginn']);
$date->modify('last day of this month');
$last_day_this_month = $date->format('Y-m-d');
// Wenn mit Monatsersten kein DV gefunden wird, wird stattdessen mit Monatsletzten gesucht um DVs zu finden
// für Personen die erst später im Monat in ihr DV einsteigen
$dv = $this->DienstverhaeltnisModel->getDVByPersonUIDOverlapping($uid, $this->OE_DEFAULT, $row_gehalt['beginn'], $last_day_this_month);
if (!hasData($dv))
{
echo "\nKein passendes DV gefunden für User ".$uid." und Datum ".$row_gehalt['beginn']." -> ROLLBACK\n";
$failed = true;
break;
}
else
{
$resultdata = getData($dv);
foreach($resultdata as $dvdata)
{
// Externer DV wird in Monatsmitte zu echten DV - daher weitersuchen bei externenDVs da
// diese sowieso kein Gehalt zugeordnet haben
if($dvdata->vertragsart_kurzbz != 'externerLehrender')
{
$dvid = $dvdata->dienstverhaeltnis_id;
// Gehaltsstart wird auf den Start des DV korrigiert wenn nicht der Monatserste
// nur wenn das Beginndatum vor dem DV-Start liegt da sonst das Datum korrigiert wird
// wenn der Vertragsbestandteil wechselt
if($row_gehalt['beginn'] < $dvdata->von)
$row_gehalt['beginn'] = $dvdata->von;
break;
}
}
}
}
else
{
$resultdata = getData($dv);
if (count($resultdata) == 1)
$dvid = $resultdata[0]->dienstverhaeltnis_id;
}
if ($dvid == '')
{
echo "Kein oder mehrere DVs gefunden -> ROLLBACK";
$failed = true;
break;
}
$allin = $this->_isAllIn($dvid, $row_gehalt['beginn']);
$db = new DB_Model();
$resultVBS = $this->_getVBS($dvid, $row_gehalt['beginn']);
if (hasData($resultVBS))
{
$vbsid = getData($resultVBS)[0]->vertragsbestandteil_id;
$vbsbis = getData($resultVBS)[0]->bis;
}
else
{
echo "Vertragsbestandteil fuer $uid DV $dvid wurde nicht gefunden mit Beginn ".$row_gehalt['beginn']."-> ROLLBACK";
$failed = true;
break;
}
if ($row_gehalt['lohnart'] == 1000)
{
if($allin)
$typ = 'grundgehalt';
else
$typ = 'basisgehalt';
}
elseif ($row_gehalt['lohnart']==1041 // 14x
|| $row_gehalt['lohnart']==1042 // 12x
|| $row_gehalt['lohnart']==3410) // USTDPausch
{
$typ = 'zusatzvereinbarung';
// Freitextbestandteil anlegen fuer die Zulage
// Gaehalt wird der Zuglage zugeordnet
$data = array(
'dienstverhaeltnis_id' => $dvid,
'von' => $row_gehalt['beginn'],
'vertragsbestandteiltyp_kurzbz' => 'freitext',
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => 'MigrateSalary'
);
if (isset($row_gehalt['ende']) && $row_gehalt['ende']!='')
$data['bis'] = $row_gehalt['ende'];
$resultVBS = $this->VertragsbestandteilModel->Insert($data);
if(!isSuccess($resultVBS))
{
echo "VBS kann nicht erstellt werden -> ROLLBACK";
$failed = true;
break;
}
$vbsid = getData($resultVBS);
$data = array(
'vertragsbestandteil_id' => $vbsid,
'freitexttyp_kurzbz' => 'zusatzvereinbarung',
'titel' => $row_gehalt['bezeichnung'],
'anmerkung' => $row_gehalt['bezeichnung'],
);
$resultVBSFreitext = $this->VertragsbestandteilFreitextModel->Insert($data);
if(!isSuccess($resultVBSFreitext))
{
echo "VBS Freitext Zusatz kann nicht erstellt werden -> ROLLBACK";
$failed = true;
break;
}
}
elseif ($row_gehalt['lohnart']==9999) // All-In Custom Lohnart nicht per Default vorhanden
{
$typ = 'zulage';
// Freitextbestandteil anlegen fuer die Zulage
// Gaehalt wird der Zuglage zugeordnet
$data = array(
'dienstverhaeltnis_id' => $dvid,
'von' => $row_gehalt['beginn'],
'vertragsbestandteiltyp_kurzbz' => 'freitext',
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => 'MigrateSalary'
);
if (isset($row_gehalt['ende']) && $row_gehalt['ende']!='')
$data['bis'] = $row_gehalt['ende'];
$resultVBS = $this->VertragsbestandteilModel->Insert($data);
if(!isSuccess($resultVBS))
{
echo "VBS AllIn kann nicht erstellt werden -> ROLLBACK";
$failed = true;
break;
}
$vbsid = getData($resultVBS);
$data = array(
'vertragsbestandteil_id' => $vbsid,
'freitexttyp_kurzbz' => 'allin',
'titel' => $row_gehalt['bezeichnung'],
'anmerkung' => $row_gehalt['bezeichnung'],
);
$resultVBSFreitext = $this->VertragsbestandteilFreitextModel->Insert($data);
if(!isSuccess($resultVBSFreitext))
{
echo "VBS Freitext AllIn Zusatz kann nicht erstellt werden -> ROLLBACK";
$failed = true;
break;
}
}
elseif($row_gehalt['lohnart']==5500) // ATZ
{
$typ = 'lohnausgleichatz';
}
else
{
$typ = 'unbekannt - '.$row_gehalt['lohnart'];
echo "\nGehaltstyp unbekannt Lohnart: ".$row_gehalt['lohnart']." -> ROLLBACK";
$failed = true;
break;
}
// Zulage 12x und Zulage 14x aus der Bezeichnung ermitteln
if(strstr($row_gehalt['bezeichnung'], '12x'))
{
$auszahlungen = 12;
}
// Format ist 7.777,77 und wird umformattiert in 7777.77
$betrag = str_replace('.','', $row_gehalt['betrag']);
$betrag = str_replace(',','.',$betrag);
$data = array(
'dienstverhaeltnis_id' => $dvid,
'vertragsbestandteil_id' => $vbsid,
'gehaltstyp_kurzbz' => $typ,
'von' => $row_gehalt['beginn'],
'grundbetrag' => $betrag,
'betrag_valorisiert' => $betrag,
'anmerkung' => $row_gehalt['bezeichnung'],
'valorisierung' => true,
'auszahlungen' => $auszahlungen,
'insertamum' => date('Y-m-d H:i:s'),
'insertvon' => 'MigrateSalary',
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => 'MigrateSalary'
);
if (isset($row_gehalt['ende']) && $row_gehalt['ende'] != '')
{
// Im Ende steht noch der Monatserste des letzten Monats
// Das muss geaendert werden auf den Monatsletzten oder das Ende des DVs
$date = new DateTime($row_gehalt['ende']);
$date->modify('last day of this month');
$last_day_this_month = $date->format('Y-m-d');
// Wenn das Dienstverhaeltnis in diesem Monat endet und nicht der Monatsletzte ist,
// dann muss hier das Ende Datum des DV stehen bzw das Ende
// oder das Ende des VBS falls die Person in der Monatsmitte Stunden wechselt
$data['bis'] = $last_day_this_month;
// Wenn der Vertragsbestandteil endet bevor das Gehalt endet, dann wir das Gehaltsende auf VBS Ende gesetzt
//echo "Ende des VBS: $vbsbis Ende des Gehalt: ".$data['bis'];
if ($vbsbis != '' && $vbsbis < $data['bis'])
{
$data['bis'] = $vbsbis;
//echo "Gehalt auf vbs ende gesetzt";
}
}
$ret = $this->GehaltsbestandteilModel->insert($data,
$this->GehaltsbestandteilModel->getEncryptedColumns()
);
}
if(!$failed)
{
$this->db->trans_commit();
}
else
{
echo "ROLLBACK";
$this->db->trans_rollback();
}
}
/**
* Prueft ob ein AllIn Vertrag vorhanden ist
*/
private function _isAllIn($dvid, $datum)
{
$db = new DB_Model();
$qry = "
SELECT
*
FROM
hr.tbl_vertragsbestandteil
JOIN hr.tbl_vertragsbestandteil_freitext USING(vertragsbestandteil_id)
WHERE
dienstverhaeltnis_id=".$db->escape($dvid)."
AND vertragsbestandteiltyp_kurzbz='freitext'
AND ".$db->escape($datum)." BETWEEN von AND COALESCE(bis, '2999-12-31')
AND freitexttyp_kurzbz='allin'";
$resultAllIn = $db->execReadOnlyQuery($qry);
if (hasData($resultAllIn))
return true;
else
return false;
}
private function _getVBS($dvid, $datum)
{
$db = new DB_Model();
$qry = "
SELECT
*
FROM
hr.tbl_vertragsbestandteil
WHERE
dienstverhaeltnis_id=".$db->escape($dvid)."
AND vertragsbestandteiltyp_kurzbz='stunden'
AND ".$db->escape($datum)." BETWEEN von AND COALESCE(bis, '2999-12-31')";
$resultVBS = $db->execReadOnlyQuery($qry);
return $resultVBS;
}
/**
* Ermittelt den User zu einer SVNR
*/
private function _getUser($svnr)
{
$db = new DB_Model();
$qry = "
SELECT
mitarbeiter_uid
FROM
public.tbl_person
JOIN public.tbl_benutzer using(person_id)
JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid)
WHERE
tbl_person.svnr = ". $db->escape($svnr)."
AND EXISTS(
SELECT
1
FROM
hr.tbl_dienstverhaeltnis
WHERE
mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid
AND oe_kurzbz=". $db->escape($this->OE_DEFAULT)."
)
ORDER BY tbl_benutzer.aktiv DESC
LIMIT 1;
";
$result = $db->execReadOnlyQuery($qry);
if (hasdata($result))
{
return $result;
}
else
return error('Kein Benutzer mit DV und SVNR:'.$svnr.' gefunden');
}
}
@@ -22,6 +22,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
* This controller operates between (interface) the JS (GUI) and the NavigationLib (back-end)
* Provides data to the ajax get calls about the filter
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
* TODO(chris): deprecated
*/
class Navigation extends FHC_Controller
{
@@ -0,0 +1,32 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Test VBform Vue Component
*/
class TestVBform extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'system/developer:r'
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Everything has a beginning
*/
public function index()
{
$this->load->view('system/logs/testVBform.php');
}
}
@@ -37,7 +37,7 @@ class FASMessages extends Auth_Controller
// Loads the view to write a new message with a template
$this->load->view(
'system/messages/htmlWriteTemplate',
'system/messages/FAShtmlWriteTemplate',
$this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents)
);
}
@@ -53,7 +53,7 @@ class FASMessages extends Auth_Controller
// Loads the view to write a new message with a template
$this->load->view(
'system/messages/htmlWriteTemplate',
'system/messages/FAShtmlWriteTemplate',
$this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents, $message_id, $recipient_id)
);
}
+123 -18
View File
@@ -7,6 +7,10 @@ if (!defined('BASEPATH')) exit('No direct script access allowed');
*/
abstract class Auth_Controller extends FHC_Controller
{
// Special Permissions
const PERM_ANONYMOUS = 'anonymous'; // Everyone
const PERM_LOGGED = 'logged_in'; // Every registered user
/**
* Extends this controller if authentication is required
*/
@@ -14,17 +18,41 @@ abstract class Auth_Controller extends FHC_Controller
{
parent::__construct();
// Loads authentication library and starts authentication
$this->load->library('AuthLib');
if (!is_array($requiredPermissions) || isEmptyArray($requiredPermissions))
show_error('The given permissions is not a valid array or it is an empty one');
if (!isset($requiredPermissions[$this->router->method]))
show_error('The given permission array does not contain the given method or is not correctly set');
$anonAllowed = false;
if ($requiredPermissions[$this->router->method] == self::PERM_ANONYMOUS)
$anonAllowed = true;
elseif (is_array($requiredPermissions[$this->router->method])
&& in_array(self::PERM_ANONYMOUS, $requiredPermissions[$this->router->method]))
$anonAllowed = true;
// Checks if the caller is allowed to access to this content
$this->_isAllowed($requiredPermissions);
if ($anonAllowed) {
// Loads authentication library without authentication
$this->load->library('AuthLib', [false]);
// Loads helper since it would only be called on authentication
$this->load->helper('hlp_authentication');
} else {
// Loads authentication library and starts authentication
$this->load->library('AuthLib');
// Checks if the caller is allowed to access to this content
$this->_isAllowed($requiredPermissions);
}
}
/**
* Checks if the caller is allowed to access to this content with the given permissions
* If it is not allowed will set the HTTP header with code 401
* Wrapper for permissionlib->isEntitled
*
* @param array $requiredPermissions
* @return void
*/
private function _isAllowed($requiredPermissions)
{
@@ -34,28 +62,105 @@ abstract class Auth_Controller extends FHC_Controller
// Checks if this user is entitled to access to this content
if (!$this->permissionlib->isEntitled($requiredPermissions, $this->router->method))
{
$this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized
$this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output
// Prints the main error message
$this->eprintflib->printError('You are not allowed to access to this content');
// Prints the called controller name
$this->eprintflib->printInfo('Controller name: '.$this->router->class);
// Prints the called controller method name
$this->eprintflib->printInfo('Method name: '.$this->router->method);
// Prints the required permissions needed to access to this method
$this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method));
$this->_outputAuthError($requiredPermissions);
exit; // immediately terminate the execution
}
}
/**
* Checks for Permissions depending if the given person is a
* Mitarbeiter and/or Student
* and exits/outputs an error if they are not met.
*
* @param integer $person_id
* @param array $permMa Perms if the person is a Mitarbeiter
* @param array $permStud Perms if the person is a Student
*
* @return void
*/
protected function checkPermissionsForPerson($person_id, $permMa, $permStud)
{
$res = $this->hasPermissionsForPerson($person_id, $permMa, $permStud);
if ($res) {
$perm = array_keys(array_flip(array_merge($res|1 ? $permMa : [], $res|2 ? $permStud : [])));
$this->_outputAuthError([$this->router->method => $perm]);
}
}
/**
* Checks for Permissions depending if the given person is a
* Mitarbeiter and/or Student
* and returns the result.
*
* @param integer $person_id
* @param array $permMa Perms if the person is a Mitarbeiter
* @param array $permStud Perms if the person is a Student
*
* @return boolean
*/
protected function hasPermissionsForPerson($person_id, $permMa, $permStud)
{
$res = 0;
$this->load->model('person/Person_model', 'PersonModel');
$this->PersonModel->addJoin('public.tbl_benutzer', 'person_id');
$this->PersonModel->addJoin('public.tbl_mitarbeiter', 'uid = mitarbeiter_uid');
$result = $this->PersonModel->load($person_id);
if (hasData($result)) {
if ($this->permissionlib->isEntitled(['a' => $permMa], 'a'))
return 0;
$res = 1;
}
$this->PersonModel->addJoin('public.tbl_prestudent', 'person_id');
$result = $this->PersonModel->load($person_id);
if (hasData($result)) {
$permStudConverted = [];
foreach (getData($result) as $row) {
foreach ($permStud as $k => $v) {
if (!isset($permStudConverted[$k])) {
$permStudConverted[$k] = $this->permissionlib->convertAccessType($v);
}
if ($this->permissionlib->isBerechtigt($permStudConverted[$k][0], $permStudConverted[$k][1], $row->studiengang_kz))
return 0;
}
}
$res += 2;
}
return $res;
}
/**
* Outputs an error message and sets the HTTP Header.
* This function is protected so that it can be overwritten.
*
* @param array $requiredPermissions
* @return void
*/
protected function _outputAuthError($requiredPermissions)
{
$this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized
$this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output
// Prints the main error message
$this->eprintflib->printError('You are not allowed to access to this content');
// Prints the called controller name
$this->eprintflib->printInfo('Controller name: '.$this->router->class);
// Prints the called controller method name
$this->eprintflib->printInfo('Method name: '.$this->router->method);
// Prints the required permissions needed to access to this method
$this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method));
}
/**
* Converts an array of permissions to a string that contains them as a comma separated list
* Ex: "<permission 1>, <permission 2>, <permission 3>"
*
* @param array $requiredPermissions
* @param string $method
* @return void
*/
private function _rpsToString($requiredPermissions, $method)
final protected function _rpsToString($requiredPermissions, $method)
{
$strRequiredPermissions = ''; // string that contains all the required permissions needed to access to this method
+51
View File
@@ -0,0 +1,51 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class CI3_Events
{
const PRIORITY_LOW = 200;
const PRIORITY_NORMAL = 100;
const PRIORITY_HIGH = 10;
private static $events = [];
private static $eventsSorted = [];
public static function on($event, $function, $priority = self::PRIORITY_NORMAL)
{
if (!isset(self::$events[$event]))
self::$events[$event] = [];
self::$events[$event][] = [$priority, $function];
if (!isset(self::$eventsSorted[$event]))
self::$eventsSorted[$event] = true;
else
self::$eventsSorted[$event] = false;
}
public static function trigger($event, ...$args)
{
if (!isset(self::$events[$event]))
return;
if (!self::$eventsSorted[$event]) {
usort(self::$events[$event], function ($a, $b) {
return $a[0] - $b[0];
});
self::$eventsSorted[$event] = true;
}
foreach (self::$events[$event] as $conf) {
$conf[1](...$args);
}
}
}
/**
* NOTE(chris): Autoload Events config
*/
require_once(APPPATH.'config/Events.php');
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';
+297 -28
View File
@@ -1,5 +1,24 @@
<?php
/**
* Copyright (C) 2023 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/>.
*/
use \stdClass as stdClass;
if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
@@ -27,6 +46,15 @@ class DB_Model extends CI_Model
const PGSQL_INT8_TYPE = 'int8';
const PGSQL_FLOAT4_TYPE = 'float4';
const PGSQL_FLOAT8_TYPE = 'float8';
const PGSQL_BYTEA_TYPE = 'bytea';
// Name of the config entry containing an array of password that can be used to encrypt/decrypt
const CRYPT_CONF_PASSWORDS = 'encryption_passwords';
const CRYPT_CAST = 'cast';
const CRYPT_PASSWORD_NAME = 'passwordName';
const CRYPT_SELECT_TEMPLATE = 'PGP_SYM_DECRYPT(%s, \'%s\')::%s AS %s';
const CRYPT_WHERE_TEMPLATE = 'PGP_SYM_DECRYPT(%s, \'%s\')::%s';
const CRYPT_WRITE_TEMPLATE = 'PGP_SYM_ENCRYPT(\'%s\', \'%s\')';
protected $dbTable; // Name of the DB-Table for CI-Insert, -Update, ...
protected $pk; // Name of the PrimaryKey for DB-Update, Load, ...
@@ -36,7 +64,7 @@ class DB_Model extends CI_Model
private $executedQueryMetaData;
private $executedQueryListFields;
private $debugMode;
private $debugMode; // Debug mode enable (true) or disabled (false)
/**
* Constructor
@@ -46,20 +74,23 @@ class DB_Model extends CI_Model
// Call parent constructor
parent::__construct();
// Set properties
$this->hasSequence = true;
// Loads DB conns and confs
// Loads DB connections and configs
$this->load->database($dbtype);
// Loads the DB config to encrypt/decrypt data
$this->config->load('db_crypt');
// Set properties
$this->hasSequence = true;
$this->debugMode = isset($this->db->db_debug) && $this->db->db_debug === true;
// Loads UDF model
$this->load->model('system/UDF_model', 'UDFModel');
// Loads the UDF library
$this->load->library('UDFLib');
// Loads the logs library
$this->load->library('LogLib');
$this->debugMode = isset($this->db->db_debug) && $this->db->db_debug === true;
}
// ------------------------------------------------------------------------------------------
@@ -85,13 +116,20 @@ class DB_Model extends CI_Model
* @param array $data DataArray for Insert
* @return array
*/
public function insert($data)
public function insert($data, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
// If this table has UDF and the validation of them is ok
if (isError($validate = $this->_prepareUDFsWrite($data, $this->dbTable))) return $validate;
$validate = $this->_prepareUDFsWrite($data, $this->dbTable);
if (isError($validate)) return $validate;
// Add the pgp_sym_eccrypt postgresql function to the set clause if needed
$this->_addEncrypt($encryptedColumns, $data);
// Add the pgp_sym_eccrypt postgresql function to the set clause if needed
if (!empty($encryptedColumns)) $this->_addEncrypt($encryptedColumns, $data);
// DB-INSERT
$insert = $this->db->insert($this->dbTable, $data);
@@ -135,14 +173,15 @@ class DB_Model extends CI_Model
* @param array $data DataArray for Insert
* @return array
*/
public function update($id, $data)
public function update($id, $data, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->pk)) return error('The given primary key is not valid', EXIT_MODEL);
if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
// If this table has UDF and the validation of them is ok
if (isError($validate = $this->_prepareUDFsWrite($data, $this->dbTable, $id))) return $validate;
$validate = $this->_prepareUDFsWrite($data, $this->dbTable, $id);
if (isError($validate)) return $validate;
$tmpId = $id;
@@ -161,6 +200,9 @@ class DB_Model extends CI_Model
$this->db->where($tmpId);
// Add the pgp_sym_eccrypt postgresql function to the set clause if needed
$this->_addEncrypt($encryptedColumns, $data);
// DB-UPDATE
$update = $this->db->update($this->dbTable, $data);
@@ -224,7 +266,7 @@ class DB_Model extends CI_Model
* @param string $id ID (Primary Key) for SELECT ... WHERE
* @return array
*/
public function load($id = null)
public function load($id = null, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->pk)) return error('The given primary key is not valid', EXIT_MODEL);
@@ -245,7 +287,7 @@ class DB_Model extends CI_Model
$tmpId = array($this->pk => $id);
}
return $this->loadWhere($tmpId);
return $this->loadWhere($tmpId, $encryptedColumns);
}
/**
@@ -253,11 +295,14 @@ class DB_Model extends CI_Model
*
* @return array
*/
public function loadWhere($where = null)
public function loadWhere($where = null, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
// Add the pgp_sym_decrypt postgresql function to the select and where clause if needed
$this->_addDecryptLoad($encryptedColumns, $where);
// Execute query
$result = $this->db->get_where($this->dbTable, $where);
@@ -265,7 +310,7 @@ class DB_Model extends CI_Model
if ($result)
{
return success($this->_toPhp($result));
return success($this->_toPhp($result, $encryptedColumns));
}
else
{
@@ -303,7 +348,8 @@ class DB_Model extends CI_Model
// NOTE: $this->db->list_fields($tables[$t]) doesn't work if there are two tables with
// the same name in two different schemas, use this workaround
$fields = array();
if (isSuccess($lstColumns = $this->_list_columns($schemaAndTable->schema, $schemaAndTable->table)))
$lstColumns = $this->_list_columns($schemaAndTable->schema, $schemaAndTable->table);
if (isSuccess($lstColumns))
{
$fields = $lstColumns->retval;
}
@@ -381,7 +427,8 @@ class DB_Model extends CI_Model
$tmpFilteredArray = array_filter(get_object_vars($sideTableObj));
if (isset($tmpFilteredArray) && count($tmpFilteredArray) > 0)
{
if (($k = $this->_findMainTable($mainTableObj, $returnArray)) === false)
$k = $this->_findMainTable($mainTableObj, $returnArray);
if ($k === false)
{
$mainTableObj->{$sideTableProperty} = array($sideTableObj);
$returnArray[$returnArrayCounter++] = $mainTableObj;
@@ -758,14 +805,13 @@ class DB_Model extends CI_Model
/**
* Like execQuery, but it allows only to perform queries to read data
*/
public function execReadOnlyQuery($query, $parametersArray = null)
public function execReadOnlyQuery($query, $parametersArray = null, $encryptedColumns = null)
{
$result = error('You are allowed to run only query for reading data'); //
$cleanedQuery = trim(preg_replace('/\t|\n|\r|;/', '', $query)); //
//
if (
(stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false)
if ((stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false)
&& (stripos($cleanedQuery, 'UPDATE') > 0 || stripos($cleanedQuery, 'UPDATE') == false)
&& (stripos($cleanedQuery, 'CREATE') > 0 || stripos($cleanedQuery, 'CREATE') == false)
&& (stripos($cleanedQuery, 'DELETE') > 0 || stripos($cleanedQuery, 'DELETE') == false)
@@ -775,7 +821,7 @@ class DB_Model extends CI_Model
{
$queryToExec = str_replace(';', '', $query); //
$result = $this->execQuery($queryToExec, $parametersArray);
$result = $this->execQuery($queryToExec, $parametersArray, $encryptedColumns);
}
return $result;
@@ -790,13 +836,16 @@ class DB_Model extends CI_Model
* boolean if the query is of the write type (INSERT, UPDATE, DELETE...)
* array that represents DB data
*/
protected function execQuery($query, $parametersArray = null)
protected function execQuery($query, $parametersArray = null, $encryptedColumns = null)
{
$result = null;
// If the query is empty don't lose time
if (!isEmptyString($query))
{
// Add the pgp_sym_decrypt postgresql function to the given query
$this->_addDecryptQuery($encryptedColumns, $query);
// If there are parameters to bind to the query
if (is_array($parametersArray) && count($parametersArray) > 0)
{
@@ -812,7 +861,7 @@ class DB_Model extends CI_Model
// If no errors occurred
if ($resultDB)
{
$result = success($this->_toPhp($resultDB));
$result = success($this->_toPhp($resultDB, $encryptedColumns));
}
else
{
@@ -840,7 +889,8 @@ class DB_Model extends CI_Model
$result->schema = DB_Model::DEFAULT_SCHEMA;
// If a schema is specified
if (($pos = strpos($schemaAndTable, '.')) !== false)
$pos = strpos($schemaAndTable, '.');
if ($pos !== false)
{
$result->schema = substr($schemaAndTable, 0, $pos);
$result->table = substr($schemaAndTable, $pos + 1);
@@ -851,6 +901,207 @@ class DB_Model extends CI_Model
// ------------------------------------------------------------------------------------------
// Private methods
//
//
/**
* To add the pgp_sym_encrypt function to the set clause where needed
*/
private function _addEncrypt($encryptedColumns, &$data)
{
// If encryptedColumns is not defined then exit
if (isEmptyArray($encryptedColumns)) return;
$tmpData = array(); // Temporary array used to copy not encrypted columns
// For each column that is going to be inserted/updated
foreach ($data as $column => $value)
{
// If the current column is in the list of the columns to be encrypted
// and contains the password name element
if (array_key_exists($column, $encryptedColumns)
&& array_key_exists(self::CRYPT_PASSWORD_NAME, $encryptedColumns[$column]))
{
// Password to encrypt data
$cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS);
$encryptionPassword = $cryptConfPasswords[$encryptedColumns[$column][self::CRYPT_PASSWORD_NAME]];
// Add the encrypted column to the set clause without escaping
$this->db->set(
$column,
sprintf(
self::CRYPT_WRITE_TEMPLATE,
$value,
$encryptionPassword
),
false // no escaping
);
}
else // otherwise copy this element as it is
{
$tmpData[$column] = $value;
}
}
$data = $tmpData; // this array does not contain encrypted columns
}
/**
* To add the pgp_sym_decrypt function to the given query
*/
private function _addDecryptQuery($encryptedColumns, &$query)
{
// If it is request to get encrypted columns
if (!isEmptyArray($encryptedColumns))
{
// For each requested encrypted column
foreach ($encryptedColumns as $encryptedColumn => $definition)
{
// If the requested encrypted column is well defined
if (!isEmptyArray($definition)
&& array_key_exists(self::CRYPT_CAST, $definition)
&& array_key_exists(self::CRYPT_PASSWORD_NAME, $definition))
{
// And if exists the wanted password to decrypt in the configs
if (array_key_exists($definition[self::CRYPT_PASSWORD_NAME], $this->config->item(self::CRYPT_CONF_PASSWORDS)))
{
// Password to decrypt data
$cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS);
$decryptionPassword = $cryptConfPasswords[$definition[self::CRYPT_PASSWORD_NAME]];
// 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
);
}
}
}
}
}
/**
* To add the pgp_sym_decrypt function to the select and where clause where needed
*/
private function _addDecryptLoad($encryptedColumns, &$where)
{
// If it is request to get encrypted columns
if (!isEmptyArray($encryptedColumns))
{
// For each requested encrypted column
foreach ($encryptedColumns as $encryptedColumn => $definition)
{
// If the requested encrypted column is well defined
if (!isEmptyArray($definition)
&& array_key_exists(self::CRYPT_CAST, $definition)
&& array_key_exists(self::CRYPT_PASSWORD_NAME, $definition))
{
// And if exists the wanted password to decrypt in the configs
if (array_key_exists($definition[self::CRYPT_PASSWORD_NAME], $this->config->item(self::CRYPT_CONF_PASSWORDS)))
{
// Password to decrypt data
$cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS);
$decryptionPassword = $cryptConfPasswords[$definition[self::CRYPT_PASSWORD_NAME]];
// -----------------------------------------
// SELECT
// Add to the select clause the column to be decrypted
// NOTE: this is going to override any previously added column with the same name
$this->addSelect(
sprintf(
self::CRYPT_SELECT_TEMPLATE,
$encryptedColumn,
$decryptionPassword,
$definition[self::CRYPT_CAST],
$encryptedColumn
)
);
// -----------------------------------------
// WHERE
// If the where parameter is a valid array
if (!isEmptyArray($where))
{
$tmpWhere = array();
// For each condition of the where clause
foreach ($where as $column => $condition)
{
$operator = null; // operator not found in the column name
// Custom operators with 2 chars
if (strpos($column, '>=') != false
|| strpos($column, '<=') != false
|| strpos($column, '!=') != false
|| strpos($column, '<>') != false
)
{
$operator = ' '.substr(trim($column), -2).' ';
}
// Custom operators with 1 chars
elseif (strpos($column, '>') != false
|| strpos($column, '<') != false
|| strpos($column, '=') != false
)
{
$operator = ' '.substr(trim($column), -1).' ';
}
else // default operator
{
$operator = ' = ';
}
// If the column from the where clause is the same from the encrypted columns definition
if (trim($column) == $encryptedColumn
|| ($operator != null && substr(trim($column), 0, strlen(trim($column)) - 2) == $encryptedColumn)
)
{
// Then rename the column using the postgresql decryption function
$tmpWhere[sprintf(
self::CRYPT_WHERE_TEMPLATE,
$encryptedColumn,
$decryptionPassword,
$definition[self::CRYPT_CAST]
).$operator] = $condition;
}
else // otherwise copy the column as it is
{
$tmpWhere[$column] = $condition;
}
}
$where = $tmpWhere; // replace with the new where
}
// Otherwise if the where parameter is a valid string
elseif (!isEmptyString($where))
{
// 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
);
}
}
}
}
}
}
/**
* Invalid ID
@@ -877,11 +1128,11 @@ class DB_Model extends CI_Model
{
if ($id != null)
{
$prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $this->dbTable, $this->_getUDFsNoPerms($id));
$prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $schemaAndTable, $this->_getUDFsNoPerms($id));
}
else
{
$prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $this->dbTable);
$prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $schemaAndTable);
}
}
@@ -895,7 +1146,7 @@ class DB_Model extends CI_Model
* - A FALSE value on failure
* - Otherwise an object filled with data on success
*/
private function _toPhp($result)
private function _toPhp($result, $encryptedColumns = null)
{
$udfs = false; // if UDFs are inside the given result set
$toPhp = $result; // if there is nothing to convert then return the result from DB
@@ -911,7 +1162,9 @@ class DB_Model extends CI_Model
// Looking for booleans, arrays and UDFs
foreach ($this->executedQueryMetaData as $eqmd)
{
// If array type, boolean type OR a UDF
// If array type, boolean type, numeric type
// Or bytea type
// Or UDF type
if (strpos($eqmd->type, DB_Model::PGSQL_ARRAY_TYPE) !== false
|| $eqmd->type == DB_Model::PGSQL_BOOLEAN_TYPE
|| $eqmd->type == DB_Model::PGSQL_INT2_TYPE
@@ -919,6 +1172,7 @@ class DB_Model extends CI_Model
|| $eqmd->type == DB_Model::PGSQL_INT8_TYPE
|| $eqmd->type == DB_Model::PGSQL_FLOAT4_TYPE
|| $eqmd->type == DB_Model::PGSQL_FLOAT8_TYPE
|| $eqmd->type == DB_Model::PGSQL_BYTEA_TYPE
|| $this->udflib->isUDFColumn($eqmd->name, $eqmd->type))
{
// If UDFs are inside this result set
@@ -981,6 +1235,21 @@ class DB_Model extends CI_Model
{
$resultElement->{$toBeConverted->name} = $this->pgFloatPhp($resultElement->{$toBeConverted->name});
}
// Byte A type
elseif ($toBeConverted->type == DB_Model::PGSQL_BYTEA_TYPE)
{
// If encrypted columns are defined
// and if the byte a column is defined as encrypted column
if (!isEmptyArray($encryptedColumns)
&& array_key_exists($toBeConverted->name, $encryptedColumns))
{
// keep the column
}
else // otherwise remove the column from the result
{
unset($resultElement->{$toBeConverted->name});
}
}
}
}
}
+231
View File
@@ -0,0 +1,231 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Controller using JSON
*/
class FHCAPI_Controller extends Auth_Controller
{
/**
* Response status
* @see https://github.com/omniti-labs/jsend
*/
const STATUS_SUCCESS = 'success';
const STATUS_FAIL = 'fail';
const STATUS_ERROR = 'error';
/**
* Error types
*/
const ERROR_TYPE_PHP = 'php';
const ERROR_TYPE_EXCEPTION = 'exception';
const ERROR_TYPE_GENERAL = 'general';
const ERROR_TYPE_404 = '404';
const ERROR_TYPE_DB = 'db';
const ERROR_TYPE_VALIDATION = 'validation';
const ERROR_TYPE_AUTH = 'auth';
/**
* Return Object
*
* @var array
*/
private $returnObj = [];
/**
* Constructor
*
* @param array $requiredPermissions
* @return void
*/
public function __construct($requiredPermissions = [])
{
if (is_cli())
show_404();
global $g_result;
$g_result = $this;
ob_start(function ($content) {
$http_response_code = http_response_code();
// NOTE(chris): For security reasons 404 will be displayed the same everywhere
if ($http_response_code == REST_Controller::HTTP_NOT_FOUND)
return $content;
header('Content-Type: application/json; charset=utf-8');
if (!isset($this->returnObj['meta']) || !isset($this->returnObj['meta']['status'])) {
switch ($http_response_code) {
case 200:
$this->setStatus(self::STATUS_SUCCESS);
break;
case 400:
$this->setStatus(self::STATUS_FAIL);
break;
default:
$this->setStatus(self::STATUS_ERROR);
break;
}
}
return json_encode($this->returnObj);
});
// NOTE(chris): overwrite error_views_path before constructor
load_class('Config')->set_item('error_views_path', VIEWPATH.'errors'.DIRECTORY_SEPARATOR.'json'.DIRECTORY_SEPARATOR);
parent::__construct($requiredPermissions);
// For JSON Requests (as opposed to multipart/form-data) get the $_POST variable from the input stream instead
if ($this->input->get_request_header('Content-Type', true) == 'application/json')
$_POST = json_decode($this->security->xss_clean($this->input->raw_input_stream), true);
elseif (isset($_POST['_jsondata'])) {
$_POST = array_merge($_POST, json_decode($_POST['_jsondata'], true));
unset($_POST['_jsondata']);
}
}
// ---------------------------------------------------------------
// Handle Output object
// ---------------------------------------------------------------
/**
* @param array $data
* @param string $type (optional)
* @return void
*/
public function addError($data, $type = null)
{
if (!isset($this->returnObj['errors']))
$this->returnObj['errors'] = [];
$error = [];
if (is_array($data)) {
if ($type == self::ERROR_TYPE_VALIDATION)
$error['messages'] = $data;
else
$error = $data;
} else {
$error['message'] = $data;
}
if ($type)
$error['type'] = $type;
$this->returnObj['errors'][] = $error;
}
/**
* @param mixed $data
* @return void
*/
public function setData($data)
{
$this->returnObj['data'] = $data;
}
/**
* @param string $key
* @param mixed $value
* @return void
*/
public function addMeta($key, $value)
{
if (!isset($this->returnObj['meta']))
$this->returnObj['meta'] = [];
$this->returnObj['meta'][$key] = $value;
}
/**
* @param string $status
* @return void
*/
public function setStatus($status)
{
$this->addMeta('status', $status);
}
// ---------------------------------------------------------------
// Handle Output object - Shortcut functions
// ---------------------------------------------------------------
/**
* @param mixed $data (optional)
* @return void
*/
protected function terminateWithSuccess($data = null)
{
$this->setData($data);
$this->setStatus(self::STATUS_SUCCESS);
exit;
}
/**
* @param array $errors
* @return void
*/
protected function terminateWithValidationErrors($errors)
{
$this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
$this->addError($errors, self::ERROR_TYPE_VALIDATION);
$this->setStatus(self::STATUS_FAIL);
exit(EXIT_ERROR);
}
/**
* @param array $error
* @param string $type (optional)
* @param integer $status (optional)
* @return void
*/
protected function terminateWithError($error, $type = null, $status = REST_Controller::HTTP_INTERNAL_SERVER_ERROR)
{
$this->output->set_status_header($status);
$this->addError($error, $type);
$this->setStatus(self::STATUS_ERROR);
exit;
}
/**
* @param stdclass $result
* @param string $errortype
* @return void
*/
protected function getDataOrTerminateWithError($result, $errortype = self::ERROR_TYPE_GENERAL)
{
if (isError($result)) {
$this->terminateWithError(getError($result), $errortype);
}
return $result->retval;
}
// ---------------------------------------------------------------
// Security
// ---------------------------------------------------------------
/**
* Outputs an error message and sets the HTTP Header.
* This overwrites the default behaviour to output a json object.
*
* @param array $requiredPermissions
* @return void
*/
protected function _outputAuthError($requiredPermissions)
{
$this->output->set_status_header(isLogged() ? REST_Controller::HTTP_FORBIDDEN : REST_Controller::HTTP_UNAUTHORIZED);
$this->addError([
'message' => 'You are not allowed to access to this content',
'controller' => $this->router->class,
'method' => $this->router->method,
'required_permissions' => $this->_rpsToString($requiredPermissions, $this->router->method)
], self::ERROR_TYPE_AUTH);
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
/**
* Copyright (C) 2023 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/>.
*/
interface IEncryption
{
public function getEncryptedColumns(): array;
}
+78 -1
View File
@@ -356,7 +356,8 @@ function sanitizeProblemChars($str)
'ss' => '/&szlig;/'
);
return preg_replace($acentos, array_keys($acentos), htmlentities($str, ENT_NOQUOTES | ENT_HTML5, $enc));
$tmp = preg_replace($acentos, array_keys($acentos), htmlentities($str, ENT_NOQUOTES | ENT_HTML5, $enc));
return html_entity_decode($tmp, ENT_NOQUOTES | ENT_HTML5, $enc);
}
/**
@@ -421,3 +422,79 @@ function isValidDate($dateString)
return false;
}
}
// ------------------------------------------------------------------------
// Collection of utility functions for form validation purposes
// ------------------------------------------------------------------------
/**
* check if string can be converted to a date
*/
function is_valid_date($dateString)
{
try
{
return (new DateTime($dateString)) !== false;
}
catch(Exception $e)
{
return false;
}
}
/**
* check if given permissions are met
*/
function has_write_permissions($value, $permissions = '')
{
if (!$permissions)
$permissions = $value;
$permissions = explode(',', $permissions);
$CI =& get_instance();
$CI->load->library('AuthLib');
$CI->load->library('PermissionLib');
return $CI->permissionlib->hasAtLeastOne(
$permissions,
'sometable',
PermissionLib::WRITE_RIGHT
);
}
/**
* check if has permissions for a studiengang_kz
*/
function has_permissions_for_stg($studiengang_kz, $permissions = '')
{
if (!$permissions)
return false;
$permissions = explode(',', $permissions);
$CI =& get_instance();
$CI->load->library('AuthLib');
$CI->load->library('PermissionLib');
foreach ($permissions as $perm) {
if (strpos($perm, PermissionLib::PERMISSION_SEPARATOR) === false) {
$CI->addError(
'The given permission does not use the correct format',
FHCAPI_Controller::ERROR_TYPE_GENERAL
);
return false;
}
list($perm, $accesstype) = explode(PermissionLib::PERMISSION_SEPARATOR, $perm);
$at = '';
if (strpos($accesstype, PermissionLib::READ_RIGHT) !== false)
$at = PermissionLib::SELECT_RIGHT; // S
if (strpos($accesstype, PermissionLib::WRITE_RIGHT) !== false)
$at .= PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; // UID
if ($CI->permissionlib->isBerechtigt($perm, $at, $studiengang_kz))
return true;
}
return false;
}
+2 -1
View File
@@ -96,7 +96,8 @@ function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod)
app_root: "'.APP_ROOT.'",
ci_router: "'.$indexPage.'",
called_path: "'.$calledPath.'",
called_method: "'.$calledMethod.'"
called_method: "'.$calledMethod.'",
user_language: "'.$user_language.'"
};';
$toPrint .= "\n";
$toPrint .= '</script>';
@@ -0,0 +1,43 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2019 - 2022, CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
* @copyright Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
* @copyright Copyright (c) 2019 - 2022, CodeIgniter Foundation (https://codeigniter.com/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
$lang['form_validation_has_write_permissions'] = 'You have no rights to edit {field} field.';
$lang['form_validation_is_valid_date'] = 'The date format is invalid or out of range.';
$lang['form_validation_has_permissions_for_stg'] = 'You have no rights for stg {field}.';
File diff suppressed because it is too large Load Diff
+17 -4
View File
@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2022 fhcomplete.org
*
@@ -36,6 +37,7 @@ class FilterCmptLib
const SESSION_METADATA = 'datasetMetadata';
const SESSION_ROW_NUMBER = 'rowNumber';
const SESSION_TIMEOUT = 'sessionTimeout';
const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns';
// Session dataset elements
const SESSION_DATASET = 'dataset';
@@ -62,6 +64,7 @@ class FilterCmptLib
// ...to specify permissions that are needed to use this FilterCmpt
const REQUIRED_PERMISSIONS = 'requiredPermissions';
const ENCRYPTED_COLUMNS = 'encryptedColumns';
// ...stament to retrieve the dataset
const QUERY = 'query';
@@ -102,6 +105,7 @@ class FilterCmptLib
private $_filterKurzbz;
private $_query;
private $_requiredPermissions;
private $_encryptedColumns;
private $_reloadDataset;
private $_sessionTimeout;
@@ -504,10 +508,12 @@ class FilterCmptLib
$saveCustomFilter = true;
}
if ($saveCustomFilter === true)
if ($saveCustomFilter === true)
{
$this->_setSessionElement(FilterCmptLib::SESSION_SIDE_MENU,
$this->_generateFilterMenu($this->_app, $this->_datasetName));
$this->_setSessionElement(
FilterCmptLib::SESSION_SIDE_MENU,
$this->_generateFilterMenu($this->_app, $this->_datasetName)
);
}
return $saveCustomFilter;
@@ -717,6 +723,7 @@ class FilterCmptLib
$this->_filterKurzbz = null;
$this->_query = null;
$this->_requiredPermissions = null;
$this->_encryptedColumns = null;
$this->_reloadDataset = true; // by default the dataset is NOT cached in session
$this->_sessionTimeout = FilterCmptLib::SESSION_DEFAULT_TIMEOUT;
@@ -727,6 +734,12 @@ class FilterCmptLib
$this->_requiredPermissions = $filterCmptArray[FilterCmptLib::REQUIRED_PERMISSIONS];
}
// Retrieved the encrypted columns parameter if present
if (isset($filterCmptArray[FilterCmptLib::ENCRYPTED_COLUMNS]))
{
$this->_encryptedColumns = $filterCmptArray[FilterCmptLib::ENCRYPTED_COLUMNS];
}
// Parameters needed to retrieve univocally a filter from DB
if (isset($filterCmptArray[FilterCmptLib::APP]))
{
@@ -1129,7 +1142,7 @@ class FilterCmptLib
$this->_ci->load->model('system/Filters_model', 'FiltersModel');
// Execute the given SQL statement suppressing error messages
$dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery);
$dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $this->_encryptedColumns);
}
return $dataset;
+27 -6
View File
@@ -1,7 +1,26 @@
<?php
/**
* Copyright (C) 2023 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 \stdClass as stdClass;
/**
* FilterWidget logic
*/
@@ -16,6 +35,7 @@ class FilterWidgetLib
const SESSION_SELECTED_FIELDS = 'selectedFields';
const SESSION_COLUMNS_ALIASES = 'columnsAliases';
const SESSION_ADDITIONAL_COLUMNS = 'additionalColumns';
const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns';
const SESSION_CHECKBOXES = 'checkboxes';
const SESSION_FILTERS = 'filters';
const SESSION_METADATA = 'datasetMetadata';
@@ -56,6 +76,7 @@ class FilterWidgetLib
const ADDITIONAL_COLUMNS = 'additionalColumns';
const CHECKBOXES = 'checkboxes';
const COLUMNS_ALIASES = 'columnsAliases';
const ENCRYPTED_COLUMNS = 'encryptedColumns';
// ...to format/mark records of a dataset
const FORMAT_ROW = 'formatRow';
@@ -120,7 +141,7 @@ class FilterWidgetLib
/**
* Gets the CI instance and loads message helper
*/
public function __construct($params = null)
public function __construct()
{
$this->_ci =& get_instance(); // get code igniter instance
}
@@ -367,7 +388,7 @@ class FilterWidgetLib
/**
* Retrieves the dataset from the DB
*/
public function getDataset($datasetQuery)
public function getDataset($datasetQuery, $encryptedColumns)
{
$dataset = null;
@@ -376,7 +397,7 @@ class FilterWidgetLib
$this->_ci->load->model('system/Filters_model', 'FiltersModel');
// Execute the given SQL statement suppressing error messages
$dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery);
$dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $encryptedColumns);
}
return $dataset;
@@ -390,7 +411,7 @@ class FilterWidgetLib
public function getFilterName($filterJson)
{
$filterName = $filterJson->name; // always present, used as default
$trimedname = (isset($filterJson->namePhrase)?trim($filterJson->namePhrase):'');
// Filter name from phrases system
if (isset($filterJson->namePhrase) && !isEmptyString($filterJson->namePhrase))
{
@@ -451,7 +472,8 @@ class FilterWidgetLib
if (in_array($selectedField, $fields))
{
// If the selected field is present in the list of the selected fields by the current filter
if (($pos = array_search($selectedField, $selectedFields)) !== false)
$pos = array_search($selectedField, $selectedFields);
if ($pos !== false)
{
// Then remove it and shift the rest of elements by one if needed
array_splice($selectedFields, $pos, 1);
@@ -750,7 +772,6 @@ class FilterWidgetLib
$this->_ci->load->library('NavigationLib', array(self::NAVIGATION_PAGE => $navigationPage));
$filterMenu = null;
$currentMenu = $this->_ci->navigationlib->getSessionMenu(); // The navigation menu currently stored in session
$session = $this->getSession(); // The filter currently stored in session (the one that is currently used)
if ($session != null)
+34 -14
View File
@@ -21,6 +21,8 @@ require_once(FHCPATH.'include/functions.inc.php');
require_once(FHCPATH.'include/wawi_kostenstelle.class.php');
require_once(FHCPATH.'include/benutzerberechtigung.class.php');
use \benutzerberechtigung as benutzerberechtigung;
class PermissionLib
{
// Available rights in the DB
@@ -65,8 +67,10 @@ class PermissionLib
if (!is_cli())
{
// API Caller rights initialization
$authObj = $this->_ci->authlib->getAuthObj();
self::$bb = new benutzerberechtigung();
self::$bb->getBerechtigungen(($this->_ci->authlib->getAuthObj())->{AuthLib::AO_USERNAME});
if ($authObj)
self::$bb->getBerechtigungen($authObj->{AuthLib::AO_USERNAME});
}
}
@@ -143,19 +147,7 @@ class PermissionLib
if (strpos($permissions[$pCounter], PermissionLib::PERMISSION_SEPARATOR) !== false)
{
// Retrieves permission and required access type from the $requiredPermissions array
list($permission, $requiredAccessType) = explode(PermissionLib::PERMISSION_SEPARATOR, $permissions[$pCounter]);
$accessType = '';
// Set the access type
if (strpos($requiredAccessType, PermissionLib::READ_RIGHT) !== false)
{
$accessType = PermissionLib::SELECT_RIGHT; // S
}
if (strpos($requiredAccessType, PermissionLib::WRITE_RIGHT) !== false)
{
$accessType .= PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; // UID
}
list($permission, $accessType) = $this->convertAccessType($permissions[$pCounter]);
if (!isEmptyString($accessType)) // if compliant
{
@@ -166,6 +158,16 @@ class PermissionLib
if ($checkPermissions === true) break;
}
}
elseif ($permissions[$pCounter] == Auth_Controller::PERM_ANONYMOUS)
{
$checkPermissions = true;
break;
}
elseif ($permissions[$pCounter] == Auth_Controller::PERM_LOGGED)
{
$checkPermissions = isLogged();
break;
}
else
{
show_error('The given permission does not use the correct format');
@@ -195,6 +197,24 @@ class PermissionLib
return $checkPermissions;
}
/**
* Retrieves permission and required access type from the newly formatted permission string
*
* @param string $permission
*
* @return array
*/
public function convertAccessType($permission)
{
list($permission, $reqAccessType) = explode(PermissionLib::PERMISSION_SEPARATOR, $permission);
$accessType = '';
if (strpos($reqAccessType, PermissionLib::READ_RIGHT) !== false)
$accessType = PermissionLib::SELECT_RIGHT;
if (strpos($reqAccessType, PermissionLib::WRITE_RIGHT) !== false)
$accessType = PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT;
return [$permission, $accessType];
}
/**
* Checks if at least one of the permissions given as parameter (requiredPermissions) belongs to the authenticated user
* It checks the given permissions against a given method (controller method name) and a given permission type (R and/or W)
+7 -5
View File
@@ -35,10 +35,12 @@ class PrestudentLib
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
}
public function setAbbrecher($prestudent_id, $studiensemester_kurzbz, $insertvon = null, $statusgrund_kurzbz = null, $datum = null, $bestaetigtam = null)
public function setAbbrecher($prestudent_id, $studiensemester_kurzbz, $insertvon = null, $statusgrund_kurzbz = null, $datum = null, $bestaetigtam = null, $bestaetigtvon = null)
{
if (!$insertvon)
$insertvon = getAuthUID();
if (!$bestaetigtvon)
$bestaetigtvon = $insertvon;
$result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id, $studiensemester_kurzbz);
if (isError($result))
@@ -72,14 +74,14 @@ class PrestudentLib
$result = $this->_ci->PrestudentstatusModel->withGrund($statusgrund_kurzbz)->insert([
'prestudent_id' => $prestudent_id,
'status_kurzbz' => Prestudentstatus_model::STATUS_ABBRECHER,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'studiensemester_kurzbz' => $prestudent_status->studiensemester_kurzbz,
'ausbildungssemester' => $prestudent_status->ausbildungssemester,
'datum' => $datum,
'insertvon' => $insertvon,
'insertamum' => date('c'),
'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz,
'studienplan_id'=> $prestudent_status->studienplan_id,
'bestaetigtvon' => $insertvon,
'bestaetigtvon' => $bestaetigtvon,
'bestaetigtam' => $bestaetigtam
]);
@@ -133,7 +135,7 @@ class PrestudentLib
}
//noch nicht eingetragene Zeugnisnoten auf 9 setzen
$result = $this->_ci->ZeugnisnoteModel->getZeugnisnoten($student->student_uid, $studiensemester_kurzbz);
$result = $this->_ci->ZeugnisnoteModel->getZeugnisnoten($student->student_uid, $prestudent_status->studiensemester_kurzbz);
if (isError($result))
return $result;
$result = getData($result) ?: [];
@@ -179,7 +181,7 @@ class PrestudentLib
//Studentlehrverband setzen
$this->_ci->StudentlehrverbandModel->update([
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'studiensemester_kurzbz' => $prestudent_status->studiensemester_kurzbz,
'student_uid' => $student->student_uid
], [
'studiengang_kz' => $student->studiengang_kz,
+113 -15
View File
@@ -30,9 +30,10 @@ class SearchBarLib
const ERROR_WRONG_SEARCHSTR = 'ERR002';
const ERROR_NO_TYPES = 'ERR003';
const ERROR_WRONG_TYPES = 'ERR004';
const ERROR_NOT_AUTH = 'ERR005';
// List of allowed types of search
const ALLOWED_TYPES = ['mitarbeiter', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms'];
const ALLOWED_TYPES = ['mitarbeiter', 'mitarbeiter_ohne_zuordnung', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms'];
const PHOTO_IMG_URL = '/cis/public/bild.php?src=person&person_id=';
@@ -108,6 +109,92 @@ class SearchBarLib
return $result;
}
private function _mitarbeiter_ohne_zuordnung($searchstr, $type)
{
$dbModel = new DB_Model();
$sql = '
SELECT
\''.$type.'\' AS type,
b.uid AS uid,
p.person_id AS person_id,
p.vorname || \' \' || p.nachname AS name,
ARRAY_AGG(DISTINCT(org.bezeichnung)) AS organisationunit_name,
COALESCE(b.alias, b.uid) || \''.'@'.DOMAIN.'\' AS email,
TRIM(COALESCE(k.kontakt, \'\') || \' \' || COALESCE(m.telefonklappe, \'\')) AS phone,
\''.base_url(self::PHOTO_IMG_URL).'\' || p.person_id AS photo_url,
ARRAY_AGG(DISTINCT(stdkst.bezeichnung)) AS standardkostenstelle
FROM public.tbl_mitarbeiter m
JOIN public.tbl_benutzer b ON(b.uid = m.mitarbeiter_uid)
LEFT JOIN (
SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid
FROM public.tbl_benutzerfunktion bf
JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
WHERE bf.funktion_kurzbz = \'kstzuordnung\'
AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
) stdkst ON stdkst.uid = b.uid
JOIN public.tbl_person p USING(person_id)
LEFT JOIN (
SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid
FROM public.tbl_benutzerfunktion bf
JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
WHERE bf.funktion_kurzbz = \'oezuordnung\'
AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
) org ON org.uid = b.uid
LEFT JOIN (
SELECT kontakt, standort_id
FROM public.tbl_kontakt
WHERE kontakttyp = \'telefon\'
) k ON(k.standort_id = m.standort_id)
WHERE
(stdkst.bezeichnung IS NULL
OR org.bezeichnung IS NULL)
AND (
' .
$this->buildSearchClause(
$dbModel,
array('b.uid', 'p.vorname', 'p.nachname'),
$searchstr
) .
'
)
GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone
';
$employees = $dbModel->execReadOnlyQuery($sql);
// If something has been found then return it
if (hasData($employees)) return getData($employees);
// Otherwise return an empty array
return array();
}
protected function buildSearchClause(DB_Model $dbModel, array $columns, $searchstr)
{
$document = implode(' || \' \' || ', $columns);
$query = '\'' . implode(':* & ', explode(' ', trim($searchstr))) . ':*\'';
$reversequery = '\'*:' . implode(' & *:', explode(' ', trim($searchstr))) . '\'';
$nospacequery = '\'' . implode('', explode(' ', trim($searchstr))) . ':*\'';
$searchclause = <<<EOSC
to_tsvector(lower(regexp_replace({$document}, '[[:punct:]]', ' ', 'g'))) @@ to_tsquery(lower({$query}))
OR
to_tsvector(reverse(lower(regexp_replace({$document}, '[[:punct:]]', ' ', 'g')))) @@ to_tsquery(reverse(lower({$reversequery})))
OR
to_tsvector(lower(regexp_replace({$document}, '[[:punct:]]', ' ', 'g'))) @@ to_tsquery(lower({$nospacequery}))
EOSC;
return $searchclause;
}
/**
* Search for employees
*/
@@ -129,34 +216,38 @@ class SearchBarLib
FROM public.tbl_mitarbeiter m
JOIN public.tbl_benutzer b ON(b.uid = m.mitarbeiter_uid)
JOIN (
SELECT o.bezeichnung, bf.uid
SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid
FROM public.tbl_benutzerfunktion bf
JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
WHERE bf.funktion_kurzbz = \'kstzuordnung\'
AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
GROUP BY o.bezeichnung, bf.uid
GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
) stdkst ON stdkst.uid = b.uid
JOIN public.tbl_person p USING(person_id)
JOIN (
SELECT o.bezeichnung, bf.uid
SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid
FROM public.tbl_benutzerfunktion bf
JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
WHERE bf.funktion_kurzbz = \'oezuordnung\'
AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
GROUP BY o.bezeichnung, bf.uid
GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
) org ON org.uid = b.uid
LEFT JOIN (
SELECT kontakt, standort_id
FROM public.tbl_kontakt
WHERE kontakttyp = \'telefon\'
) k ON(k.standort_id = m.standort_id)
WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR org.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR stdkst.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
WHERE ' .
$this->buildSearchClause(
$dbModel,
array('b.uid', 'p.vorname', 'p.nachname', 'org.bezeichnung', 'stdkst.bezeichnung'),
$searchstr
) .
'
GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone
');
@@ -178,15 +269,17 @@ class SearchBarLib
SELECT
\''.$type.'\' AS type,
o.oe_kurzbz AS oe_kurzbz,
o.bezeichnung AS name,
\'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS name,
oParent.oe_kurzbz AS parentoe_kurzbz,
oParent.bezeichnung AS parentoe_name,
(CASE WHEN oParent.bezeichnung IS NOT NULL THEN \'[\' || otParent.bezeichnung || \'] \' || oParent.bezeichnung END) AS parentoe_name,
ARRAY_AGG(DISTINCT(bfLeader.uid)) AS leader_uid,
ARRAY_AGG(DISTINCT(bfLeader.vorname || \' \' || bfLeader.nachname)) AS leader_name,
COUNT(bfCount.benutzerfunktion_id) AS number_of_people,
(CASE WHEN o.mailverteiler = TRUE THEN o.oe_kurzbz || \''.'@'.DOMAIN.'\' END) AS mailgroup
FROM public.tbl_organisationseinheit o
JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
LEFT JOIN public.tbl_organisationseinheit oParent ON(oParent.oe_kurzbz = o.oe_parent_kurzbz)
LEFT JOIN public.tbl_organisationseinheittyp otParent ON(oParent.organisationseinheittyp_kurzbz = otParent.organisationseinheittyp_kurzbz)
LEFT JOIN (
SELECT benutzerfunktion_id, oe_kurzbz
FROM public.tbl_benutzerfunktion
@@ -204,9 +297,14 @@ class SearchBarLib
AND (datum_bis IS NULL OR datum_bis >= NOW())
AND b.aktiv = TRUE
) bfLeader ON(bfLeader.oe_kurzbz = o.oe_kurzbz)
WHERE o.oe_kurzbz ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
OR o.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
GROUP BY type, o.oe_kurzbz, o.bezeichnung, oParent.oe_kurzbz, oParent.bezeichnung
WHERE ' .
$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
');
// If something has been found
+22 -3
View File
@@ -1,5 +1,22 @@
<?php
/**
* Copyright (C) 2023 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');
/**
@@ -16,6 +33,7 @@ class TableWidgetLib
const SESSION_FIELDS = 'fields';
const SESSION_COLUMNS_ALIASES = 'columnsAliases';
const SESSION_ADDITIONAL_COLUMNS = 'additionalColumns';
const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns';
const SESSION_CHECKBOXES = 'checkboxes';
const SESSION_METADATA = 'datasetMetadata';
const SESSION_ROW_NUMBER = 'rowNumber';
@@ -49,6 +67,7 @@ class TableWidgetLib
const ADDITIONAL_COLUMNS = 'additionalColumns';
const CHECKBOXES = 'checkboxes';
const COLUMNS_ALIASES = 'columnsAliases';
const ENCRYPTED_COLUMNS = 'encryptedColumns';
// ...to format/mark records of a dataset
const FORMAT_ROW = 'formatRow';
@@ -74,7 +93,7 @@ class TableWidgetLib
/**
* Gets the CI instance and loads message helper
*/
public function __construct($params = null)
public function __construct()
{
$this->_ci =& get_instance(); // get code igniter instance
}
@@ -177,7 +196,7 @@ class TableWidgetLib
/**
* Retrieves the dataset from the DB
*/
public function getDataset($datasetQuery)
public function getDataset($datasetQuery, $encryptedColumns)
{
$dataset = null;
@@ -186,7 +205,7 @@ class TableWidgetLib
$this->_ci->load->model('system/Filters_model', 'FiltersModel');
// Execute the given SQL statement suppressing error messages
$dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery);
$dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $encryptedColumns);
}
return $dataset;
@@ -33,7 +33,8 @@ class PlausicheckDefinitionLib
'PrestudentMischformOhneOrgform' => 'PrestudentMischformOhneOrgform',
'StgPrestudentUngleichStgStudienplan' => 'StgPrestudentUngleichStgStudienplan',
'StgPrestudentUngleichStgStudent' => 'StgPrestudentUngleichStgStudent',
'StudentstatusNachAbbrecher' => 'StudentstatusNachAbbrecher'
'StudentstatusNachAbbrecher' => 'StudentstatusNachAbbrecher',
'DualesStudiumOhneMarkierung' => 'DualesStudiumOhneMarkierung'
//'StudienplanUngueltig' => 'StudienplanUngueltig'
);
@@ -12,8 +12,7 @@ class PlausicheckProducerLib
private $_ci; // ci instance
private $_extensionName; // name of extension
private $_app; // name of application
private $_konfiguration = array(); // konfigratio parameters
private $_konfiguration = array(); // configuration parameters
public function __construct($params = null)
{
@@ -0,0 +1,143 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
require_once('PlausiChecker.php');
/**
*
*/
class DualesStudiumOhneMarkierung extends PlausiChecker
{
public function executePlausiCheck($params)
{
$results = array();
// get parameters from config
$exkludierte_studiengang_kz = isset($this->_config['exkludierteStudiengaenge']) ? $this->_config['exkludierteStudiengaenge'] : null;
// pass parameters needed for plausicheck
$studiensemester_kurzbz = isset($params['studiensemester_kurzbz']) ? $params['studiensemester_kurzbz'] : null;
$studiengang_kz = isset($params['studiengang_kz']) ? $params['studiengang_kz'] : null;
// get all students failing the plausicheck
$prestudentRes = $this->getDualesStudiumOhneMarkierung(
$studiensemester_kurzbz,
$studiengang_kz,
null,
$exkludierte_studiengang_kz
);
if (isError($prestudentRes)) return $prestudentRes;
if (hasData($prestudentRes))
{
$prestudents = getData($prestudentRes);
// populate results with data necessary for writing issues
foreach ($prestudents as $prestudent)
{
$results[] = array(
'person_id' => $prestudent->person_id,
'oe_kurzbz' => $prestudent->prestudent_stg_oe_kurzbz,
'fehlertext_params' => array(
'prestudent_id' => $prestudent->prestudent_id,
'studienplan' => $prestudent->studienplan
),
'resolution_params' => array(
'prestudent_id' => $prestudent->prestudent_id,
'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz
)
);
}
}
// return the results
return success($results);
}
/**
* All prestudents in dual Studiengang should have set the dual flag to true.
* @param studiensemester_kurzbz string check is to be executed for certain Studiensemester
* @param studiengang_kz int if check is to be executed for certain Studiengang
* @param prestudent_id int if check is to be executed only for one prestudent
* @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check
* @return success with prestudents or error
*/
public function getDualesStudiumOhneMarkierung(
$studiensemester_kurzbz,
$studiengang_kz = null,
$prestudent_id = null,
$exkludierte_studiengang_kz = null
) {
$params = array($studiensemester_kurzbz);
$qry = "
SELECT
DISTINCT pre.person_id, pre.prestudent_id,
stpl.bezeichnung AS studienplan,
status.studiensemester_kurzbz,
status.ausbildungssemester,
stg.oe_kurzbz AS prestudent_stg_oe_kurzbz
FROM
public.tbl_prestudent pre
JOIN public.tbl_prestudentstatus status USING(prestudent_id)
JOIN public.tbl_person USING(person_id)
JOIN lehre.tbl_studienplan stpl USING(studienplan_id)
JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz
JOIN public.tbl_studiensemester sem USING(studiensemester_kurzbz)
WHERE
(stpl.orgform_kurzbz = 'DUA' OR status.orgform_kurzbz = 'DUA')
AND pre.dual = FALSE
AND status.studiensemester_kurzbz=?
AND pre.bismelden
AND stg.melderelevant
AND NOT EXISTS (
SELECT 1
FROM
public.tbl_prestudentstatus
JOIN lehre.tbl_studienplan USING(studienplan_id)
JOIN public.tbl_studiensemester USING(studiensemester_kurzbz)
WHERE
prestudent_id = pre.prestudent_id
AND
(
-- if there is a newer non-dual status, dual has not to be set
(
(
tbl_studienplan.orgform_kurzbz <> stpl.orgform_kurzbz
OR status.orgform_kurzbz <> tbl_prestudentstatus.orgform_kurzbz
)
AND
(
tbl_studiensemester.ende::date > sem.ende::date
OR (tbl_studiensemester.ende::date = sem.ende::date AND tbl_prestudentstatus.datum::date > status.datum::date)
)
)
OR
-- exclude Abgewiesene - they are not reported
tbl_prestudentstatus.status_kurzbz = 'Abgewiesener'
)
)";
if (isset($studiengang_kz))
{
$qry .= " AND stg.studiengang_kz = ?";
$params[] = $studiengang_kz;
}
if (isset($prestudent_id))
{
$qry .= " AND pre.prestudent_id = ?";
$params[] = $prestudent_id;
}
if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz))
{
$qry .= " AND stg.studiengang_kz NOT IN ?";
$params[] = $exkludierte_studiengang_kz;
}
return $this->_db->execReadOnlyQuery($qry, $params);
}
}
@@ -67,6 +67,7 @@ class InaktiverStudentAktiverStatus extends PlausiChecker
$prestudent_id = null,
$exkludierte_studiengang_kz = null
) {
$this->_ci->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
$aktStudiensemesterRes = $this->_ci->StudiensemesterModel->getAkt();
if (isError($aktStudiensemesterRes)) return $aktStudiensemesterRes;
@@ -0,0 +1,36 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Student in dual Studiengang should have set the dual flag to true.
*/
class CORE_STUDENTSTATUS_0016 implements IIssueResolvedChecker
{
public function checkIfIssueIsResolved($params)
{
if (!isset($params['prestudent_id']) || !is_numeric($params['prestudent_id']))
return error('Prestudent Id missing, issue_id: '.$params['issue_id']);
if (!isset($params['studiensemester_kurzbz']) || isEmptyString($params['studiensemester_kurzbz']))
return error('Studiensemester missing, issue_id: '.$params['issue_id']);
$this->_ci =& get_instance(); // get code igniter instance
$this->_ci->load->library('issues/plausichecks/DualesStudiumOhneMarkierung');
// check if issue persists
$checkRes = $this->_ci->dualesstudiumohnemarkierung->getDualesStudiumOhneMarkierung(
$params['studiensemester_kurzbz'],
null,
$params['prestudent_id']
);
if (isError($checkRes)) return $checkRes;
if (hasData($checkRes))
return success(false); // not resolved if issue is still present
else
return success(true); // resolved otherwise
}
}
@@ -0,0 +1,69 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\IValidation;
/**
* Description of AbstractBestandteil
*
* @author bambi
*/
abstract class AbstractBestandteil implements IValidation
{
protected $isvalid;
protected $validationerrors;
protected $modifiedcolumns;
protected $fromdb;
public function __construct()
{
$this->isvalid = false;
$this->validationerrors = array();
$this->modifiedcolumns = array();
$this->fromdb = false;
}
public function isDirty() {
return count($this->modifiedcolumns) > 0;
}
protected function markDirty($columnname, $old_value, $new_value) {
if( $this->fromdb ) {
// data comes from db dont check for changes
if( isset($this->modifiedcolumns[$columnname]) ) {
unset($this->modifiedcolumns[$columnname]);
}
return;
}
if( is_bool($new_value) && ($old_value !== $new_value) ) {
$this->modifiedcolumns[$columnname] = $columnname;
} else if($old_value != $new_value) {
$this->modifiedcolumns[$columnname] = $columnname;
}
}
public function isValid()
{
return $this->isvalid;
}
public function getValidationErrors()
{
return $this->validationerrors;
}
public function addValidationError($errormsg)
{
if( !in_array($errormsg, $this->validationerrors, true) )
{
$this->validationerrors[] = $errormsg;
}
$this->isvalid = false;
}
abstract public function hydrateByStdClass($data, $fromdb=false);
}
@@ -0,0 +1,296 @@
<?php
namespace vertragsbestandteil;
require_once __DIR__ . '/IValidation.php';
require_once __DIR__ . '/AbstractBestandteil.php';
use vertragsbestandteil\AbstractBestandteil;
use vertragsbestandteil\IValidation;
const TYPE_ECHT = 'echterdv';
const TYPE_STUDENTISCHE_HILFSKRAFT = 'studentischehilfskr';
const TYPE_FREI = 'freierdv';
const TYPE_EXTERN = 'externerlehrender';
const TYPE_GAST = 'gastlektor';
const TYPE_ECHT_FREI = 'echterfreier';
const TYPE_WERKVERTRAG = 'werkvertrag';
const TYPE_UEBERLASSUNG = 'ueberlassungsvertrag';
class Dienstverhaeltnis extends AbstractBestandteil {
protected $dienstverhaeltnis_id;
protected $mitarbeiter_uid;
protected $vertragsart_kurzbz;
protected $oe_kurzbz;
protected $checkoverlap;
protected $von;
protected $bis;
protected $insertamum;
protected $insertvon;
protected $updateamum;
protected $updatevon;
protected $dvendegrund_kurzbz;
protected $dvendegrund_anmerkung;
public function __construct()
{
parent::__construct();
$this->checkoverlap = true;
}
public function hydrateByStdClass($data, $fromdb=false)
{
$this->fromdb = $fromdb;
isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id);
isset($data->mitarbeiter_uid) && $this->setMitarbeiter_uid($data->mitarbeiter_uid);
isset($data->vertragsart_kurzbz) && $this->setVertragsart_kurzbz($data->vertragsart_kurzbz);
isset($data->checkoverlap) && $this->setCheckoverlap($data->checkoverlap);
isset($data->oe_kurzbz) && $this->setOe_kurzbz($data->oe_kurzbz);
isset($data->von) && $this->setVon($data->von);
isset($data->bis) && $this->setBis($data->bis);
isset($data->insertamum) && $this->setInsertamum($data->insertamum);
isset($data->insertvon) && $this->setInsertvon($data->insertvon);
isset($data->updateamum) && $this->setUpdateamum($data->updateamum);
isset($data->updatevon) && $this->setUpdatevon($data->updatevon);
isset($data->dvendegrund_kurzbz) && $this->setDvendegrund_kurzbz($data->dvendegrund_kurzbz);
isset($data->dvendegrund_anmerkung) && $this->setDvendegrund_anmerkung($data->dvendegrund_anmerkung);
$this->fromdb = false;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(),
'mitarbeiter_uid' => $this->getMitarbeiter_uid(),
'vertragsart_kurzbz' => $this->getVertragsart_kurzbz(),
'oe_kurzbz' => $this->getOe_kurzbz(),
'von' => $this->getVon(),
'bis' => $this->getBis(),
'insertamum' => $this->getInsertamum(),
'insertvon' => $this->getInsertvon(),
'updateamum' => $this->getUpdateamum(),
'updatevon' => $this->getUpdatevon(),
'dvendegrund_kurzbz' => $this->getDvendegrund_kurzbz(),
'dvendegrund_anmerkung' => $this->getDvendegrund_anmerkung()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()}
mitarbeiter_uid: {$this->getMitarbeiter_uid()}
vertragsart_kurzbz: {$this->getVertragsart_kurzbz()}
oe_kurzbz: {$this->getOe_kurzbz()}
von: {$this->getVon()}
bis: {$this->getBis()}
EOTXT;
return $txt;
}
public function getDienstverhaeltnis_id()
{
return $this->dienstverhaeltnis_id;
}
public function getMitarbeiter_uid()
{
return $this->mitarbeiter_uid;
}
public function getVertragsart_kurzbz()
{
return $this->vertragsart_kurzbz;
}
public function getOe_kurzbz()
{
return $this->oe_kurzbz;
}
public function getVon()
{
return $this->von;
}
public function getBis()
{
return $this->bis;
}
public function getInsertamum()
{
return $this->insertamum;
}
public function getInsertvon()
{
return $this->insertvon;
}
public function getUpdateamum()
{
return $this->updateamum;
}
public function getUpdatevon()
{
return $this->updatevon;
}
public function getDvendegrund_kurzbz()
{
return $this->dvendegrund_kurzbz;
}
public function getDvendegrund_anmerkung()
{
return $this->dvendegrund_anmerkung;
}
public function setDienstverhaeltnis_id($dienstverhaeltnis_id)
{
$this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id);
$this->dienstverhaeltnis_id = $dienstverhaeltnis_id;
return $this;
}
public function setMitarbeiter_uid($mitarbeiter_uid)
{
$this->markDirty('mitarbeiter_uid', $this->mitarbeiter_uid, $mitarbeiter_uid);
$this->mitarbeiter_uid = $mitarbeiter_uid;
return $this;
}
public function setVertragsart_kurzbz($vertragsart_kurzbz)
{
$this->markDirty('vertragsart_kurzbz', $this->vertragsart_kurzbz, $vertragsart_kurzbz);
$this->vertragsart_kurzbz = $vertragsart_kurzbz;
return $this;
}
public function setCheckoverlap(bool $checkoverlap)
{
$this->checkoverlap = $checkoverlap;
}
public function setOe_kurzbz($oe_kurzbz)
{
$this->markDirty('oe_kurzbz', $this->oe_kurzbz, $oe_kurzbz);
$this->oe_kurzbz = $oe_kurzbz;
return $this;
}
public function setVon($von)
{
$this->markDirty('von', $this->von, $von);
$this->von = $von;
return $this;
}
public function setBis($bis)
{
$this->markDirty('bis', $this->bis, $bis);
$this->bis = $bis;
return $this;
}
public function setInsertamum($insertamum)
{
$this->markDirty('insertamum', $this->insertamum, $insertamum);
$this->insertamum = $insertamum;
return $this;
}
public function setInsertvon($insertvon)
{
$this->markDirty('insertvon', $this->insertvon, $insertvon);
$this->insertvon = $insertvon;
return $this;
}
public function setUpdateamum($updateamum)
{
$this->markDirty('updateamum', $this->updateamum, $updateamum);
$this->updateamum = $updateamum;
return $this;
}
public function setUpdatevon($updatevon)
{
$this->markDirty('updatevon', $this->updatevon, $updatevon);
$this->updatevon = $updatevon;
return $this;
}
public function setDvendegrund_kurzbz($dvendegrund_kurzbz)
{
$this->markDirty('dvendegrund_kurzbz', $this->dvendegrund_kurzbz, $dvendegrund_kurzbz);
$this->dvendegrund_kurzbz = $dvendegrund_kurzbz;
return $this;
}
public function setDvendegrund_anmerkung($dvendegrund_anmerkung)
{
$this->markDirty('dvendegrund_anmerkung', $this->dvendegrund_anmerkung, $dvendegrund_anmerkung);
$this->dvendegrund_anmerkung = $dvendegrund_anmerkung;
return $this;
}
public function validate() {
//do Validation here
$ci = get_instance();
$ci->load->library('vertragsbestandteil/VertragsbestandteilLib',
null, 'VertragsbestandteilLib');
if( empty($this->mitarbeiter_uid) ) {
$this->validationerrors[] = 'Mitarbeiter_UID fehlt.';
}
if( empty($this->oe_kurzbz) ) {
$this->validationerrors[] = 'Unternehmen fehlt.';
}
if( empty($this->vertragsart_kurzbz) ) {
$this->validationerrors[] = 'Vertragsart fehlt.';
}
$von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von);
$bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
if( false === $von ) {
$this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.';
}
if( $this->bis !== null && $bis === false ) {
$this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.';
}
if( $this-> bis !== null && $von && $bis && $von > $bis ) {
$this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.';
}
if( $this->checkoverlap && !(in_array($this->vertragsart_kurzbz, array('werkvertrag', 'studentischehilfskr')) )
&& $ci->VertragsbestandteilLib->isOverlappingExistingDV($this) )
{
$this->validationerrors[] = 'Es existiert bereits ein überlappendes Dienstverhältnis';
}
// return status after Validation
if( count($this->validationerrors) > 0 ) {
$this->isvalid = false;
} else {
$this->isvalid = true;
}
return $this->isvalid;
}
}
@@ -0,0 +1,360 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\AbstractBestandteil;
use DateTimeImmutable;
/**
* Salary always depends on employment (Dienstverhältnis) and optionally on part of contract (Vetragsbestandteil)
*/
class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializable
{
protected $gehaltsbestandteil_id;
protected $dienstverhaeltnis_id;
protected $vertragsbestandteil_id;
protected $gehaltstyp_kurzbz;
protected $von;
protected $bis;
protected $anmerkung;
protected $grundbetrag;
protected $betrag_valorisiert;
protected $valorisierungssperre;
protected $valorisierung;
protected $auszahlungen;
protected $insertamum;
protected $insertvon;
protected $updateamum;
protected $updatevon;
public function __construct()
{
parent::__construct();
}
public function hydrateByStdClass($data, $fromdb=false)
{
$this->fromdb = $fromdb;
isset($data->gehaltsbestandteil_id) && $this->setGehaltsbestandteil_id($data->gehaltsbestandteil_id);
isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id);
isset($data->vertragsbestandteil_id) && $this->setVertragsbestandteil_id($data->vertragsbestandteil_id);
isset($data->gehaltstyp_kurzbz) && $this->setGehaltstyp_kurzbz($data->gehaltstyp_kurzbz);
isset($data->von) && $this->setVon($data->von);
isset($data->bis) && $this->setBis($data->bis);
isset($data->anmerkung) && $this->setAnmerkung($data->anmerkung);
isset($data->grundbetrag) && $this->setGrundbetrag($data->grundbetrag);
isset($data->betrag_valorisiert) && $this->setBetrag_valorisiert($data->betrag_valorisiert);
isset($data->valorisierungssperre) && $this->setValorisierungssperre($data->valorisierungssperre);
isset($data->valorisierung) && $this->setValorisierung($data->valorisierung);
isset($data->auszahlungen) && $this->setAuszahlungen($data->auszahlungen);
isset($data->insertamum) && $this->setInsertamum($data->insertamum);
isset($data->insertvon) && $this->setInsertvon($data->insertvon);
isset($data->updateamum) && $this->setUpdateamum($data->updateamum);
isset($data->updatevon) && $this->setUpdatevon($data->updatevon);
$this->fromdb = false;
}
public function getGehaltsbestandteil_id()
{
return $this->gehaltsbestandteil_id;
}
public function getDienstverhaeltnis_id()
{
return $this->dienstverhaeltnis_id;
}
public function getVertragsbestandteil_id()
{
return $this->vertragsbestandteil_id;
}
public function getGehaltstyp_kurzbz()
{
return $this->gehaltstyp_kurzbz;
}
public function getVon()
{
return $this->von;
}
public function getBis()
{
return $this->bis;
}
public function getVonDateTime()
{
return $this->toDateTime($this->von);
}
public function getBisDateTime()
{
return $this->toDateTime($this->bis);
}
protected function toDateTime($d) {
if ($d == null) return null;
return new DateTimeImmutable($d);
}
public function getAnmerkung()
{
return $this->anmerkung;
}
public function getGrundbetrag()
{
return $this->grundbetrag;
}
public function getBetrag_valorisiert()
{
return $this->betrag_valorisiert;
}
public function getValorisierungssperre()
{
return $this->valorisierungssperre;
}
public function getValorisierung()
{
return $this->valorisierung;
}
public function getAuszahlungen()
{
return $this->auszahlungen;
}
public function getInsertamum()
{
return $this->insertamum;
}
public function getInsertvon()
{
return $this->insertvon;
}
public function getUpdateamum()
{
return $this->updateamum;
}
public function getUpdatevon()
{
return $this->updatevon;
}
public function setGehaltsbestandteil_id($gehaltsbestandteil_id)
{
$this->markDirty('gehaltsbestandteil_id', $this->gehaltsbestandteil_id, $gehaltsbestandteil_id);
$this->gehaltsbestandteil_id = $gehaltsbestandteil_id;
return $this;
}
public function setDienstverhaeltnis_id($dienstverhaeltnis_id)
{
$this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id);
$this->dienstverhaeltnis_id = $dienstverhaeltnis_id;
return $this;
}
public function setVertragsbestandteil_id($vertragsbestandteil_id)
{
$this->markDirty('vertragsbestandteil_id', $this->vertragsbestandteil_id, $vertragsbestandteil_id);
$this->vertragsbestandteil_id = $vertragsbestandteil_id;
return $this;
}
public function setGehaltstyp_kurzbz($gehaltstyp_kurzbz)
{
$this->markDirty('gehaltstyp_kurzbz', $this->gehaltstyp_kurzbz, $gehaltstyp_kurzbz);
$this->gehaltstyp_kurzbz = $gehaltstyp_kurzbz;
return $this;
}
public function setVon($von)
{
$this->markDirty('von', $this->von, $von);
$this->von = $von;
return $this;
}
public function setBis($bis)
{
$this->markDirty('bis', $this->bis, $bis);
$this->bis = $bis;
return $this;
}
public function setAnmerkung($anmerkung)
{
$this->markDirty('anmerkung', $this->anmerkung, $anmerkung);
$this->anmerkung = $anmerkung;
return $this;
}
public function setGrundbetrag($grundbetrag)
{
$this->markDirty('grundbetrag', $this->grundbetrag, $grundbetrag);
$this->grundbetrag = $grundbetrag;
return $this;
}
public function setBetrag_valorisiert($betrag_valorisiert)
{
$this->markDirty('betrag_valorisiert', $this->betrag_valorisiert, $betrag_valorisiert);
$this->betrag_valorisiert = $betrag_valorisiert;
return $this;
}
public function setValorisierungssperre($valorisierungssperre)
{
$this->markDirty('valorisierungssperre', $this->valorisierungssperre, $valorisierungssperre);
$this->valorisierungssperre = $valorisierungssperre;
return $this;
}
public function setValorisierung($valorisierung)
{
$this->markDirty('valorisierung', $this->valorisierung, $valorisierung);
$this->valorisierung = $valorisierung;
return $this;
}
public function setAuszahlungen($auszahlungen)
{
$this->markDirty('auszahlungen', $this->auszahlungen, $auszahlungen);
$this->auszahlungen = $auszahlungen;
return $this;
}
public function setInsertamum($insertamum)
{
$this->markDirty('insertamum', $this->insertamum, $insertamum);
$this->insertamum = $insertamum;
return $this;
}
public function setInsertvon($insertvon)
{
$this->markDirty('insertvon', $this->insertvon, $insertvon);
$this->insertvon = $insertvon;
return $this;
}
public function setUpdateamum($updateamum)
{
$this->markDirty('updateamum', $this->updateamum, $updateamum);
$this->updateamum = $updateamum;
return $this;
}
public function setUpdatevon($updatevon)
{
$this->markDirty('updatevon', $this->updatevon, $updatevon);
$this->updatevon = $updatevon;
return $this;
}
public function jsonSerialize()
{
$vars = get_object_vars($this);
unset($vars['CI']);
return $vars;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'gehaltsbestandteil_id' => $this->getGehaltsbestandteil_id(),
'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(),
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'gehaltstyp_kurzbz' => $this->getGehaltstyp_kurzbz(),
'von' => $this->getVon(),
'bis' => $this->getBis(),
'anmerkung' => $this->getAnmerkung(),
'grundbetrag' => $this->getGrundbetrag(),
'betrag_valorisiert' => $this->getBetrag_valorisiert(),
'valorisierungssperre' => $this->getValorisierungssperre(),
'valorisierung' => $this->getValorisierung(),
'auszahlungen' => $this->getAuszahlungen(),
'insertamum' => $this->getInsertamum(),
'insertvon' => $this->getInsertvon(),
'updateamum' => $this->getUpdateamum(),
'updatevon' => $this->getUpdatevon()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
gehaltsbestandteil_id: {$this->getGehaltsbestandteil_id()}
dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()}
vertragsbestandteil_id: {$this->getVertragsbestandteil_id()}
gehaltstyp_kurzbz: {$this->getGehaltstyp_kurzbz()}
von: {$this->getVon()}
bis: {$this->getBis()}
anmerkung: {$this->getAnmerkung()}
grundbetrag: {$this->getGrundbetrag()}
betrag_valorisiert: {$this->getBetrag_valorisiert()}
valorisierungssperre: {$this->getValorisierungssperre()}
valorisierung: {$this->getValorisierung()}
auszahlungen: {$this->getAuszahlungen()}
insertamum: {$this->getInsertamum()}
insertvon: {$this->getInsertvon()}
updateamum: {$this->getUpdateamum()}
updatevon: {$this->getUpdatevon()}
EOTXT;
return $txt;
}
public function validate() {
//do Validation here
if( empty($this->gehaltstyp_kurzbz) )
{
$this->validationerrors[] = "Ein Gehaltstyp muss ausgewählt sein.";
}
if( empty($this->grundbetrag) )
{
$this->validationerrors[] = "Betrag fehlt.";
}
$von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von);
$bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
if( false === $von ) {
$this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.';
}
if( $this->bis !== null && $bis === false ) {
$this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.';
}
if( $this-> bis !== null && $von && $bis && $von > $bis ) {
$this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.';
}
// return status after Validation
if( count($this->validationerrors) > 0 ) {
$this->isvalid = false;
} else {
$this->isvalid = true;
}
return $this->isvalid;
}
}
@@ -0,0 +1,149 @@
<?php
require_once __DIR__ . '/IValidation.php';
require_once __DIR__ . '/AbstractBestandteil.php';
require_once __DIR__ . '/Gehaltsbestandteil.php';
use vertragsbestandteil\Gehaltsbestandteil;
/**
* Description of GehaltsbestandteilLib
*
* @author bambi
*/
class GehaltsbestandteilLib
{
protected $CI;
/** @var Gehaltsbestandteil_model */
protected $GehaltsbestandteilModel;
protected $loggedInUser;
public function __construct()
{
$this->loggedInUser = getAuthUID();
$this->CI = get_instance();
$this->CI->load->model('vertragsbestandteil/Gehaltsbestandteil_model',
'GehaltsbestandteilModel');
$this->CI->load->library('extensions/FHC-Core-Personalverwaltung/abrechnung/GehaltsLib');
$this->GehaltsbestandteilModel = $this->CI->GehaltsbestandteilModel;
}
public function fetchGehaltsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false)
{
return $this->GehaltsbestandteilModel->getGehaltsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture);
}
public function fetchGehaltsbestandteil($gehaltsbestandteil_id)
{
return $this->GehaltsbestandteilModel->getGehaltsbestandteil($gehaltsbestandteil_id);
}
public function storeGehaltsbestandteile($gehaltsbestandteile)
{
foreach( $gehaltsbestandteile as $gehaltsbestandteil )
{
$this->storeGehaltsbestandteil($gehaltsbestandteil);
}
}
public function storeGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
{
try
{
$this->setUIDtoPGSQL();
if( intval($gehaltsbestandteil->getGehaltsbestandteil_id()) > 0 )
{
$this->updateGehaltsbestandteil($gehaltsbestandteil);
}
else
{
$this->insertGehaltsbestandteil($gehaltsbestandteil);
}
}
catch (Exception $ex)
{
log_message('debug', "Storing Gehaltsbestandteil failed. " . $ex->getMessage());
throw new Exception('Storing Gehaltsbestandteil failed.');
}
}
protected function insertGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
{
$gehaltsbestandteil->setInsertvon($this->loggedInUser)
->setInsertamum(strftime('%Y-%m-%d %H:%M:%S'));
$ret = $this->GehaltsbestandteilModel->insert($gehaltsbestandteil->toStdClass(),
$this->GehaltsbestandteilModel->getEncryptedColumns());
if( hasData($ret) )
{
$gehaltsbestandteil->setGehaltsbestandteil_id(getData($ret));
}
else
{
throw new Exception('error inserting gehaltsbestandteil');
}
}
protected function updateGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
{
if(!$gehaltsbestandteil->isDirty()) {
return;
}
$gehaltsbestandteil->setUpdatevon($this->loggedInUser)
->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S'));
$ret = $this->GehaltsbestandteilModel->update($gehaltsbestandteil->getGehaltsbestandteil_id(),
$gehaltsbestandteil->toStdClass(),
$this->GehaltsbestandteilModel->getEncryptedColumns());
if(isError($ret) )
{
throw new Exception('error updating gehaltsbestandteil');
}
}
public function deleteGehaltsbestandteile($gehaltsbestandteile)
{
foreach( $gehaltsbestandteile as $gehaltsbestandteil )
{
$this->deleteGehaltsbestandteil($gehaltsbestandteil);
}
}
public function deleteGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
{
$this->setUIDtoPGSQL();
// delete Gehaltsabrechnung
$ret = $this->CI->gehaltslib->deleteAbrechnung($gehaltsbestandteil);
//
$ret = $this->GehaltsbestandteilModel->delete($gehaltsbestandteil->getGehaltsbestandteil_id());
if (isError($ret))
{
throw new Exception('error deleting gehaltsbestandteil');
}
}
public function endGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil, $enddate)
{
$this->setUIDtoPGSQL();
if( $gehaltsbestandteil->getBis() !== null && $gehaltsbestandteil->getBis() < $enddate )
{
return;
}
$gehaltsbestandteil->setBis($enddate);
$this->updateGehaltsbestandteil($gehaltsbestandteil);
}
protected function setUIDtoPGSQL() {
$ret = $this->GehaltsbestandteilModel
->execReadOnlyQuery('SET LOCAL pv21.uid TO \''
. $this->loggedInUser . '\'');
if(isError($ret))
{
throw new Exception('error setting uid to pgsql');
}
}
}
@@ -0,0 +1,18 @@
<?php
namespace vertragsbestandteil;
/**
* Description of IValidation
*
* @author bambi
*/
interface IValidation
{
public function isValid();
public function getValidationErrors();
public function validate();
public function addValidationError($errormsg);
}
@@ -0,0 +1,111 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFreitext;
/**
* Description of OverlapChecker
*
* @author bambi
*/
class OverlapChecker
{
protected $CI;
/**
* @var Vertragsbestandteil_model
*/
protected $VertragsbestandteilModel;
/**
* @var VertragsbestandteilFreitext_model
*/
protected $VertragsbestandteilFreitextModel;
/**
* @var VertragsbestandteilTyp_model
*/
protected $VertragsbestandteilTypModel;
/**
* @var VertragsbestandteilFreitexttyp_model
*/
protected $VertragsbestandteilFreitexttypModel;
protected static $instance = null;
public static function getInstance()
{
if( null === self::$instance )
{
self::$instance = new OverlapChecker();
}
return self::$instance;
}
private function __construct()
{
$this->CI = get_instance();
$this->CI->load->model('vertragsbestandteil/Vertragsbestandteil_model',
'VertragsbestandteilModel');
$this->VertragsbestandteilModel = $this->CI->VertragsbestandteilModel;
$this->CI->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model',
'VertragsbestandteilFreitextModel');
$this->VertragsbestandteilFreitextModel = $this->CI->VertragsbestandteilFreitextModel;
$this->CI->load->model('vertragsbestandteil/Vertragsbestandteiltyp_model',
'VertragsbestandteilTypModel');
$this->VertragsbestandteilTypModel = $this->CI->VertragsbestandteilTypModel;
$this->CI->load->model('vertragsbestandteil/VertragsbestandteilFreitexttyp_model',
'VertragsbestandteilFreitexttypModel');
$this->VertragsbestandteilFreitexttypModel = $this->CI->VertragsbestandteilFreitexttypModel;
}
public function overlapsVB(Vertragsbestandteil $vb)
{
$result = $this->VertragsbestandteilTypModel->load($vb->getVertragsbestandteiltyp_kurzbz());
if( null === ($vertragsbestandteiltyp = getData($result)) )
{
throw new Exception('vertragsbestandteiltyp: '
. $vb->getVertragsbestandteiltyp_kurzbz() . ' not found.');
}
if( true === $vertragsbestandteiltyp[0]->ueberlappend )
{
// vertragsbestandteiltyp can overlap
return false;
}
if( $this->VertragsbestandteilModel->countOverlappingVBsOfSameType($vb) === 0 )
{
return false;
}
else
{
return true;
}
}
public function overlapsFreitext(VertragsbestandteilFreitext $vbft)
{
$result = $this->VertragsbestandteilFreitexttypModel->load($vbft->getFreitexttypKurzbz());
if( null === ($vertragsbestandteilfreitexttyp = getData($result)) )
{
throw new Exception('vertragsbestandteilfreitexttyp: '
. $vbft->getFreitexttypKurzbz() . ' not found.');
}
if( true === $vertragsbestandteilfreitexttyp[0]->ueberlappend )
{
// freitexttyp can overlap
return false;
}
if( $this->VertragsbestandteilFreitextModel->countOverlappingVBFreitextsOfSameType($vbft) === 0 )
{
return false;
}
else
{
return true;
}
}
private function __clone() {}
}
@@ -0,0 +1,265 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\AbstractBestandteil;
/**
* Description of Vertragsbestandteil
*
* @author bambi
*/
abstract class Vertragsbestandteil extends AbstractBestandteil implements \JsonSerializable
{
protected $vertragsbestandteil_id;
protected $dienstverhaeltnis_id;
protected $von;
protected $bis;
protected $vertragsbestandteiltyp_kurzbz;
protected $insertamum;
protected $insertvon;
protected $updateamum;
protected $updatevon;
protected $gehaltsbestandteile;
public function __construct()
{
parent::__construct();
$this->gehaltsbestandteile = array();
}
public function hydrateByStdClass($data, $fromdb=false)
{
$this->fromdb = $fromdb;
isset($data->vertragsbestandteil_id) && $this->setVertragsbestandteil_id($data->vertragsbestandteil_id);
isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id);
isset($data->von) && $this->setVon($data->von);
isset($data->bis) && $this->setBis($data->bis);
isset($data->vertragsbestandteiltyp_kurzbz) && $this->setVertragsbestandteiltyp_kurzbz($data->vertragsbestandteiltyp_kurzbz);
isset($data->insertamum) && $this->setInsertamum($data->insertamum);
isset($data->insertvon) && $this->setInsertvon($data->insertvon);
isset($data->updateamum) && $this->setUpdateamum($data->updateamum);
isset($data->updatevon) && $this->setUpdatevon($data->updatevon);
$this->fromdb = false;
}
public function addGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
{
$gehaltsbestandteil->setDienstverhaeltnis_id($this->getDienstverhaeltnis_id());
$gehaltsbestandteil->setVertragsbestandteil_id($this->getVertragsbestandteil_id());
$this->gehaltsbestandteile[] = $gehaltsbestandteil;
return $this;
}
public function getGehaltsbestandteile()
{
return $this->gehaltsbestandteile;
}
public function getVertragsbestandteil_id()
{
return $this->vertragsbestandteil_id;
}
public function getDienstverhaeltnis_id()
{
return $this->dienstverhaeltnis_id;
}
public function getVon()
{
return $this->von;
}
public function getBis()
{
return $this->bis;
}
public function getVertragsbestandteiltyp_kurzbz()
{
return $this->vertragsbestandteiltyp_kurzbz;
}
public function getInsertamum()
{
return $this->insertamum;
}
public function getInsertvon()
{
return $this->insertvon;
}
public function getUpdateamum()
{
return $this->updateamum;
}
public function getUpdatevon()
{
return $this->updatevon;
}
public function setGehaltsbestandteile($gehaltsbestandteile)
{
$this->gehaltsbestandteile = $gehaltsbestandteile;
return $this;
}
public function setVertragsbestandteil_id($vertragsbestandteil_id)
{
$this->markDirty('vertragsbestandteil_id', $this->vertragsbestandteil_id, $vertragsbestandteil_id);
$this->vertragsbestandteil_id = $vertragsbestandteil_id;
foreach ($this->gehaltsbestandteile as $gehaltsbestandteil)
{
$gehaltsbestandteil->setVertragsbestandteil_id($vertragsbestandteil_id);
}
return $this;
}
public function setDienstverhaeltnis_id($dienstverhaeltnis_id)
{
$this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id);
$this->dienstverhaeltnis_id = $dienstverhaeltnis_id;
foreach ($this->gehaltsbestandteile as $gehaltsbestandteil)
{
$gehaltsbestandteil->setDienstverhaeltnis_id($dienstverhaeltnis_id);
}
return $this;
}
public function setVon($von)
{
$this->markDirty('von', $this->von, $von);
$this->von = $von;
return $this;
}
public function setBis($bis)
{
$this->markDirty('bis', $this->bis, $bis);
$this->bis = $bis;
return $this;
}
public function setVertragsbestandteiltyp_kurzbz($vertragsbestandteiltyp_kurzbz)
{
$this->markDirty('vertragsbestandteiltyp_kurzbz', $this->vertragsbestandteiltyp_kurzbz, $vertragsbestandteiltyp_kurzbz);
$this->vertragsbestandteiltyp_kurzbz = $vertragsbestandteiltyp_kurzbz;
return $this;
}
public function setInsertamum($insertamum)
{
$this->markDirty('insertamum', $this->insertamum, $insertamum);
$this->insertamum = $insertamum;
return $this;
}
public function setInsertvon($insertvon)
{
$this->markDirty('insertvon', $this->insertvon, $insertvon);
$this->insertvon = $insertvon;
return $this;
}
public function setUpdateamum($updateamum)
{
$this->markDirty('updateamum', $this->updateamum, $updateamum);
$this->updateamum = $updateamum;
return $this;
}
public function setUpdatevon($updatevon)
{
$this->markDirty('updatevon', $this->updatevon, $updatevon);
$this->updatevon = $updatevon;
return $this;
}
public function baseToStdClass() {
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(),
'von' => $this->getVon(),
'bis' => $this->getBis(),
'vertragsbestandteiltyp_kurzbz' => $this->getVertragsbestandteiltyp_kurzbz(),
'insertamum' => $this->getInsertamum(),
'insertvon' => $this->getInsertvon(),
'updateamum' => $this->getUpdateamum(),
'updatevon' => $this->getUpdatevon(),
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function jsonSerialize()
{
$vars = get_object_vars($this);
unset($vars['CI']);
// TODO cleanup workaroung for vb freitext where db column is anmerkung and formfield is freitext
if( isset($vars['anmerkung']) ) {
$vars['freitext'] = $vars['anmerkung'];
}
return $vars;
}
public function __toString()
{
return <<<EOTXT
vertragsbestandteil_id: {$this->getVertragsbestandteil_id()}
dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()}
von: {$this->getVon()}
bis: {$this->getBis()}
vertragsbestandteiltyp_kurzbz: {$this->getVertragsbestandteiltyp_kurzbz()}
insertamum: {$this->getInsertamum()}
insertvon: {$this->getInsertvon()}
updateamum: {$this->getUpdateamum()}
updatevon: {$this->getUpdatevon()}
EOTXT;
}
public function beforePersist() {
// can be overridden in childs
}
public function afterDelete() {
// can be overridden in childs
}
public function validate() {
$von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von);
$bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
if( false === $von ) {
$this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.';
}
if( $this->bis !== null && $bis === false ) {
$this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.';
}
if( $this-> bis !== null && $von && $bis && $von > $bis ) {
$this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.';
}
if( count($this->validationerrors) > 0 ) {
$this->isvalid = false;
} else {
$this->isvalid = true;
}
return $this->isvalid;
}
public abstract function toStdClass();
}
@@ -0,0 +1,137 @@
<?php
namespace vertragsbestandteil;
use Exception;
use vertragsbestandteil\VertragsbestandteilStunden;
/**
* Description of VertragsbestandteilFactory
*
* @author bambi
*/
class VertragsbestandteilFactory
{
const VERTRAGSBESTANDTEIL_STUNDEN = 'stunden';
const VERTRAGSBESTANDTEIL_FUNKTION = 'funktion';
const VERTRAGSBESTANDTEIL_GEHALT = 'gehalt';
const VERTRAGSBESTANDTEIL_FREITEXT = 'freitext';
const VERTRAGSBESTANDTEIL_KARENZ = 'karenz';
const VERTRAGSBESTANDTEIL_BEFRISTUNG = 'befristung';
const VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST = 'kuendigungsfrist';
const VERTRAGSBESTANDTEIL_KV = 'kv';
const VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH = 'urlaubsanspruch';
const VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG = 'zeitaufzeichnung';
const VERTRAGSBESTANDTEIL_LEHRE = 'lehre';
public static function getVertragsbestandteil($data, $fromdb=false)
{
$vertragsbestandteiltyp_kurzbz = isset($data->vertragsbestandteiltyp_kurzbz)
? $data->vertragsbestandteiltyp_kurzbz : false;
if( false === $vertragsbestandteiltyp_kurzbz )
{
throw new Exception('Missing Parameter vertragsbestandteiltyp_kurzbz');
}
$vertragsbestandteil = null;
switch ($vertragsbestandteiltyp_kurzbz)
{
case self::VERTRAGSBESTANDTEIL_FREITEXT:
$vertragsbestandteil = new VertragsbestandteilFreitext();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_FUNKTION:
$vertragsbestandteil = new VertragsbestandteilFunktion();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_KARENZ:
$vertragsbestandteil = new VertragsbestandteilKarenz();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST:
$vertragsbestandteil = new VertragsbestandteilKuendigungsfrist();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_STUNDEN:
$vertragsbestandteil = new VertragsbestandteilStunden();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH:
$vertragsbestandteil = new VertragsbestandteilUrlaubsanspruch();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG:
$vertragsbestandteil = new VertragsbestandteilZeitaufzeichnung();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
default:
throw new Exception('Unknown vertragsbestandteiltyp_kurzbz '
. $vertragsbestandteiltyp_kurzbz);
}
return $vertragsbestandteil;
}
public static function getVertragsbestandteilDBModel($vertragsbestandteil_kurzbz): \DB_model
{
$CI = get_instance();
$vertragsbestandteildbmodel = null;
switch ($vertragsbestandteil_kurzbz)
{
case self::VERTRAGSBESTANDTEIL_FREITEXT:
$CI->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model',
'VertragsbestandteilFreitext_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilFreitext_model;
break;
case self::VERTRAGSBESTANDTEIL_FUNKTION:
$CI->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model',
'VertragsbestandteilFunktion_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilFunktion_model;
break;
case self::VERTRAGSBESTANDTEIL_KARENZ:
$CI->load->model('vertragsbestandteil/VertragsbestandteilKarenz_model',
'VertragsbestandteilKarenz_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilKarenz_model;
break;
case self::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST:
$CI->load->model('vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model',
'VertragsbestandteilKuendigungsfrist_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilKuendigungsfrist_model;
break;
case self::VERTRAGSBESTANDTEIL_STUNDEN:
$CI->load->model('vertragsbestandteil/VertragsbestandteilStunden_model',
'VertragsbestandteilStunden_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilStunden_model;
break;
case self::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH:
$CI->load->model('vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model',
'VertragsbestandteilUrlaubsanspruch_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilUrlaubsanspruch_model;
break;
case self::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG:
$CI->load->model('vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model',
'VertragsbestandteilZeitaufzeichnung_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilZeitaufzeichnung_model;
break;
default:
throw new Exception('Unknown vertragsbestandteil_kurzbz '
. $vertragsbestandteil_kurzbz);
}
return $vertragsbestandteildbmodel;
}
}
@@ -0,0 +1,134 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
class VertragsbestandteilFreitext extends Vertragsbestandteil
{
protected $freitexttyp_kurzbz;
protected $titel;
protected $anmerkung;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FREITEXT);
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->freitexttyp) && $this->setFreitexttypKurzbz($data->freitexttyp);
isset($data->freitexttyp_kurzbz) && $this->setFreitexttypKurzbz($data->freitexttyp_kurzbz);
isset($data->titel) && $this->setTitel($data->titel);
isset($data->freitext) && $this->setAnmerkung($data->freitext);
isset($data->anmerkung) && $this->setAnmerkung($data->anmerkung);
$this->fromdb = false;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'freitexttyp_kurzbz' => $this->getFreitexttypKurzbz(),
'titel' => $this->getTitel(),
'anmerkung' => $this->getAnmerkung()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
anmerkung: {$this->getAnmerkung()}
titel: {$this->getTitel()}
freitexttyp_kurzbz: {$this->getFreitexttypKurzbz()}
EOTXT;
return parent::__toString() . $txt;
}
/**
* Get the value of anmerkung
*/
public function getAnmerkung()
{
return $this->anmerkung;
}
/**
* Set the value of anmerkung
*/
public function setAnmerkung($anmerkung): self
{
$this->markDirty('anmerkung', $this->anmerkung, $anmerkung);
$this->anmerkung = $anmerkung;
return $this;
}
/**
* Get the value of titel
*/
public function getTitel()
{
return $this->titel;
}
/**
* Set the value of titel
*/
public function setTitel($titel): self
{
$this->markDirty('titel', $this->titel, $titel);
$this->titel = $titel;
return $this;
}
/**
* Get the value of freitexttyp_kurzbz
*/
public function getFreitexttypKurzbz()
{
return $this->freitexttyp_kurzbz;
}
/**
* Set the value of freitexttyp_kurzbz
*/
public function setFreitexttypKurzbz($freitexttyp_kurzbz): self
{
$this->markDirty('freitexttyp_kurzbz', $this->freitexttyp_kurzbz, $freitexttyp_kurzbz);
$this->freitexttyp_kurzbz = $freitexttyp_kurzbz;
return $this;
}
public function validate()
{
if( empty($this->freitexttyp_kurzbz) ) {
$this->validationerrors[] = 'Bitte einen gültigen Freitexttyp auswählen.';
}
if( empty($this->titel) ) {
$this->validationerrors[] = 'Bitte einen Titel angeben.';
}
if( empty($this->anmerkung) ) {
$this->validationerrors[] = 'Bitte eine Beschreibung eingeben.';
}
return parent::validate();
}
}
@@ -0,0 +1,369 @@
<?php
namespace vertragsbestandteil;
use Exception;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
/**
* Description of VertragsbestandteilFunktion
*
* @author bambi
*/
class VertragsbestandteilFunktion extends Vertragsbestandteil
{
protected $benutzerfunktion_id;
protected $benutzerfunktiondata;
protected $CI;
public function __construct()
{
parent::__construct();
$this->benutzerfunktiondata = null;
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FUNKTION);
$this->CI = get_instance();
$this->CI->load->model('person/Benutzerfunktion_model',
'BenutzerfunktionModel');
$this->CI->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model',
'VertragsbestandteilFunktionModel');
$this->CI->load->library('vertragsbestandteil/VertragsbestandteilLib',
null, 'VertragsbestandteilLib');
}
public function isDirty()
{
$isdirty = parent::isDirty();
if( !$isdirty ) {
$bf = $this->loadBenutzerfunktion($this->getBenutzerfunktion_id());
if( !$this->areVbAndBfInSync($bf) )
{
$isdirty = true;
}
}
return $isdirty;
}
public function beforePersist()
{
if( isset($this->benutzerfunktion_id) && intval($this->benutzerfunktion_id) > 0 )
{
$this->beforePersitExisting();
}
else
{
$this->beforePersitNew();
}
}
protected function loadBenutzerfunktion($bfid)
{
$bfres = $this->CI->BenutzerfunktionModel->load($bfid);
if(!hasData($bfres))
{
throw new Exception('failed to load existing Benutzerfunktion');
}
return (getData($bfres))[0];
}
protected function loadPersitedVB($vbid)
{
$vb = $this->CI->VertragsbestandteilLib->fetchVertragsbestandteil($vbid);
if( $vb === null )
{
throw new Exception('failed to load persited Vertragsbestandteil');
}
return $vb;
}
protected function areVbAndBfInSync($bf)
{
$vbvon = $this->getVon();
$vbbis = $this->getBis();
if( intval($this->getVertragsbestandteil_id()) > 0 )
{
$vb = $this->loadPersitedVB($this->getVertragsbestandteil_id());
$vbvon = $vb->getVon();
$vbbis = $vb->getBis();
}
if( ($bf->datum_von === $vbvon) && ($bf->datum_bis === $vbbis) )
{
return true;
}
return false;
}
protected function isBefore($a, $b)
{
if($a === null) {
return false;
}
elseif($b === null) {
return true;
}
else {
return $a < $b;
}
}
protected function isAfter($a, $b)
{
if($b === null) {
return false;
}
elseif($a === null) {
return true;
}
else {
return $a > $b;
}
}
protected function beforePersitExisting()
{
$bf = $this->loadBenutzerfunktion($this->getBenutzerfunktion_id());
if( $this->areVbAndBfInSync($bf) )
{
// vb or stored vb von bis is in sync so update benutzerfunktion
$this->updateBenutzerfunktion($bf, $this->getVon(), $this->getBis());
}
else
{
$daybeforevon = \DateTime::createFromFormat('Y-m-d', $this->getVon(),
new \DateTimeZone('Europe/Vienna'));
$daybeforevon->sub(new \DateInterval('P1D'));
if( $this->isBefore($bf->datum_von, $this->getVon()) &&
$this->isBefore($bf->datum_von, $this->getBis()) )
{
$data = (object) array(
'mitarbeiter_uid' => $bf->uid,
'funktion' => $bf->funktion_kurzbz,
'orget' => $bf->oe_kurzbz
);
$this->createBenutzerfunktionData($data);
$bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert());
$this->setBenutzerfunktion_id($bfid);
}
elseif( $this->isBefore($bf->datum_von, $this->getVon()) &&
$this->isAfter($this->getBis(), $bf->datum_von) )
{
$this->updateBenutzerfunktion($bf, $bf->datum_von, $daybeforevon->format('Y-m-d'));
$data = (object) array(
'mitarbeiter_uid' => $bf->uid,
'funktion' => $bf->funktion_kurzbz,
'orget' => $bf->oe_kurzbz
);
$this->createBenutzerfunktionData($data);
$bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert());
$this->setBenutzerfunktion_id($bfid);
}
else
{
$this->updateBenutzerfunktion($bf, $this->getVon(), $this->getBis());
}
}
}
protected function updateBenutzerfunktion($bf, $von, $bis)
{
$data = array();
if($von !== $bf->datum_von)
{
$data['datum_von'] = $von;
}
if($bis !== $bf->datum_bis)
{
$data['datum_bis'] = $bis;
}
if( count($data) === 0 )
{
return;
}
$data['updateamum'] = strftime('%Y-%m-%d %H:%M:%S');
$data['updatevon'] = getAuthUID();
$ret = $this->CI->BenutzerfunktionModel->update($bf->benutzerfunktion_id, $data);
if(isError($ret) )
{
throw new Exception('failed to update Benutzerfunktion');
}
}
protected function insertBenutzerfunktion($benutzerfunktiondata)
{
$ret = $this->CI->BenutzerfunktionModel->insert($benutzerfunktiondata);
if(isError($ret) )
{
throw new Exception('failed to create Benutzerfunktion');
}
return getData($ret);
}
protected function deleteBenutzerfunktion($benutzerfunktion_id)
{
$ret = $this->CI->BenutzerfunktionModel->delete($benutzerfunktion_id);
if(isError($ret) )
{
throw new Exception('failed to delete Benutzerfunktion');
}
}
protected function beforePersitNew() {
if( $this->benutzerfunktiondata === null)
{
return;
}
$bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert());
$this->setBenutzerfunktion_id($bfid);
}
public function afterDelete()
{
if( !(intval($this->getBenutzerfunktion_id()) > 0) )
{
return;
}
$this->deleteBenutzerfunktion($this->getBenutzerfunktion_id());
}
public function toStdClass()
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'benutzerfunktion_id' => $this->getBenutzerfunktion_id()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
benutzerfunktion_id: {$this->getBenutzerfunktion_id()}
EOTXT;
return parent::__toString() . $txt;
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->benutzerfunktionid) && $this->setBenutzerfunktion_id($data->benutzerfunktionid);
isset($data->benutzerfunktion_id) && $this->setBenutzerfunktion_id($data->benutzerfunktion_id);
isset($data->funktion) && isset($data->orget)
&& isset($data->mitarbeiter_uid) && $this->createBenutzerfunktionData($data);
isset($data->funktion_bezeichnung) && isset($data->oe_bezeichnung)
&& $this->createBenutzerfunktionData4Display($data);
$this->fromdb = false;
}
public function getBenutzerfunktion_id()
{
return $this->benutzerfunktion_id;
}
public function setBenutzerfunktion_id($benutzerfunktion_id)
{
$this->markDirty('benutzerfunktion_id', $this->benutzerfunktion_id, $benutzerfunktion_id);
$this->benutzerfunktion_id = $benutzerfunktion_id;
return $this;
}
protected function getBenutzerfunktionData4Insert()
{
if( null === $this->benutzerfunktiondata ) {
return null;
}
$benutzerfunktiondata = (object) array(
'funktion_kurzbz' => $this->benutzerfunktiondata->funktion_kurzbz,
'oe_kurzbz' => $this->benutzerfunktiondata->oe_kurzbz,
'uid' => $this->benutzerfunktiondata->uid,
'datum_von' => $this->getVon(),
'datum_bis' => $this->getBis(),
'insertamum' => strftime('%Y-%m-%d %H:%M:%S'),
'insertvon' => getAuthUID()
);
return $benutzerfunktiondata;
}
protected function createBenutzerfunktionData($data)
{
if( empty($data->funktion) || empty($data->orget) )
{
return;
}
$this->benutzerfunktiondata = (object) array(
'funktion_kurzbz' => $data->funktion,
'oe_kurzbz' => $data->orget,
'uid' => $data->mitarbeiter_uid
);
}
protected function createBenutzerfunktionData4Display($data)
{
if( empty($data->funktion_bezeichnung) || empty($data->oe_bezeichnung) )
{
return;
}
$this->benutzerfunktiondata = (object) array(
'funktion_kurzbz' => $data->funktion_kurzbz,
'funktion_bezeichnung' => $data->funktion_bezeichnung,
'oe_kurzbz' => $data->oe_kurzbz,
'oe_bezeichnung' => $data->oe_bezeichnung,
'oe_kurzbz_sap' => $data->oe_kurzbz_sap,
'oe_typ_kurzbz' => $data->oe_typ_kurzbz,
'oe_typ_bezeichnung' => $data->oe_typ_bezeichnung,
'uid' => $data->mitarbeiter_uid
);
}
public function validate()
{
if( (intval($this->benutzerfunktion_id) < 1)
&& ($this->benutzerfunktiondata === NULL) ) {
$this->validationerrors[] = 'Eine bestehende Funktion oder eine '
. 'Funktion und eine Organisationseinheit müssen ausgewählt sein.';
}
// TODO check if Benutzerfunktion is assigned to another vb
if( intval($this->benutzerfunktion_id) > 0 )
{
if ( $this->CI->VertragsbestandteilFunktionModel
->isBenutzerfunktionAlreadyAttachedToAnotherVB(
$this->benutzerfunktion_id,
$this->getVertragsbestandteil_id()) )
{
$this->validationerrors[] = 'Die Benutzerfunktion ist bereits '
. 'mit einem anderen Vertragsbestandteil verknüpft und kann '
. 'nicht mehrfach verknüft werden.';
}
}
return parent::validate();
}
}
@@ -0,0 +1,141 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
class VertragsbestandteilKarenz extends Vertragsbestandteil
{
protected $karenztyp_kurzbz;
protected $tatsaechlicher_geburtstermin;
protected $geplanter_geburtstermin;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_KARENZ);
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->karenztyp_kurzbz) && $this->setKarenztypKurzbz($data->karenztyp_kurzbz);
isset($data->geplanter_geburtstermin) && $this->setGeplanterGeburtstermin($data->geplanter_geburtstermin);
isset($data->tatsaechlicher_geburtstermin) && $this->setTatsaechlicherGeburtstermin($data->tatsaechlicher_geburtstermin);
$this->fromdb = false;
}
/**
* Get the value of karenztyp_kurzbz
*/
public function getKarenztypKurzbz()
{
return $this->karenztyp_kurzbz;
}
/**
* Set the value of karenztyp_kurzbz
*/
public function setKarenztypKurzbz($karenztyp_kurzbz): self
{
$this->markDirty('karenztyp_kurzbz', $this->karenztyp_kurzbz, $karenztyp_kurzbz);
$this->karenztyp_kurzbz = $karenztyp_kurzbz;
return $this;
}
/**
* Get the value of tatsaechlicher_geburtstermin
*/
public function getTatsaechlicherGeburtstermin()
{
return $this->tatsaechlicher_geburtstermin;
}
/**
* Set the value of tatsaechlicher_geburtstermin
*/
public function setTatsaechlicherGeburtstermin($tatsaechlicher_geburtstermin): self
{
$this->markDirty('tatsaechlicher_geburtstermin', $this->tatsaechlicher_geburtstermin, $tatsaechlicher_geburtstermin);
$this->tatsaechlicher_geburtstermin = $tatsaechlicher_geburtstermin;
return $this;
}
/**
* Get the value of geplanter_geburtstermin
*/
public function getGeplanterGeburtstermin()
{
return $this->geplanter_geburtstermin;
}
/**
* Set the value of geplanter_geburtstermin
*/
public function setGeplanterGeburtstermin($geplanter_geburtstermin): self
{
$this->markDirty('geplanter_geburtstermin', $this->geplanter_geburtstermin, $geplanter_geburtstermin);
$this->geplanter_geburtstermin = $geplanter_geburtstermin;
return $this;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'karenztyp_kurzbz' => $this->getKarenztypKurzbz(),
'tatsaechlicher_geburtstermin' => $this->getTatsaechlicherGeburtstermin(),
'geplanter_geburtstermin' => $this->getGeplanterGeburtstermin()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
karenztyp_kurzbz: {$this->getKarenztypKurzbz()}
tatsaechlicher_geburtstermin: {$this->getTatsaechlicherGeburtstermin()}
geplanter_geburtstermin: {$this->getGeplanterGeburtstermin()}
EOTXT;
return parent::__toString() . $txt;
}
public function validate()
{
if( empty($this->karenztyp_kurzbz) ) {
$this->validationerrors[] = 'Ein Karenztyp muss ausgewählt sein.';
}
if( $this->karenztyp_kurzbz === 'elternkarenz' ) {
$geplant = \DateTimeImmutable::createFromFormat('Y-m-d', $this->geplanter_geburtstermin);
$tatsaechlich = \DateTimeImmutable::createFromFormat('Y-m-d', $this->tatsaechlicher_geburtstermin);
if( false === $geplant ) {
$this->validationerrors[] = 'Bei Elternkarenz muss der geplanter Geburtstermin ein gültiges Datum sein.';
}
if( !empty($this->tatsaechlicher_geburtstermin) && $tatsaechlich === false ) {
$this->validationerrors[] = 'Bei Elternkarenz muss der tatsaechliche Geburtstermin leer oder ein gültiges Datum sein.';
}
}
$bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
if( false === $bis ) {
$this->validationerrors[] = 'Bei einer Karenz muss ein gültiges Ende-Datum angegeben werden.';
}
return parent::validate();
}
}
@@ -0,0 +1,117 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
class VertragsbestandteilKuendigungsfrist extends Vertragsbestandteil
{
protected $arbeitgeber_frist;
protected $arbeitnehmer_frist;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST);
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->arbeitgeber_frist) && $this->setArbeitgeberFrist($data->arbeitgeber_frist);
isset($data->arbeitnehmer_frist) && $this->setArbeitnehmerFrist($data->arbeitnehmer_frist);
$this->fromdb = false;
}
/**
* Get the value of arbeitgeber_frist
*/
public function getArbeitgeberFrist()
{
return $this->arbeitgeber_frist;
}
/**
* Set the value of arbeitgeber_frist
*/
public function setArbeitgeberFrist($arbeitgeber_frist): self
{
$this->markDirty('arbeitgeber_frist', $this->arbeitgeber_frist, $arbeitgeber_frist);
$this->arbeitgeber_frist = $arbeitgeber_frist;
return $this;
}
/**
* Get the value of arbeitnehmer_frist
*/
public function getArbeitnehmerFrist()
{
return $this->arbeitnehmer_frist;
}
/**
* Set the value of arbeitnehmer_frist
*/
public function setArbeitnehmerFrist($arbeitnehmer_frist): self
{
$this->markDirty('arbeitnehmer_frist', $this->arbeitnehmer_frist, $arbeitnehmer_frist);
$this->arbeitnehmer_frist = $arbeitnehmer_frist;
return $this;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'arbeitgeber_frist' => $this->getArbeitgeberFrist(),
'arbeitnehmer_frist' => $this->getArbeitnehmerFrist()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
arbeitgeber_frist: {$this->getArbeitgeberFrist()}
arbeitnehmer_frist: {$this->getArbeitnehmerFrist()}
EOTXT;
return parent::__toString() . $txt;
}
public function validate()
{
if( !(filter_var($this->arbeitgeber_frist, FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 0,
'max_range' => 52
)
)
)) ) {
$this->validationerrors[] = 'Arbeitgeberfrist muss eine Wochenanzahl im Bereich 1 bis 52 sein.';
}
if( !(filter_var($this->arbeitnehmer_frist, FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 1,
'max_range' => 52
)
)
)) ) {
$this->validationerrors[] = 'Arbeitnehmerfrist muss eine Wochenanzahl im Bereich 1 bis 52 sein.';
}
return parent::validate();
}
}
@@ -0,0 +1,512 @@
<?php
require_once __DIR__ . '/IValidation.php';
require_once __DIR__ . '/AbstractBestandteil.php';
require_once __DIR__ . '/Dienstverhaeltnis.php';
require_once __DIR__ . '/Vertragsbestandteil.php';
require_once __DIR__ . '/VertragsbestandteilStunden.php';
require_once __DIR__ . '/VertragsbestandteilFunktion.php';
require_once __DIR__ . '/VertragsbestandteilZeitaufzeichnung.php';
require_once __DIR__ . '/VertragsbestandteilKuendigungsfrist.php';
require_once __DIR__ . '/VertragsbestandteilUrlaubsanspruch.php';
require_once __DIR__ . '/VertragsbestandteilFreitext.php';
require_once __DIR__ . '/VertragsbestandteilKarenz.php';
require_once __DIR__ . '/VertragsbestandteilFactory.php';
require_once __DIR__ . '/OverlapChecker.php';
use vertragsbestandteil\Dienstverhaeltnis;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
/**
* Description of VertragsbestandteilLib
*
* @author bambi
*/
class VertragsbestandteilLib
{
const INCLUDE_FUTURE = true;
const DO_NOT_INCLUDE_FUTURE = false;
protected $CI;
/** @var Dienstverhaeltnis_model */
protected $DienstverhaeltnisModel;
/** @var Vertragsbestandteil_model */
protected $VertragsbestandteilModel;
/** @var Benutzer_model */
protected $BenutzerModel;
/**
* @var GehaltsbestandteilLib
*/
protected $GehaltsbestandteilLib;
protected $loggedInUser;
public function __construct()
{
$this->loggedInUser = getAuthUID();
$this->CI = get_instance();
$this->CI->load->model('vertragsbestandteil/Dienstverhaeltnis_model',
'DienstverhaeltnisModel');
$this->DienstverhaeltnisModel = $this->CI->DienstverhaeltnisModel;
$this->CI->load->model('vertragsbestandteil/Vertragsbestandteil_model',
'VertragsbestandteilModel');
$this->VertragsbestandteilModel = $this->CI->VertragsbestandteilModel;
$this->CI->load->model('person/benutzer_model',
'BenutzerModel');
$this->BenutzerModel = $this->CI->BenutzerModel;
$this->CI->load->library('vertragsbestandteil/GehaltsbestandteilLib',
null, 'GehaltsbestandteilLib');
$this->GehaltsbestandteilLib = $this->CI->GehaltsbestandteilLib;
}
public function handleGUIData($guidata, $employeeUID, $userUID)
{
$guiHandler = new GUIHandler($employeeUID, $userUID);
$ret = false;
try {
$ret = $guiHandler->handle($guidata, $employeeUID, $userUID);
} catch (Exception $ex)
{
log_message('debug', "Error handling json data from GUI. " . $ex->getMessage());
}
return $ret;
}
public function fetchDienstverhaeltnisse($unternehmen, $stichtag=null, $mitarbeiteruid=null) {
$dvs = $this->DienstverhaeltnisModel->fetchDienstverhaeltnisse($unternehmen, $stichtag, $mitarbeiteruid);
return $dvs;
}
public function fetchDienstverhaeltnis($dienstverhaeltnis_id)
{
$result = $this->DienstverhaeltnisModel->load($dienstverhaeltnis_id);
$dv = null;
if(null !== ($row = getData($result)))
{
$dv = new Dienstverhaeltnis();
$dv->hydrateByStdClass($row[0], true);
}
return $dv;
}
public function fetchVertragsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false)
{
$vbs = $this->VertragsbestandteilModel->getVertragsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture);
$gbs = $this->GehaltsbestandteilLib->fetchGehaltsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture);
$gbsByVBid = array();
foreach( $gbs as $gb )
{
if( intval($gb->getVertragsbestandteil_id()) > 0 )
{
if( !isset($gbsByVBid[$gb->getVertragsbestandteil_id()])
|| !is_array($gbsByVBid[$gb->getVertragsbestandteil_id()]) ) {
$gbsByVBid[$gb->getVertragsbestandteil_id()] = array();
}
$gbsByVBid[$gb->getVertragsbestandteil_id()][] = $gb;
}
}
foreach ($vbs as $vb)
{
if( isset($gbsByVBid[$vb->getVertragsbestandteil_id()]) )
{
$vb->setGehaltsbestandteile($gbsByVBid[$vb->getVertragsbestandteil_id()]);
}
}
return $vbs;
}
public function fetchVertragsbestandteil($vertragsbestandteil_id)
{
return $this->VertragsbestandteilModel->getVertragsbestandteil($vertragsbestandteil_id);
}
public function storeDienstverhaeltnis(Dienstverhaeltnis $dv)
{
if( intval($dv->getDienstverhaeltnis_id()) > 0 )
{
$this->updateDienstverhaeltnis($dv);
}
else
{
$this->insertDienstverhaeltnis($dv);
}
}
public function storeVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
{
$this->CI->db->trans_begin();
try
{
$this->setUIDtoPGSQL();
if( intval($vertragsbestandteil->getVertragsbestandteil_id()) > 0 )
{
$this->updateVertragsbestandteil($vertragsbestandteil);
}
else
{
$this->insertVertragsbestandteil($vertragsbestandteil);
}
if( $this->CI->db->trans_status() === false )
{
log_message('debug', "Transaction failed");
throw new Exception("Transaction failed");
}
$this->CI->db->trans_commit();
}
catch (Exception $ex)
{
log_message('debug', "Transaction rolled back. " . $ex->getMessage());
$this->CI->db->trans_rollback();
throw new Exception('Storing Vertragsbestandteil failed.');
}
}
public function deleteDienstverhaeltnis(Dienstverhaeltnis $dv)
{
$this->CI->db->trans_begin();
try
{
$this->setUIDtoPGSQL();
if( intval($dv->getDienstverhaeltnis_id()) > 0 )
{
$vbs = $this->fetchVertragsbestandteile($dv->getDienstverhaeltnis_id());
foreach ($vbs as $vb)
{
$this->deleteVertragsbestandteil($vb);
}
$ret = $this->DienstverhaeltnisModel->delete($dv->getDienstverhaeltnis_id());
if(isError($ret) )
{
log_message('debug', "Delete DV failed");
throw new Exception('error deleting dienstverhaeltnis '
. $dv->getDienstverhaeltnis_id());
}
if( $this->CI->db->trans_status() === false )
{
log_message('debug', "Transaction failed");
throw new Exception("Transaction failed");
}
$this->CI->db->trans_commit();
}
}
catch (Exception $ex)
{
log_message('debug', "Transaction rolled back. " . $ex->getMessage());
$this->CI->db->trans_rollback();
return $ex->getMessage();
}
return true;
}
public function deleteVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
{
$this->CI->db->trans_begin();
try
{
$this->setUIDtoPGSQL();
if( intval($vertragsbestandteil->getVertragsbestandteil_id()) > 0 )
{
$this->deleteVertragsbestandteilHelper($vertragsbestandteil);
}
if( $this->CI->db->trans_status() === false )
{
log_message('debug', "Transaction failed");
throw new Exception("Transaction failed");
}
$this->CI->db->trans_commit();
}
catch (Exception $ex)
{
log_message('debug', "Transaction rolled back. " . $ex->getMessage());
$this->CI->db->trans_rollback();
throw new Exception('Delete Vertragsbestandteil failed.');
}
}
protected function insertDienstverhaeltnis(Dienstverhaeltnis $dv)
{
$dv->setInsertvon($this->loggedInUser)
->setInsertamum(strftime('%Y-%m-%d %H:%M:%S'));
$ret = $this->DienstverhaeltnisModel->insert($dv->toStdClass());
if( hasData($ret) )
{
$dv->setDienstverhaeltnis_id(getData($ret));
}
else
{
throw new Exception('error inserting dienstverhaeltnis');
}
}
protected function insertVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
{
$vertragsbestandteil->setInsertvon($this->loggedInUser)
->setInsertamum(strftime('%Y-%m-%d %H:%M:%S'));
$vertragsbestandteil->beforePersist();
$ret = $this->VertragsbestandteilModel->insert($vertragsbestandteil->baseToStdClass());
if( hasData($ret) )
{
$vertragsbestandteil->setVertragsbestandteil_id(getData($ret));
}
else
{
throw new Exception('error inserting vertragsbestandteil');
}
$specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel(
$vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
$retspecial = $specialisedModel->insert($vertragsbestandteil->toStdClass());
if(isError($retspecial) )
{
throw new Exception('error updating vertragsbestandteil '
. $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
}
try
{
$gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile();
$this->GehaltsbestandteilLib->storeGehaltsbestandteile($gehaltsbestandteile);
}
catch(Exception $ex)
{
throw new Exception('VertragsbestandteilLib insertVertragsbestandteil '
. 'failed to store Gehaltsbestandteile. ' . $ex->getMessage());
}
}
protected function updateDienstverhaeltnis(Dienstverhaeltnis $dv)
{
if(!$dv->isDirty()) {
return;
}
$dv->setUpdatevon($this->loggedInUser)
->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S'));
$ret = $this->DienstverhaeltnisModel->update($dv->getDienstverhaeltnis_id(),
$dv->toStdClass());
if(isError($ret) )
{
throw new Exception('error updating dienstverhaeltnis');
}
}
private function deleteVertragsbestandteilHelper(Vertragsbestandteil $vertragsbestandteil)
{
$specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel(
$vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
$retspecial = $specialisedModel->delete($vertragsbestandteil->getVertragsbestandteil_id());
if(isError($retspecial) )
{
throw new Exception('error deleting vertragsbestandteil '
. $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
}
try
{
$gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile();
$this->GehaltsbestandteilLib->deleteGehaltsbestandteile($gehaltsbestandteile);
}
catch(Exception $ex)
{
throw new Exception('VertragsbestandteilLib deleteVertragsbestandteil '
. 'failed to delete Gehaltsbestandteile. ' . $ex->getMessage());
}
$ret = $this->VertragsbestandteilModel->delete($vertragsbestandteil->getVertragsbestandteil_id());
if(isError($ret) )
{
throw new Exception('error deleting vertragsbestandteil');
}
$vertragsbestandteil->afterDelete();
}
protected function updateVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
{
if($vertragsbestandteil->isDirty()) {
$vertragsbestandteil->setUpdatevon($this->loggedInUser)
->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S'));
$vertragsbestandteil->beforePersist();
$basedata = $vertragsbestandteil->baseToStdClass();
if( count((array) $basedata) > 0 )
{
$ret = $this->VertragsbestandteilModel->update(
$vertragsbestandteil->getVertragsbestandteil_id(),
$basedata);
if(isError($ret) )
{
throw new Exception('error updating vertragsbestandteil');
}
}
$specialisedData = $vertragsbestandteil->toStdClass();
if( count((array) $specialisedData) > 0 )
{
$specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel(
$vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
$retspecial = $specialisedModel->update(
$vertragsbestandteil->getVertragsbestandteil_id(),
$specialisedData);
if(isError($retspecial) )
{
throw new Exception('error updating vertragsbestandteil '
. $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
}
}
}
try
{
$gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile();
$this->GehaltsbestandteilLib->storeGehaltsbestandteile($gehaltsbestandteile);
}
catch(Exception $ex)
{
throw new Exception('VertragsbestandteilLib updateVertragsbestandteil '
. 'failed to store Gehaltsbestandteile. ' . $ex->getMessage());
}
}
public function isOverlappingExistingDV(Dienstverhaeltnis $dv)
{
return $this->DienstverhaeltnisModel->isOverlappingExistingDV(
$dv->getMitarbeiter_uid(),
$dv->getOe_kurzbz(),
$dv->getVon(),
$dv->getBis(),
$dv->getDienstverhaeltnis_id()
);
}
protected function hasOtherActiveDV(Dienstverhaeltnis $dv, $duedate)
{
$hasotheractivedv = false;
$result = $this->DienstverhaeltnisModel->getDVByPersonUID($dv->getMitarbeiter_uid(), null, $duedate);
$dvs = getData($result);
foreach ($dvs as $tmpdv)
{
if(intval($tmpdv->dienstverhaeltnis_id) !== intval($dv->getDienstverhaeltnis_id()))
{
$hasotheractivedv = true;
break;
}
}
return $hasotheractivedv;
}
/**
* like endDienstverhaeltnis, but also sets aktiv flag to false
*/
public function deactivateDienstverhaeltnis(Dienstverhaeltnis $dv, $enddate, $deactivate)
{
$result = $this->endDienstverhaeltnis($dv, $enddate);
if ( $result === true)
{
if (!$deactivate) return $result;
if(!$this->hasOtherActiveDV($dv, $enddate))
{
$result = $this->BenutzerModel->update(
array('uid' => $dv->getMitarbeiter_uid()),
array(
'aktiv' => false,
'updateaktivam' => date('Y-m-d'),
'updateaktivvon' => $this->loggedInUser
)
);
}
}
return $result;
}
public function endDienstverhaeltnis(Dienstverhaeltnis $dv, $enddate, $dvendegrund_kurzbz=null, $dvendegrund_anmerkung=null)
{
if( $dv->getBis() !== null && $dv->getBis() < $enddate )
{
return 'Dienstverhältnis ist bereits beendet.';
}
$this->CI->db->trans_begin();
try
{
$this->setUIDtoPGSQL();
if( intval($dv->getDienstverhaeltnis_id()) > 0 )
{
$gbs = $this->GehaltsbestandteilLib->fetchGehaltsbestandteile($dv->getDienstverhaeltnis_id());
foreach ($gbs as $gb)
{
$this->GehaltsbestandteilLib->endGehaltsbestandteil($gb, $enddate);
}
$vbs = $this->fetchVertragsbestandteile($dv->getDienstverhaeltnis_id());
foreach ($vbs as $vb)
{
$this->endVertragsbestandteil($vb, $enddate);
}
if( $dvendegrund_kurzbz !== null )
{
$dv->setDvendegrund_kurzbz($dvendegrund_kurzbz);
}
if( $dvendegrund_anmerkung !== null )
{
$dv->setDvendegrund_anmerkung($dvendegrund_anmerkung);
}
$dv->setBis($enddate);
$this->updateDienstverhaeltnis($dv);
if( $this->CI->db->trans_status() === false )
{
log_message('debug', "Transaction failed");
throw new Exception("Transaction failed");
}
$this->CI->db->trans_commit();
}
}
catch (Exception $ex)
{
log_message('debug', "end DV failed " . $dv->getDienstverhaeltnis_id());
log_message('debug', "Transaction rolled back. " . $ex->getMessage());
$this->CI->db->trans_rollback();
return $ex->getMessage();
}
return true;
}
public function endVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil, $enddate)
{
if( $vertragsbestandteil->getBis() !== null && $vertragsbestandteil->getBis() < $enddate )
{
return;
}
$vertragsbestandteil->setBis($enddate);
$this->updateVertragsbestandteil($vertragsbestandteil);
}
protected function setUIDtoPGSQL() {
$ret = $this->VertragsbestandteilModel
->execReadOnlyQuery('SET LOCAL pv21.uid TO \''
. $this->loggedInUser . '\'');
if(isError($ret))
{
throw new Exception('error setting uid to pgsql');
}
}
}
@@ -0,0 +1,110 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
/**
* Description of VertragsbestandteilStunden
*
* @author bambi
*/
class VertragsbestandteilStunden extends Vertragsbestandteil
{
protected $wochenstunden;
protected $teilzeittyp_kurzbz;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_STUNDEN);
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->wochenstunden) && $this->setWochenstunden($data->wochenstunden);
isset($data->teilzeittyp_kurzbz) && $this->setTeilzeittyp_kurzbz($data->teilzeittyp_kurzbz);
$this->fromdb = false;
}
public function getWochenstunden()
{
return $this->wochenstunden;
}
public function getTeilzeittyp_kurzbz()
{
return $this->teilzeittyp_kurzbz;
}
public function setWochenstunden($wochenstunden)
{
$this->markDirty('wochenstunden', $this->wochenstunden, $wochenstunden);
$this->wochenstunden = $wochenstunden;
return $this;
}
public function setTeilzeittyp_kurzbz($teilzeittyp_kurzbz)
{
$teilzeittyp_kurzbz = ($teilzeittyp_kurzbz !== '')
? $teilzeittyp_kurzbz : null;
$this->markDirty('teilzeittyp_kurzbz', $this->teilzeittyp_kurzbz, $teilzeittyp_kurzbz);
$this->teilzeittyp_kurzbz = $teilzeittyp_kurzbz;
return $this;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'wochenstunden' => $this->getWochenstunden(),
'teilzeittyp_kurzbz' => $this->getTeilzeittyp_kurzbz()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
wochenstunden: {$this->getWochenstunden()}
teilzeittyp_kurzbz: {$this->getTeilzeittyp_kurzbz()}
EOTXT;
return parent::__toString() . $txt;
}
public function validate()
{
if( false === filter_var($this->wochenstunden, FILTER_VALIDATE_FLOAT,
array(
'options' => array(
'min_range' => 0,
'max_range' => 100
)
)
) ) {
$this->validationerrors[] = 'Stunden muss eine Kommazahl im Bereich 0 bis 100 sein.';
}
else
{
if( floatval($this->wochenstunden) < floatval('0.01') &&
$this->teilzeittyp_kurzbz !== 'altersteilzeit' )
{
$this->validationerrors[] = '0 Wochenstunden ist nur in Kombination mit Altersteilzeit zulässig.';
}
}
return parent::validate();
}
}
@@ -0,0 +1,83 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
class VertragsbestandteilUrlaubsanspruch extends Vertragsbestandteil
{
protected $tage;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH);
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->tage) && $this->setTage($data->tage);
$this->fromdb = false;
}
/**
* Get the value of tage
*/
public function getTage()
{
return $this->tage;
}
/**
* Set the value of tage
*/
public function setTage($tage): self
{
$this->markDirty('tage', $this->tage, $tage);
$this->tage = $tage;
return $this;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'tage' => $this->getTage(),
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
tage: {$this->getTage()}
EOTXT;
return parent::__toString() . $txt;
}
public function validate()
{
if( !(filter_var($this->tage, FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 1,
'max_range' => 50
)
)
)) ) {
$this->validationerrors[] = 'Urlaubsanspruch muss eine Tagesanzahl im Bereich 1 bis 50 sein.';
}
return parent::validate();
}
}
@@ -0,0 +1,118 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
class VertragsbestandteilZeitaufzeichnung extends Vertragsbestandteil
{
protected $zeitaufzeichnung;
protected $azgrelevant;
protected $homeoffice;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG);
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->zeitaufzeichnung) && $this->setZeitaufzeichnung($data->zeitaufzeichnung);
isset($data->azgrelevant) && $this->setAzgrelevant($data->azgrelevant);
isset($data->homeoffice) && $this->setHomeoffice($data->homeoffice);
$this->fromdb = false;
}
/**
* Get the value of zeitaufzeichnung
*/
public function getZeitaufzeichnung()
{
return $this->zeitaufzeichnung;
}
/**
* Set the value of zeitaufzeichnung
*/
public function setZeitaufzeichnung($zeitaufzeichnung): self
{
$this->markDirty('zeitaufzeichnung', $this->zeitaufzeichnung, $zeitaufzeichnung);
$this->zeitaufzeichnung = $zeitaufzeichnung;
return $this;
}
/**
* Get the value of azgrelevant
*/
public function getAzgrelevant()
{
return $this->azgrelevant;
}
/**
* Set the value of azgrelevant
*/
public function setAzgrelevant($azgrelevant): self
{
$this->markDirty('azgrelevant', $this->azgrelevant, $azgrelevant);
$this->azgrelevant = $azgrelevant;
return $this;
}
/**
* Get the value of homeoffice
*/
public function getHomeoffice()
{
return $this->homeoffice;
}
/**
* Set the value of homeoffice
*/
public function setHomeoffice($homeoffice): self
{
$this->markDirty('homeoffice', $this->homeoffice, $homeoffice);
$this->homeoffice = $homeoffice;
return $this;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'zeitaufzeichnung' => $this->getZeitaufzeichnung(),
'azgrelevant' => $this->getAzgrelevant(),
'homeoffice' => $this->getHomeoffice()
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
zeitaufzeichnung: {$this->getZeitaufzeichnung()}
azgrelevant: {$this->getAzgrelevant()}
homeoffice: {$this->getHomeoffice()}
EOTXT;
return parent::__toString() . $txt;
}
public function validate()
{
return parent::validate();
}
}
@@ -0,0 +1,35 @@
<?php
class Bismeldestichtag_model extends DB_Model
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dbTable = 'bis.tbl_bismeldestichtag';
$this->pk = 'meldestichtag_id';
}
/**
* Gets last Bismeldestichtag for a Studiensemester.
* @param $studiensemester_kurzbz
* @return object success or error
*/
public function getByStudiensemester($studiensemester_kurzbz)
{
$query = '
SELECT
meldestichtag
FROM
bis.tbl_bismeldestichtag
JOIN public.tbl_studiensemester USING (studiensemester_kurzbz)
WHERE
studiensemester_kurzbz = ?
ORDER BY meldestichtag DESC
LIMIT 1';
return $this->execQuery($query, array($studiensemester_kurzbz));
}
}
@@ -238,7 +238,7 @@ class Prestudentstatus_model extends DB_Model
{
$this->addSelect('tbl_prestudentstatus.*,
tbl_studienplan.bezeichnung AS studienplan_bezeichnung,
tbl_studienplan.orgform_kurzbz AS orgform,
tbl_orgform.orgform_kurzbz AS orgform,
tbl_studienplan.sprache,
tbl_orgform.bezeichnung_mehrsprachig AS bezeichnung_orgform,
tbl_status.bezeichnung_mehrsprachig,
@@ -250,7 +250,7 @@ class Prestudentstatus_model extends DB_Model
$this->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT');
$this->addJoin('public.tbl_status', 'tbl_status.status_kurzbz = tbl_prestudentstatus.status_kurzbz');
$this->addJoin('public.tbl_status_grund', 'statusgrund_id', 'LEFT');
$this->addJoin('bis.tbl_orgform', 'tbl_studienplan.orgform_kurzbz = tbl_orgform.orgform_kurzbz', 'LEFT');
$this->addJoin('bis.tbl_orgform', 'COALESCE(tbl_studienplan.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz, tbl_studiengang.orgform_kurzbz) = tbl_orgform.orgform_kurzbz', 'LEFT');
$this->db->where('tbl_status.status_kurzbz = tbl_prestudentstatus.status_kurzbz');
$where = array('prestudent_id' => $prestudent_id);
@@ -267,7 +267,7 @@ class Prestudentstatus_model extends DB_Model
return $this->loadWhere($where);
}
public function loadLastWithStgDetails($prestudent_id, $studiensemester_kurzbz = null)
public function loadLastWithStgDetails($prestudent_id, $studiensemester_kurzbz = null, $max_date = null)
{
$this->load->config('studierendenantrag');
@@ -295,7 +295,8 @@ class Prestudentstatus_model extends DB_Model
$this->addJoin('public.tbl_studiensemester ss', 'studiensemester_kurzbz');
$this->addJoin('public.tbl_person pers', 'person_id');
$this->addJoin('public.tbl_studiengang g', 'p.studiengang_kz=g.studiengang_kz');
$this->addJoin('bis.tbl_orgform o', 'g.orgform_kurzbz=o.orgform_kurzbz');
$this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
$this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz');
$this->addOrder($this->dbTable . '.datum', 'DESC');
$this->addOrder($this->dbTable . '.insertamum', 'DESC');
@@ -303,7 +304,8 @@ class Prestudentstatus_model extends DB_Model
$this->addLimit(1);
$this->db->where_in($this->dbTable . '.status_kurzbz', $this->config->item('antrag_prestudentstatus_whitelist'));
if ($max_date)
$this->db->where($this->dbTable . '.insertamum <', $max_date);
$whereArr = [
$this->dbTable . '.prestudent_id' => $prestudent_id,
@@ -322,7 +322,7 @@ class Reihungstest_model extends DB_Model
JOIN lehre.tbl_studienplan ON (tbl_prestudentstatus.studienplan_id = tbl_studienplan.studienplan_id)
LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code)
WHERE rt_id = ?
AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\'
AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\')
AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz
AND bewerbung_abgeschicktamum IS NOT NULL
AND bestaetigtam IS NOT NULL
@@ -411,7 +411,7 @@ class Reihungstest_model extends DB_Model
JOIN lehre.tbl_studienplan ON (tbl_prestudentstatus.studienplan_id = tbl_studienplan.studienplan_id)
LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code)
WHERE rt.studiengang_kz = ?
AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\'
AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\')
AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz
AND bewerbung_abgeschicktamum IS NOT NULL
AND bestaetigtam IS NOT NULL
@@ -462,7 +462,7 @@ class Reihungstest_model extends DB_Model
LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code)
LEFT JOIN PUBLIC.tbl_ort ON (tbl_rt_person.ort_kurzbz = tbl_ort.ort_kurzbz)
WHERE rt_id = ?
AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\'
AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\')
AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz
AND bewerbung_abgeschicktamum IS NOT NULL
AND bestaetigtam IS NOT NULL
@@ -20,7 +20,7 @@ class Rueckstellung_model extends DB_Model
$this->addLimit(1);
$this->addJoin('tbl_rueckstellung_status', 'status_kurzbz');
$this->addSelect('*,
array_to_json(bezeichnung_mehrsprachig::varchar[])->>'.$language_index . 'as bezeichnung');
array_to_json(bezeichnung_mehrsprachig::varchar[])->>'.$language_index . ' as bezeichnung');
$this->addOrder('datum_bis', 'DESC');
$where['person_id'] = $person_id;
+1 -1
View File
@@ -84,7 +84,7 @@ class Student_model extends DB_Model
}
/**
* Get the FH-Email for a student (not the private kontakt emailt)
* Get the FH-Email for a student (not the private kontakt email)
* @param $student_uid
* @return string
*/
@@ -39,6 +39,7 @@ class Pruefung_model extends DB_Model
/**
* NOTE(chris): not used
* @return string
*/
protected function loadWhereThreeExamsFailed()
@@ -86,8 +87,16 @@ class Pruefung_model extends DB_Model
$this->addJoin('public.tbl_person pers', 'person_id');
$this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
$this->addJoin('public.tbl_studiengang g', 'ps.studiengang_kz=g.studiengang_kz');
$this->addJoin('bis.tbl_orgform o', 'g.orgform_kurzbz=o.orgform_kurzbz');
$this->db->join('campus.tbl_studierendenantrag a', 'ps.prestudent_id=a.prestudent_id and a.typ = ?', 'LEFT', false);
$this->addJoin(
'public.tbl_prestudentstatus pss',
'pss.prestudent_id=ps.prestudent_id
AND pss.studiensemester_kurzbz=le.studiensemester_kurzbz
AND pss.status_kurzbz=get_rolle_prestudent(ps.prestudent_id, le.studiensemester_kurzbz)',
'LEFT'
);
$this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
$this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz');
$this->db->join('campus.tbl_studierendenantrag a', 'ps.prestudent_id=a.prestudent_id and a.typ = ?', 'LEFT', false);
$this->db->where("n.positiv", false);
/* $this->db->where_in("p.pruefungstyp_kurzbz1", ['kommPruef','zusKommPruef']);*/
@@ -122,6 +131,8 @@ class Pruefung_model extends DB_Model
*/
public function loadWhereCommitteeExamsFailed()
{
$this->load->config('studierendenantrag');
$this->dbTable = 'lehre.tbl_pruefung p';
$this->addSelect('p.datum');
@@ -129,8 +140,13 @@ class Pruefung_model extends DB_Model
$this->addJoin('lehre.tbl_note n', 'note');
$this->db->where("n.positiv", false);
$note_blacklist = $this->config->item('note_blacklist_wiederholung');
if ($note_blacklist)
$this->db->where_not_in("n.note", $note_blacklist);
$this->db->where_in("p.pruefungstyp_kurzbz", ['kommPruef','zusKommPruef']);
$this->addOrder('p.datum', 'DESC');
return $this->load();
}
@@ -154,8 +170,10 @@ class Pruefung_model extends DB_Model
$this->addSelect('ps.prestudent_id');
$this->addSelect('lv.bezeichnung as lvbezeichnung');
$this->addSelect('le.studiensemester_kurzbz');
$this->addSelect('a.studierendenantrag_id');
$this->addSelect('a.typ');
$this->addSelect('campus.get_status_studierendenantrag(a.studierendenantrag_id) status');
$this->addSelect('pss.ausbildungssemester');
$this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id');
$this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
@@ -164,10 +182,20 @@ class Pruefung_model extends DB_Model
$this->addJoin('public.tbl_person pers', 'person_id');
$this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
$this->addJoin('public.tbl_studiengang g', 'ps.studiengang_kz=g.studiengang_kz');
$this->addJoin('bis.tbl_orgform o', 'g.orgform_kurzbz=o.orgform_kurzbz');
$this->addJoin('campus.tbl_studierendenantrag a', 'ps.prestudent_id=a.prestudent_id and a.typ=' . $this->escape(Studierendenantrag_model::TYP_WIEDERHOLUNG), 'LEFT');
$this->db->where_in("get_rolle_prestudent(ps.prestudent_id, null)", $this->config->item('antrag_prestudentstatus_whitelist'));
$this->addJoin(
'public.tbl_prestudentstatus pss',
'pss.prestudent_id=ps.prestudent_id
AND pss.studiensemester_kurzbz=le.studiensemester_kurzbz
AND pss.status_kurzbz=get_rolle_prestudent(ps.prestudent_id, le.studiensemester_kurzbz)',
'LEFT'
);
$this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
$this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz');
$this->addJoin(
'campus.tbl_studierendenantrag a',
'ps.prestudent_id=a.prestudent_id and a.typ=' . $this->escape(Studierendenantrag_model::TYP_WIEDERHOLUNG),
'LEFT'
);
$this->db->where("g.aktiv", true);
@@ -191,12 +219,19 @@ class Pruefung_model extends DB_Model
*
* @return stdClass
*/
public function loadWhereCommitteeExamFailedForPrestudent($prestudent_id)
public function loadWhereCommitteeExamFailedForPrestudent($prestudent_id, $max_date = null, $studiensemester_kurzbz = null)
{
$this->withDetailsForStudierendenAntrag();
$this->db->where('ps.prestudent_id', $prestudent_id);
if ($max_date !== null) {
$this->db->where('p.datum <=', $max_date);
}
if ($studiensemester_kurzbz !== null) {
$this->db->where('le.studiensemester_kurzbz', $studiensemester_kurzbz);
}
return $this->loadWhereCommitteeExamsFailed();
}
@@ -212,12 +247,14 @@ class Pruefung_model extends DB_Model
$this->withDetailsForStudierendenAntrag();
if ($maxDate)
$this->db->where("p.datum < ", $maxDate->format('c'));
$this->db->where("p.datum <= ", $maxDate->format('Y-m-d'));
if ($minDate)
$this->db->where("p.datum > ", $minDate->format('c'));
$this->db->where("p.datum > ", $minDate->format('Y-m-d'));
$this->db->where("b.aktiv", true);
$this->db->where_in("get_rolle_prestudent(ps.prestudent_id, null)", $this->config->item('antrag_prestudentstatus_whitelist'));
if (is_array($status)) {
if (in_array(null, $status)) {
$status = array_filter($status);
@@ -26,25 +26,28 @@ class Studierendenantrag_model extends DB_Model
return $this->loadForStudiengaenge($studiengaenge, $typ, $this->StudierendenantragstatusModel::STATUS_CREATED);
}
public function loadForStudiengaenge($studiengaenge, $typ = null, $status = null)
public function loadForStudiengaenge($studiengaenge, $typ = null, $status = null, $sql = null)
{
$sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
if ($sql == null)
$sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
$this->addSelect('stg.bezeichnung');
$this->addSelect('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung AS bezeichnung');
$this->addSelect('bezeichnung_mehrsprachig[(' . $sql . ')] AS orgform', false);
$this->addSelect('s.studierendenantrag_id');
$this->addSelect('matrikelnr');
$this->addSelect('studienjahr_kurzbz');
$this->addSelect('vorname');
$this->addSelect('nachname');
$this->addSelect('prestudent_id');
$this->addSelect('p.prestudent_id');
$this->addSelect('p.studiengang_kz');
$this->addSelect('semester');
$this->addSelect($this->dbTable . '.grund');
$this->addSelect('datum');
$this->addSelect($this->dbTable . '.datum');
$this->addSelect('datum_wiedereinstieg');
$this->addSelect($this->dbTable . '.typ');
$this->addSelect('st.studierendenantrag_statustyp_kurzbz as status');
$this->addSelect('s.insertvon as status_insertvon');
$this->addSelect('s.insertamum as status_insertamum');
$this->addSelect('dms_id');
$this->addSelect('st.bezeichnung[(' . $sql . ')] as statustyp');
@@ -52,8 +55,16 @@ class Studierendenantrag_model extends DB_Model
$this->addJoin('public.tbl_student', 'prestudent_id');
$this->addJoin('public.tbl_person', 'person_id');
$this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz');
$this->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$this->addJoin('bis.tbl_orgform', 'orgform_kurzbz');
$this->addJoin('public.tbl_studiensemester ss', 'studiensemester_kurzbz');
$this->addJoin(
'public.tbl_prestudentstatus ps',
'ps.prestudent_id=p.prestudent_id
AND ps.studiensemester_kurzbz=ss.studiensemester_kurzbz
AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, ss.studiensemester_kurzbz)',
'LEFT'
);
$this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
$this->addJoin('bis.tbl_orgform of', 'of.orgform_kurzbz=COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, stg.orgform_kurzbz)');
$this->addJoin(
'campus.tbl_studierendenantrag_status as s',
'campus.get_status_id_studierendenantrag('. $this->dbTable .'.studierendenantrag_id) = studierendenantrag_status_id'
@@ -71,6 +82,47 @@ class Studierendenantrag_model extends DB_Model
return $this->loadWhere($where);
}
public function loadActiveForStudiengaenge($studiengaenge)
{
// NOTE(chris): get language before changing things in the global
// db object because getUserLanguage() might use it and it should
// not have been tampered with
$sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
$this->db->group_start();
$this->db->where_not_in('s.studierendenantrag_statustyp_kurzbz', [
Studierendenantragstatus_model::STATUS_CANCELLED,
Studierendenantragstatus_model::STATUS_APPROVED,
Studierendenantragstatus_model::STATUS_REJECTED,
Studierendenantragstatus_model::STATUS_OBJECTION_DENIED,
Studierendenantragstatus_model::STATUS_DEREGISTERED,
Studierendenantragstatus_model::STATUS_PAUSE
]);
$this->db->or_group_start();
$this->db->where('s.studierendenantrag_statustyp_kurzbz', Studierendenantragstatus_model::STATUS_APPROVED);
$this->db->where('tbl_studierendenantrag.typ', Studierendenantrag_model::TYP_ABMELDUNG_STGL);
$this->db->group_end();
$this->db->group_end();
return $this->loadForStudiengaenge($studiengaenge, null, null, $sql);
}
public function loadStgsWithAntraege($studiengaenge)
{
$this->addDistinct();
$this->addSelect('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung AS bezeichnung');
$this->addSelect('p.studiengang_kz');
$this->addJoin('public.tbl_prestudent p', 'prestudent_id');
$this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz');
$this->addOrder('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung');
$this->db->where_in('p.studiengang_kz', $studiengaenge);
return $this->load();
}
public function isInStudiengang($studierendenantrag_id, $studiengaenge)
{
$this->addJoin('public.tbl_prestudent', 'prestudent_id');
@@ -92,12 +144,18 @@ class Studierendenantrag_model extends DB_Model
$lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage());
$this->addSelect('*');
$this->addSelect('campus.get_status_studierendenantrag(studierendenantrag_id) status');
$this->addSelect($this->dbTable . '.grund AS grund');
$this->addSelect('s.studierendenantrag_statustyp_kurzbz status');
$this->addSelect('s.insertvon status_insertvon');
$this->addSelect('t.bezeichnung[(' . $lang . ')] statustyp');
$this->addJoin(
'campus.tbl_studierendenantrag_status s',
'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id'
);
$this->addJoin(
'campus.tbl_studierendenantrag_statustyp t',
'campus.get_status_studierendenantrag(studierendenantrag_id)=t.studierendenantrag_statustyp_kurzbz'
's.studierendenantrag_statustyp_kurzbz=t.studierendenantrag_statustyp_kurzbz'
);
if ($types && is_array($types)) {
@@ -120,14 +178,22 @@ class Studierendenantrag_model extends DB_Model
public function getStgAndSem($antrag_id)
{
$this->addSelect('p.studiengang_kz');
$this->addSelect('stg.bezeichnung');
$this->addSelect('s.ausbildungssemester');
$this->addSelect('s.orgform_kurzbz');
$this->addSelect('plan.sprache');
$this->addSelect('COALESCE(plan.orgform_kurzbz, s.orgform_kurzbz, stg.orgform_kurzbz) AS orgform_kurzbz');
$this->addJoin(
'public.tbl_prestudentstatus s',
$this->dbTable . '.prestudent_id=s.prestudent_id AND ' . $this->dbTable . '.studiensemester_kurzbz=s.studiensemester_kurzbz'
$this->dbTable . '.prestudent_id=s.prestudent_id
AND ' .
$this->dbTable . '.studiensemester_kurzbz=s.studiensemester_kurzbz
AND ' .
$this->dbTable . '.insertamum > s.insertamum'
);
$this->addJoin('public.tbl_prestudent p', $this->dbTable . '.prestudent_id=p.prestudent_id');
$this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
$this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
$this->addOrder('s.datum', 'DESC');
$this->addOrder('s.insertamum', 'DESC');
@@ -135,8 +201,6 @@ class Studierendenantrag_model extends DB_Model
$this->addLimit(1);
$this->db->where_in('s.status_kurzbz', $this->config->item('antrag_prestudentstatus_whitelist'));
return $this->loadWhere([
$this->pk => $antrag_id
]);
@@ -188,18 +252,45 @@ class Studierendenantrag_model extends DB_Model
$this->addSelect($this->dbTable . '.datum_wiedereinstieg');
$this->addSelect($this->dbTable . '.grund');
$this->addSelect($this->dbTable . '.dms_id');
$this->addSelect("(SELECT count(1) FROM campus.tbl_studierendenantrag_status WHERE studierendenantrag_id = " . $this->dbTable . ".studierendenantrag_id AND studierendenantrag_statustyp_kurzbz = 'Genehmigt') AS isapproved", false);
$this->addSelect('s.insertvon AS status_insertvon');
$this->addSelect(
"(SELECT count(1) FROM campus.tbl_studierendenantrag_status WHERE studierendenantrag_id = " .
$this->dbTable .
".studierendenantrag_id AND studierendenantrag_statustyp_kurzbz = 'Genehmigt') AS isapproved",
false
);
$this->addJoin('public.tbl_prestudent p', 'prestudent_id', 'RIGHT');
$this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz');
$this->addJoin('bis.tbl_orgform', 'orgform_kurzbz');
$this->addJoin(
'public.tbl_prestudentstatus ps',
'ps.prestudent_id=p.prestudent_id AND ps.studiensemester_kurzbz=' .
$this->dbTable .
'.studiensemester_kurzbz AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, ' .
$this->dbTable .
'.studiensemester_kurzbz)',
'LEFT'
);
$this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
$this->addJoin('bis.tbl_orgform of', 'of.orgform_kurzbz=COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, stg.orgform_kurzbz)');
$this->addJoin(
'campus.tbl_studierendenantrag_status s',
'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id',
'LEFT'
);
$this->addJoin(
'campus.tbl_studierendenantrag_statustyp st',
'campus.get_status_studierendenantrag(studierendenantrag_id)=st.studierendenantrag_statustyp_kurzbz',
's.studierendenantrag_statustyp_kurzbz=st.studierendenantrag_statustyp_kurzbz',
'LEFT'
);
$this->db->where("(SELECT status_kurzbz FROM public.tbl_prestudentstatus WHERE prestudent_id=p.prestudent_id AND status_kurzbz='Student' LIMIT 1) IS NOT NULL", null, false);
$this->db->where("(
SELECT status_kurzbz
FROM public.tbl_prestudentstatus
WHERE prestudent_id=p.prestudent_id
AND status_kurzbz='Student'
LIMIT 1
) IS NOT NULL", null, false);
return $this->loadWhere([
@@ -240,4 +331,144 @@ class Studierendenantrag_model extends DB_Model
return $this->loadWhere($where);
}
/**
* Checks if the Prestudent has an active Unterbrechung between
* the start of the given semester and the given enddate.
* If the enddate is omitted the end of the given semester is used.
*
* @param integer $prestudent_id
* @param string $studiensemester_kurzbz
* @param string $enddate (optional)
*
* @return boolean
*/
public function hasRunningUnterbrechungBetween($prestudent_id, $studiensemester, $enddate = null)
{
$start = '(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=' . $this->db->escape($studiensemester) . ')';
$end = $enddate
? $this->db->escape($enddate)
: '(SELECT ende FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=' . $this->db->escape($studiensemester) . ')';
$this->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$this->db->where([
'prestudent_id' => $prestudent_id,
'typ' => Studierendenantrag_model::TYP_UNTERBRECHUNG,
'campus.get_status_studierendenantrag(studierendenantrag_id) !=' => Studierendenantragstatus_model::STATUS_CANCELLED,
'start < ' . $end => null,
'datum_wiedereinstieg > ' . $start => null,
]);
return (boolean)$this->db->count_all_results($this->dbTable);
}
/**
* Gets free semester slots for a new Unterbrechung.
*
* @param integer $prestudent_id
* @param string $studiensemester_kurzbz (optional)
*
* @return stdClass
*/
public function getFreeSlotsForUnterbrechung($prestudent_id, $studiensemester = null)
{
$max_starters = 2;
$max_length = max(
2,
(integer)$this->config->item('unterbrecher_semester_max_length')
);
$subquery = '';
if ($studiensemester)
$subquery = 'SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=?';
else
$subquery = 'SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=public.get_stdsem_prestudent (?, null)';
$sql = "WITH numbered_sems AS (
SELECT
a.studienjahr_kurzbz AS studienjahr_kurzbz,
a.studiensemester_kurzbz AS von,
b.studiensemester_kurzbz AS bis,
a.start AS start,
b.start AS ende,
ROW_NUMBER() OVER (
PARTITION BY a.studiensemester_kurzbz
ORDER BY b.start
) AS row_number
FROM public.tbl_studiensemester a
LEFT JOIN public.tbl_studiensemester b ON (b.start > a.ende)
),
last_sems AS (
SELECT *
FROM numbered_sems
WHERE numbered_sems.row_number <= ?
)
SELECT s.von, s.bis, s.start, s.ende, studierendenantrag_id, studienjahr_kurzbz
FROM last_sems s
LEFT JOIN (
SELECT studierendenantrag_id, start, datum_wiedereinstieg AS ende
FROM campus.tbl_studierendenantrag
LEFT JOIN public.tbl_studiensemester USING(studiensemester_kurzbz)
WHERE typ=?
AND campus.get_status_studierendenantrag(studierendenantrag_id) != ?
AND prestudent_id=?
) a ON (s.start < a.ende AND s.ende > a.start)
WHERE s.start >= (" . $subquery . ")
ORDER BY s.start, s.ende
LIMIT ?;";
return $this->execQuery($sql, [
$max_length,
self::TYP_UNTERBRECHUNG,
Studierendenantragstatus_model::STATUS_CANCELLED,
$prestudent_id,
$studiensemester ?: $prestudent_id,
$max_length * $max_starters
]);
}
/**
* Returns if an Antrag is manually paused
*
* @param integer $antrag_id
*
* @return boolean
*/
public function isManuallyPaused($antrag_id)
{
$this->addJoin(
'campus.tbl_studierendenantrag_status s',
'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id'
);
$this->db->where([
's.studierendenantrag_id' => $antrag_id,
's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE
]);
$this->db->group_start();
$this->db->where_not_in('s.insertvon', [
Studierendenantragstatus_model::INSERTVON_DEREGISTERED,
Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL
]);
$this->db->or_group_start();
$this->db->where('s.insertvon', Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL);
$this->db->where('1 !=', '(
SELECT COUNT(*)%2
FROM campus.tbl_studierendenantrag_status i
WHERE i.studierendenantrag_id = s.studierendenantrag_id
AND i.insertamum > (
SELECT ii.insertamum
FROM campus.tbl_studierendenantrag_status ii
WHERE ii.studierendenantrag_id = s.studierendenantrag_id
AND ii.insertvon <> ' . $this->escape(Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL) . '
ORDER BY ii.insertamum DESC
LIMIT 1
)
)', false);
$this->db->group_end();
$this->db->group_end();
return hasData($this->load());
}
}
@@ -65,20 +65,40 @@ class Studierendenantraglehrveranstaltung_model extends DB_Model
'stat.studierendenantrag_status_id = campus.get_status_id_studierendenantrag(a.studierendenantrag_id)'
);
$this->addJoin('public.tbl_student s', 'prestudent_id');
$this->addJoin(
'lehre.tbl_zeugnisnote z',
'z.lehrveranstaltung_id=lv.lehrveranstaltung_id AND z.student_uid=s.student_uid AND z.studiensemester_kurzbz=a.studiensemester_kurzbz',
'LEFT'
);
// NOTE(chris): last offizell note
$this->addJoin('(
SELECT z.*
FROM lehre.tbl_zeugnisnote z
LEFT JOIN public.tbl_studiensemester zs
USING(studiensemester_kurzbz)
JOIN (
SELECT zi.lehrveranstaltung_id, zi.student_uid, MAX(zis.start) AS start
FROM lehre.tbl_zeugnisnote zi
LEFT JOIN lehre.tbl_note zin
USING(note)
LEFT JOIN public.tbl_studiensemester zis
USING(studiensemester_kurzbz)
WHERE zin.aktiv AND zin.offiziell
GROUP BY zi.lehrveranstaltung_id, zi.student_uid
) zx
ON (
z.lehrveranstaltung_id=zx.lehrveranstaltung_id
AND z.student_uid=zx.student_uid
AND zs.start = zx.start
)) z', 'z.lehrveranstaltung_id=lv.lehrveranstaltung_id AND z.student_uid=s.student_uid', 'LEFT');
$this->addJoin('lehre.tbl_note zn', 'z.note = zn.note', 'LEFT');
$this->load->config('studierendenantrag');
$note_intern_angerechntet = $this->config->item('wiederholung_note_angerechnet');
return $this->loadWhere([
'ps.prestudent_id' => $prestudent_id,
'a.typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
'stat.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED,
'n.note <> ' => 0,
$this->dbTable . '.studiensemester_kurzbz' => $studiensemester_kurzbz,
'(n.note<>19 OR (z.note IS NOT NULL AND zn.positiv))' => null
'(n.note<>' . $this->db->escape($note_intern_angerechntet) . ' OR (z.note IS NOT NULL AND zn.positiv))' => null
]);
}
}
@@ -14,6 +14,11 @@ class Studierendenantragstatus_model extends DB_Model
const STATUS_REQUESTSENT_2 = 'ZweiteAufforderungVersandt';
const STATUS_OBJECTED = 'Beeinsprucht';
const STATUS_OBJECTION_DENIED = 'EinspruchAbgelehnt';
const STATUS_DEREGISTERED = 'Abgemeldet';
const STATUS_PAUSE = 'Pause';
const INSERTVON_ABMELDUNGSTGL = "AbmeldungStgl";
const INSERTVON_DEREGISTERED = "Studienabbruch";
/**
* Constructor
@@ -48,4 +53,157 @@ class Studierendenantragstatus_model extends DB_Model
return $this->loadWhere($where);
}
public function stopAntraegeForAbmeldungStgl($antrag_id)
{
$sql = 'INSERT INTO campus.tbl_studierendenantrag_status
(studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum)
SELECT studierendenantrag_id, ?, ?, (
SELECT insertamum
FROM campus.tbl_studierendenantrag_status
WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?)
)
FROM campus.tbl_studierendenantrag
WHERE prestudent_id = (
SELECT prestudent_id
FROM campus.tbl_studierendenantrag
WHERE studierendenantrag_id = ?
)
AND studierendenantrag_id <> ?
AND (
(
typ = ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ?
) OR (
typ = ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ?
) OR (
typ = ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ?
)
)';
return $this->execQuery($sql, [
self::STATUS_PAUSE,
self::INSERTVON_ABMELDUNGSTGL,
$antrag_id,
$antrag_id,
$antrag_id,
Studierendenantrag_model::TYP_ABMELDUNG,
[
Studierendenantragstatus_model::STATUS_CREATED
],
Studierendenantrag_model::TYP_UNTERBRECHUNG,
[
Studierendenantragstatus_model::STATUS_CREATED
],
Studierendenantrag_model::TYP_WIEDERHOLUNG,
[
Studierendenantragstatus_model::STATUS_REQUESTSENT_1,
Studierendenantragstatus_model::STATUS_REQUESTSENT_2,
Studierendenantragstatus_model::STATUS_CREATED,
Studierendenantragstatus_model::STATUS_LVSASSIGNED,
Studierendenantragstatus_model::STATUS_PAUSE
],
]);
}
public function resumeAntraegeForAbmeldungStgl($antrag_id)
{
$sql = 'INSERT INTO campus.tbl_studierendenantrag_status
(studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum)
SELECT studierendenantrag_id, (
SELECT studierendenantrag_statustyp_kurzbz
FROM campus.tbl_studierendenantrag_status s
WHERE s.studierendenantrag_id=a.studierendenantrag_id
AND campus.get_status_id_studierendenantrag(a.studierendenantrag_id) <> studierendenantrag_status_id
ORDER BY insertamum DESC
LIMIT 1
), ?, (
SELECT insertamum
FROM campus.tbl_studierendenantrag_status
WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?)
)
FROM campus.tbl_studierendenantrag a
WHERE prestudent_id = (
SELECT prestudent_id
FROM campus.tbl_studierendenantrag
WHERE studierendenantrag_id = ?
)
AND typ <> ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) = ?
';
return $this->execQuery($sql, [
self::INSERTVON_ABMELDUNGSTGL,
$antrag_id,
$antrag_id,
Studierendenantrag_model::TYP_ABMELDUNG_STGL,
Studierendenantragstatus_model::STATUS_PAUSE
]);
}
public function stopAntraegeForAbbruchBy($antrag_id)
{
$sql = 'INSERT INTO campus.tbl_studierendenantrag_status
(studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum)
SELECT studierendenantrag_id, ?, ?, (
SELECT insertamum
FROM campus.tbl_studierendenantrag_status
WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?)
)
FROM campus.tbl_studierendenantrag
WHERE prestudent_id = (
SELECT prestudent_id
FROM campus.tbl_studierendenantrag
WHERE studierendenantrag_id = ?
)
AND studierendenantrag_id <> ?
AND (
(
typ = ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
) OR (
typ = ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
) OR (
typ = ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
) OR (
typ = ?
AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
)
)';
return $this->execQuery($sql, [
self::STATUS_PAUSE,
self::INSERTVON_DEREGISTERED,
$antrag_id,
$antrag_id,
$antrag_id,
Studierendenantrag_model::TYP_ABMELDUNG,
[
Studierendenantragstatus_model::STATUS_APPROVED,
Studierendenantragstatus_model::STATUS_CANCELLED
],
Studierendenantrag_model::TYP_UNTERBRECHUNG,
[
Studierendenantragstatus_model::STATUS_APPROVED,
Studierendenantragstatus_model::STATUS_CANCELLED,
Studierendenantragstatus_model::STATUS_REMINDERSENT,
Studierendenantragstatus_model::STATUS_REJECTED
],
Studierendenantrag_model::TYP_ABMELDUNG_STGL,
[
Studierendenantragstatus_model::STATUS_CANCELLED,
Studierendenantragstatus_model::STATUS_DEREGISTERED,
Studierendenantragstatus_model::STATUS_OBJECTION_DENIED
],
Studierendenantrag_model::TYP_WIEDERHOLUNG,
[
Studierendenantragstatus_model::STATUS_DEREGISTERED,
Studierendenantragstatus_model::STATUS_APPROVED
],
]);
}
}
@@ -188,4 +188,20 @@ class Organisationseinheit_model extends DB_Model
}
return $this->loadWhere($condition);
}
/**
* Get OEs by eventQuery string. Use with autocomplete event queries.
* @param $eventQuery String
* @return array
*/
public function getAutocompleteSuggestions($eventQuery)
{
$this->addSelect('oe_kurzbz');
$this->addSelect('organisationseinheittyp_kurzbz, oe_kurzbz, bezeichnung, aktiv, lehre');
$this->addOrder('organisationseinheittyp_kurzbz, bezeichnung');
return $this->loadWhere("
oe_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%'
");
}
}
@@ -525,20 +525,6 @@ class Studiengang_model extends DB_Model
return $this->execQuery($query, $params);
}
public function loadWithOrgform($studiengang_kzs)
{
$sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
$this->addSelect($this->dbTable . '.*');
$this->addSelect('o.bezeichnung_mehrsprachig[(' . $sql . ')] AS orgform');
$this->addJoin('bis.tbl_orgform o', 'orgform_kurzbz');
$this->db->where_in($this->dbTable . '.studiengang_kz', $studiengang_kzs);
return $this->load();
}
/**
* @param array $studiengang_kzs
* @param array $not_antrag_typ (optional) If the prestudent has an antrag with one of the specified types it will be excluded from the result
@@ -571,12 +557,13 @@ class Studiengang_model extends DB_Model
AND ps.ausbildungssemester=get_absem_prestudent(p.prestudent_id, NULL)
AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, NULL)'
);
$this->addJoin('bis.tbl_orgform o', $this->dbTable . '.orgform_kurzbz=o.orgform_kurzbz');
$this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id');
$this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz)=o.orgform_kurzbz');
$this->addJoin('public.tbl_person pers', 'person_id');
$this->addJoin('public.tbl_student stud', 'p.prestudent_id=stud.prestudent_id', 'LEFT');
$this->db->where_in($this->dbTable . '.studiengang_kz', $studiengang_kzs);
$this->db->where_in('ps.status_kurzbz', $this->config->item('antrag_prestudentstatus_whitelist'));
$this->db->where_in('ps.status_kurzbz', $this->config->item('antrag_prestudentstatus_whitelist_abmeldung'));
$this->db->where($this->dbTable . ".aktiv", true);
if ($not_antrag_typ !== null && is_array($not_antrag_typ)) {
@@ -60,7 +60,7 @@ class Studienplan_model extends DB_Model
));
}
public function getStudienplanLehrveranstaltungForPrestudent($studienplan_id, $semester, $prestudent_id, $note_stsem)
public function getStudienplanLehrveranstaltungForPrestudent($studienplan_id, $semester, $prestudent_id)
{
$lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage());
$sql = 'SELECT student_uid FROM public.tbl_student WHERE prestudent_id=' . $this->escape($prestudent_id);
@@ -75,11 +75,27 @@ class Studienplan_model extends DB_Model
$this->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'studienplan_id');
$this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
$this->addJoin(
'lehre.tbl_zeugnisnote zn',
'zn.lehrveranstaltung_id=lv.lehrveranstaltung_id AND zn.student_uid=(' . $sql . ') AND zn.studiensemester_kurzbz=' . $this->escape($note_stsem),
'LEFT'
);
// NOTE(chris): last offizell note
$this->addJoin('(
SELECT z.*
FROM lehre.tbl_zeugnisnote z
LEFT JOIN public.tbl_studiensemester zs
USING(studiensemester_kurzbz)
JOIN (
SELECT zi.lehrveranstaltung_id, zi.student_uid, MAX(zis.start) AS start
FROM lehre.tbl_zeugnisnote zi
LEFT JOIN lehre.tbl_note zin
USING(note)
LEFT JOIN public.tbl_studiensemester zis
USING(studiensemester_kurzbz)
WHERE zin.aktiv AND zin.offiziell
GROUP BY zi.lehrveranstaltung_id, zi.student_uid
) zx
ON (
z.lehrveranstaltung_id=zx.lehrveranstaltung_id
AND z.student_uid=zx.student_uid
AND zs.start = zx.start
)) zn', 'zn.lehrveranstaltung_id=lv.lehrveranstaltung_id AND zn.student_uid=( ' . $sql . ')', 'LEFT');
$this->addJoin('lehre.tbl_note n', 'n.note=zn.note', 'LEFT');
$this->addOrder('lehre.tbl_studienplan_lehrveranstaltung.sort');
@@ -180,4 +180,60 @@ class Benutzerfunktion_model extends DB_Model
return $this->execQuery($query, $parameters_array);
}
public function insertBenutzerfunktion($Json)
{
unset($Json['benutzerfunktion_id']);
unset($Json['updateamum']);
$Json['insertvon'] = getAuthUID();
$Json['insertamum'] = $this->escape('NOW()');
if ($Json['datum_bis']=='')
{
unset($Json['datum_bis']);
}
$result = $this->insert($Json);
if (isError($result))
{
return error($result->msg, EXIT_ERROR);
}
$record = $this->load($result->retval);
return $record;
}
function updateBenutzerfunktion($funktionJson)
{
$funktionJson['updatevon'] = getAuthUID();
$funktionJson['updateamum'] = $this->escape('NOW()');
$result = $this->update($funktionJson['benutzerfunktion_id'], $funktionJson);
if (isError($result))
{
return error($result->msg, EXIT_ERROR);
}
$result = $this->load($funktionJson['benutzerfunktion_id']);
return $result;
}
function deleteBenutzerfunktion($funktionJson)
{
$result = $this->delete($funktionJson);
if (isError($result))
{
return error($result->msg, EXIT_ERROR);
}
return success($funktionJson);
}
}
@@ -0,0 +1,15 @@
<?php
class Kennzeichen_model extends DB_Model
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dbTable = 'public.tbl_kennzeichen';
$this->pk = 'kennzeichen_id';
}
}
+30 -5
View File
@@ -1,5 +1,22 @@
<?php
/**
* Copyright (C) 2023 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/>.
*/
class Person_model extends DB_Model
{
/**
@@ -8,6 +25,7 @@ class Person_model extends DB_Model
public function __construct()
{
parent::__construct();
$this->dbTable = 'public.tbl_person';
$this->pk = 'person_id';
@@ -70,7 +88,7 @@ class Person_model extends DB_Model
if (isset($person['svnr']) && $person['svnr'] != '')
{
$this->PersonModel->addOrder('svnr', 'DESC');
$result = $this->PersonModel->loadWhere(array(
$result = $this->PersonModel->loadWhere(array(
'person_id != ' => $person['person_id'],
'SUBSTRING(svnr FROM 1 FOR 10) = ' => $person['svnr'])
);
@@ -138,7 +156,8 @@ class Person_model extends DB_Model
'lower(nachname) like '.$this->db->escape('%'.$filter.'%')."
OR lower(vorname) like ".$this->db->escape('%'.$filter.'%')."
OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.$filter.'%')."
OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%'));
OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%')
);
return $result;
}
@@ -152,8 +171,12 @@ class Person_model extends DB_Model
*/
public function getPersonStammdaten($person_id, $zustellung_only = false)
{
$this->addSelect('public.tbl_person.*, tbl_person.staatsbuergerschaft AS staatsbuergerschaft_code, tbl_person.geburtsnation AS geburtsnation_code,
s.kurztext as staatsbuergerschaft, g.kurztext as geburtsnation');
$this->addSelect('public.tbl_person.*,
tbl_person.staatsbuergerschaft AS staatsbuergerschaft_code,
tbl_person.geburtsnation AS geburtsnation_code,
s.kurztext as staatsbuergerschaft,
g.kurztext as geburtsnation'
);
$this->addJoin('bis.tbl_nation s', 'public.tbl_person.staatsbuergerschaft = s.nation_code', 'LEFT');
$this->addJoin('bis.tbl_nation g', 'public.tbl_person.geburtsnation = g.nation_code', 'LEFT');
@@ -258,7 +281,8 @@ class Person_model extends DB_Model
*/
public function getFullName($uid)
{
if (!$result = getData($this->getByUid($uid))[0])
$result = getData($this->getByUid($uid))[0];
if (!$result)
{
show_error('Failed loading person');
}
@@ -351,3 +375,4 @@ class Person_model extends DB_Model
]);
}
}
@@ -11,4 +11,24 @@ class Betriebsmittel_model extends DB_Model
$this->dbTable = 'wawi.tbl_betriebsmittel';
$this->pk = 'betriebsmittel_id';
}
/**
* load Liste Inventarnummern
*/
public function loadInventarliste($filter)
{
$filter = urldecode(strtoLower($filter));
$qry = "
SELECT
bm.inventarnummer, bm.betriebsmitteltyp, bm.betriebsmittel_id, CONCAT(bm.inventarnummer, ' ', bm.beschreibung) as dropdowntext
FROM
wawi.tbl_betriebsmittel bm
WHERE
upper(bm.inventarnummer) LIKE '%" .$this->db->escape_like_str($filter)."%'
OR
lower(bm.inventarnummer) LIKE '%" .$this->db->escape_like_str($filter)."%'";
return $this->execQuery($qry);
}
}
@@ -96,4 +96,49 @@ class Betriebsmittelperson_model extends DB_Model
return $this->loadWhere($condition);
}
public function getBetriebsmittelData($id, $type_id)
{
switch ($type_id) {
case 'person_id':
$cond = 'bmp.person_id';
break;
case 'uid':
$cond = 'bmp.uid';
break;
case 'betriebsmittelperson_id':
$cond = 'bmp.betriebsmittelperson_id';
break;
default:
return error("ID nicht gültig");
}
$query = "
SELECT
bm.nummer, bmp.person_id, bm.betriebsmitteltyp, bmp.anmerkung as anmerkung, bmp.retouram, TO_CHAR(bmp.retouram::timestamp, 'DD.MM.YYYY') AS format_retour, bmp.ausgegebenam, TO_CHAR(bmp.ausgegebenam::timestamp, 'DD.MM.YYYY') AS format_ausgabe, bm.beschreibung, bmp.uid, bmp.kaution, bm.betriebsmittel_id, bmp.betriebsmittelperson_id, bm.inventarnummer, bm.nummer2
FROM
wawi.tbl_betriebsmittelperson bmp
JOIN
wawi.tbl_betriebsmittel bm ON (bmp.betriebsmittel_id = bm.betriebsmittel_id)
WHERE
" . $cond . " = ? ";
return $this->execQuery($query, array($id));
}
/**
* Perform a loadWhere on the vw_betriebsmittelperson DB View
*
* @param array $where
*
* @return stdClass
*/
public function loadViewWhere($where)
{
$table = $this->dbTable;
$this->dbTable = 'public.vw_betriebsmittelperson';
$result = $this->loadWhere($where);
$this->dbTable = $table;
return $result;
}
}
@@ -144,10 +144,15 @@ class Mitarbeiter_model extends DB_Model
* Checks if alias exists
* @param $kurzbz
*/
public function kurzbzExists($kurzbz)
public function kurzbzExists($kurzbz, $uid=null)
{
$this->addSelect('1');
$result = $this->loadWhere(array('kurzbz' => $kurzbz));
$where = array('kurzbz' => $kurzbz);
if ($uid != null)
{
$where['mitarbeiter_uid<>'] = $uid;
}
$result = $this->loadWhere($where);
if (isSuccess($result))
{
@@ -171,7 +176,6 @@ class Mitarbeiter_model extends DB_Model
*/
public function generateKurzbz($uid)
{
$kurzbz = '';
$this->addLimit(1);
$this->addSelect('vorname, nachname');
$this->addJoin('public.tbl_benutzer', 'tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid');
@@ -181,25 +185,35 @@ class Mitarbeiter_model extends DB_Model
if (hasData($nameresult))
{
$kurzbzdata = getData($nameresult);
$nachname_clean = sanitizeProblemChars($kurzbzdata[0]->nachname);
$vorname_clean = sanitizeProblemChars($kurzbzdata[0]->vorname);
$genKurzbz = $this->generateKurzbzHelper($kurzbzdata[0]->vorname, $kurzbzdata[0]->nachname);
for ($nn = 6, $vn = 2; $nn != 0; $nn--, $vn++)
{
$kurzbz = mb_substr($nachname_clean, 0, $nn);
$kurzbz .= mb_substr($vorname_clean, 0, $vn);
return $genKurzbz;
}
return error('No Kurzbezeichnung could be generated');
}
$kurzbzexists = $this->kurzbzExists($kurzbz);
public function generateKurzbzHelper($vorname, $nachname)
{
$nachname_clean = sanitizeProblemChars($nachname);
$vorname_clean = sanitizeProblemChars($vorname);
$kurzbz = '';
if (hasData($kurzbzexists) && !getData($kurzbzexists)[0])
break;
}
for ($nn = 6, $vn = 2; $nn != 0; $nn--, $vn++)
{
$kurzbz = mb_substr($nachname_clean, 0, $nn);
$kurzbz .= mb_substr($vorname_clean, 0, $vn);
$kurzbzexists = $this->kurzbzExists($kurzbz);
if (hasData($kurzbzexists) && getData($kurzbzexists)[0])
return error('No Kurzbezeichnung could be generated');
if (hasData($kurzbzexists) && !getData($kurzbzexists)[0])
break;
}
$kurzbzexists = $this->kurzbzExists($kurzbz);
if (hasData($kurzbzexists) && getData($kurzbzexists)[0])
return error('No Kurzbezeichnung could be generated');
return success($kurzbz);
}
}
@@ -0,0 +1,17 @@
<?php
class Stundensatz_model extends DB_Model
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dbTable = 'hr.tbl_stundensatz';
$this->pk = 'stundensatz_id';
$this->hasSequence = true;
}
}
@@ -0,0 +1,16 @@
<?php
class Stundensatztyp_model extends DB_Model
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dbTable = 'hr.tbl_stundensatztyp';
$this->pk = 'stundensatztyp';
}
}
@@ -21,4 +21,26 @@ class Zeitaufzeichnung_model extends DB_Model
return $this->execQuery($qry);
}
public function getFullInterval($uid, $fromDate, $toDate)
{
$qry = <<<EOL
SELECT d.dates, z.*
FROM
(SELECT
*, to_char ((ende-start),'HH24:MI') as diff,
(SELECT (to_char(sum(ende-start),'DD')::integer)*24+to_char(sum(ende-start),'HH24')::integer || ':' || to_char(sum(ende-start),'MI')
FROM campus.tbl_zeitaufzeichnung
WHERE uid=? and start between ? AND ?) as summe
FROM campus.tbl_zeitaufzeichnung
WHERE uid=? AND (aktivitaet_kurzbz != 'DienstreiseMT' or aktivitaet_kurzbz is null) AND start between ? AND ?) as z
RIGHT JOIN (select generate_series ( ?::timestamp , ?::timestamp , '1 day'::interval) :: date as dates) d on date(z.ende) = d.dates
ORDER BY d.dates desc, z.start desc
EOL;
return $this->execQuery($qry, array($uid, $fromDate, $toDate, $uid, $fromDate, $toDate, $fromDate, $toDate));
}
}
+18 -1
View File
@@ -1,5 +1,22 @@
<?php
/**
* Copyright (C) 2023 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/>.
*/
class PersonLog_model extends DB_Model
{
/**
@@ -17,7 +34,7 @@ class PersonLog_model extends DB_Model
* @param array $data Data of Log Entry to save.
* @return success object if true
*/
public function insert($data)
public function insert($data, $encryptedColumns = null)
{
$result = $this->db->insert($this->dbTable, $data);
if ($result)
@@ -0,0 +1,249 @@
<?php
class Dienstverhaeltnis_model extends DB_Model
{
public function __construct()
{
parent::__construct();
$this->dbTable = 'hr.tbl_dienstverhaeltnis';
$this->pk = 'dienstverhaeltnis_id';
}
/**
* @return list of DV
*/
public function getDVByPersonUID($uid, $oe_kurzbz=null, $datum=null)
{
$result = null;
$qry = "
SELECT
dv.dienstverhaeltnis_id,
tbl_benutzer.uid,
tbl_mitarbeiter.personalnummer,
tbl_mitarbeiter.kurzbz,
tbl_mitarbeiter.lektor,
tbl_mitarbeiter.fixangestellt,
tbl_person.person_id,
tbl_benutzer.alias,
org.oe_kurzbz,
org.bezeichnung oe_bezeichnung,
dv.von,
dv.bis,
dv.dvendegrund_kurzbz,
dv.dvendegrund_anmerkung,
dv.vertragsart_kurzbz,
dv.updateamum,
dv.updatevon,
dv.dvendegrund_kurzbz,
dv.dvendegrund_anmerkung
FROM tbl_mitarbeiter
JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text
JOIN tbl_person USING (person_id)
JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text)
JOIN public.tbl_organisationseinheit org USING(oe_kurzbz)
WHERE tbl_benutzer.uid=?";
$data = array($uid);
if(!is_null($oe_kurzbz))
{
$qry.=" AND oe_kurzbz=?";
$data[] = $oe_kurzbz;
}
if (!is_null($datum))
{
$qry.=" AND ? BETWEEN dv.von AND COALESCE(dv.bis, '2999-12-31')";
$data[] = $datum;
}
$qry .="
ORDER BY dv.von desc
";
return $this->execQuery($qry, $data);
}
public function getDVByID($dvid) {
$this->addSelect('hr.tbl_dienstverhaeltnis.*, public.tbl_organisationseinheit.bezeichnung as unternehmen');
$this->addJoin('public.tbl_organisationseinheit', 'hr.tbl_dienstverhaeltnis.oe_kurzbz = public.tbl_organisationseinheit.oe_kurzbz');
$result = $this->load($dvid);
if (hasData($result)) {
return $result;
}
return error('could not fetch DV by ID');
}
public function getCurrentDVByPersonUID($uid, $dateAsUnixTS)
{
$date = DateTime::createFromFormat( 'U', $dateAsUnixTS );
$datestring = $date->format("Y-m-d");
$qry = "
SELECT
dv.dienstverhaeltnis_id,
tbl_benutzer.uid,
tbl_mitarbeiter.personalnummer,
tbl_mitarbeiter.kurzbz,
tbl_mitarbeiter.lektor,
tbl_mitarbeiter.fixangestellt,
tbl_person.person_id,
tbl_benutzer.alias,
dv.von,
dv.bis,
dv.vertragsart_kurzbz,
dv.updateamum,
dv.updatevon
FROM tbl_mitarbeiter
JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text
JOIN tbl_person USING (person_id)
JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text)
WHERE tbl_benutzer.uid=? and (dv.von<=? and (dv.bis is null OR dv.bis>=?))
ORDER BY dv.von desc
";
return $this->execQuery($qry, array($uid, $datestring, $datestring));
}
public function isOverlappingExistingDV($mitarbeiter_uid, $oe_kurzbz, $von, $bis, $dvid=null)
{
$params = array($mitarbeiter_uid, $oe_kurzbz, $von, $bis, $von, $bis);
$dvidclause = '';
if (intval($dvid) > 0)
{
$params = array_merge($params, array($dvid, $dvid));
$dvidclause = <<<EODVIDC
AND (
SELECT
COUNT(*) AS karenzen
FROM
hr.tbl_vertragsbestandteil vb
WHERE
vb.dienstverhaeltnis_id = ?
AND
vb.vertragsbestandteiltyp_kurzbz = 'karenz'
AND
dv.von::date >= COALESCE(vb.von, '1970-01-01'::date)
AND
COALESCE(dv.bis::date, '2170-12-31'::date) <= COALESCE(vb.bis, '2170-12-31')
) = 0
AND dv.dienstverhaeltnis_id != ?
EODVIDC;
}
$query = <<<EOSQL
SELECT
count(*) AS dvcount
FROM
hr.tbl_dienstverhaeltnis dv
WHERE
dv.mitarbeiter_uid = ?
AND
dv.oe_kurzbz = ?
AND
dv.vertragsart_kurzbz NOT IN ('werkvertrag', 'studentischehilfskr')
AND
?::date <= COALESCE(dv.bis, '2170-12-31'::date)
AND
COALESCE(?::date, '2170-12-31'::date) >= dv.von
AND (
SELECT
COUNT(*) AS karenzen
FROM
hr.tbl_vertragsbestandteil vb
WHERE
vb.dienstverhaeltnis_id = dv.dienstverhaeltnis_id
AND
vb.vertragsbestandteiltyp_kurzbz = 'karenz'
AND
?::date >= COALESCE(vb.von, '1970-01-01'::date)
AND
COALESCE(?::date, '2170-12-31'::date) <= COALESCE(vb.bis, '2170-12-31')
) = 0
{$dvidclause}
EOSQL;
$ret = $this->execReadOnlyQuery($query, $params);
if( ($dvcount = getData($ret)) && ($dvcount[0]->dvcount > 0) ) {
return true;
}
return false;
}
public function getDVByPersonUIDOverlapping($uid, $oe_kurzbz=null, $beginn=null, $ende=null)
{
$result = null;
$qry = "
SELECT
dv.dienstverhaeltnis_id,
tbl_benutzer.uid,
tbl_mitarbeiter.personalnummer,
tbl_mitarbeiter.kurzbz,
tbl_mitarbeiter.lektor,
tbl_mitarbeiter.fixangestellt,
tbl_person.person_id,
tbl_benutzer.alias,
org.oe_kurzbz,
org.bezeichnung oe_bezeichnung,
dv.von,
dv.bis,
dv.vertragsart_kurzbz,
dv.updateamum,
dv.updatevon
FROM tbl_mitarbeiter
JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text
JOIN tbl_person USING (person_id)
JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text)
JOIN public.tbl_organisationseinheit org USING(oe_kurzbz)
WHERE tbl_benutzer.uid=?";
$data = array($uid);
if(!is_null($oe_kurzbz))
{
$qry.=" AND oe_kurzbz=?";
$data[] = $oe_kurzbz;
}
if (!is_null($beginn) && !is_null($ende))
{
$qry.=" AND (?,?) OVERLAPS (dv.von, COALESCE(dv.bis, '2999-12-31'))";
$data[] = $beginn;
$data[] = $ende;
}
$qry .="
ORDER BY dv.von desc
";
return $this->execQuery($qry, $data);
}
public function fetchDienstverhaeltnisse($unternehmen, $stichtag=null, $mitarbeiteruid=null) {
$where = "oe_kurzbz = " . $this->escape($unternehmen);
if( !is_null($stichtag) )
{
$where .= " AND " . $this->escape($stichtag) . " BETWEEN COALESCE(von, '1970-01-01') AND COALESCE(bis, '2070-12-31')";
}
if( !is_null($mitarbeiteruid) )
{
$where .= " AND mitarbeiter_uid = " . $this->escape($mitarbeiteruid);
}
$res = $this->loadWhere($where);
$dvs = array();
if(hasData($res) )
{
$dvs = getData($res);
}
return $dvs;
}
}
@@ -0,0 +1,147 @@
<?php
require_once __DIR__ . '/IEncryption.php';
use vertragsbestandteil\Gehaltsbestandteil;
class Gehaltsbestandteil_model extends DB_Model implements IEncryption
{
public function __construct()
{
parent::__construct();
$this->dbTable = 'hr.tbl_gehaltsbestandteil';
$this->pk = 'gehaltsbestandteil_id';
}
public function getEncryptedColumns(): array
{
return array(
'grundbetrag' => array(
DB_Model::CRYPT_CAST => 'numeric',
DB_Model::CRYPT_PASSWORD_NAME => 'ENCRYPTIONKEYGEHALT'
),
'betrag_valorisiert' => array(
DB_Model::CRYPT_CAST => 'numeric',
DB_Model::CRYPT_PASSWORD_NAME => 'ENCRYPTIONKEYGEHALT'
)
);
}
public function getCurrentGBTByDV($dienstverhaeltnis_id, $dateAsUnixTS)
{
$date = DateTime::createFromFormat( 'U', $dateAsUnixTS );
$datestring = $date->format("Y-m-d");
$qry = "
SELECT
gehaltsbestandteil_id,
gbt.von,
gbt.bis,
gbt.anmerkung,
gbt.dienstverhaeltnis_id,
gehaltstyp_kurzbz,
valorisierungssperre,
gbt.valorisierung,
grundbetrag as grund_betrag_decrypted,
betrag_valorisiert as betrag_val_decrypted,
gt.bezeichnung as gehaltstyp_bezeichnung,
vb.vertragsbestandteiltyp_kurzbz,
bf.funktion_kurzbz,
bf.oe_kurzbz,
fkt.beschreibung as fkt_beschreibung,
fb.bezeichnung as fb_bezeichnung,
org.bezeichnung as org_bezeichnung,
freitext.freitexttyp_kurzbz,
freitext.titel as freitext_titel
FROM hr.tbl_gehaltsbestandteil gbt LEFT JOIN hr.tbl_gehaltstyp gt using(gehaltstyp_kurzbz)
LEFT JOIN hr.tbl_vertragsbestandteil vb using(vertragsbestandteil_id)
LEFT JOIN hr.tbl_vertragsbestandteil_funktion vbf using(vertragsbestandteil_id)
LEFT JOIN public.tbl_benutzerfunktion bf using(benutzerfunktion_id)
LEFT JOIN public.tbl_funktion fkt using(funktion_kurzbz)
LEFT JOIN public.tbl_fachbereich fb using(fachbereich_kurzbz)
LEFT JOIN public.tbl_organisationseinheit org on (bf.oe_kurzbz=org.oe_kurzbz)
LEFT JOIN hr.tbl_vertragsbestandteil_freitext freitext on(vb.vertragsbestandteil_id=freitext.vertragsbestandteil_id)
WHERE gbt.dienstverhaeltnis_id=? AND
(gbt.von<=? and (gbt.bis is null OR gbt.bis>=?))
ORDER BY gt.sort
";
return $this->execQuery($qry,
array($dienstverhaeltnis_id, $datestring, $datestring),
$this->getEncryptedColumns());
}
public function getGBTChartDataByDV_old($dienstverhaeltnis_id)
{
$qry = "
WITH gbt as
(select von,bis,grundbetrag as grund_betrag_decrypted from hr.tbl_gehaltsbestandteil where dienstverhaeltnis_id=?)
select von,bis, (select sum(gbt.grund_betrag_decrypted) as sum_betrag
from gbt where gbt.von<=gbtmeta.von and (gbt.bis is null or gbt.bis>=gbtmeta.von)
) as summe from gbt as gbtmeta order by von,bis
";
return $this->execQuery($qry,
array($dienstverhaeltnis_id),
$this->getEncryptedColumns());
}
public function getGehaltsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false)
{
$stichtagclause = '';
if( !is_null($stichtag) )
{
$date = strftime('%Y-%m-%d', strtotime($stichtag));
$stichtagclause = 'AND (' . $this->escape($date)
. ' BETWEEN COALESCE(von, \'1970-01-01\'::date)'
. ' AND COALESCE(bis, \'2170-01-01\'::date)';
if( $includefuture )
{
$stichtagclause .= ' OR COALESCE(von, \'1970-01-01\'::date) > '
. $this->escape($date);
}
$stichtagclause .= ')';
}
$this->addSelect('*');
$where = <<<EOSQL
dienstverhaeltnis_id = {$this->escape($dienstverhaeltnis_id)}
{$stichtagclause}
EOSQL;
$query = $this->loadWhere(
$where,
$this->getEncryptedColumns()
);
$gehaltsbestandteile = array();
if( null !== ($rows = getData($query)) )
{
foreach( $rows as $row ) {
$tmpgb = new Gehaltsbestandteil();
$tmpgb->hydrateByStdClass($row, true);
$gehaltsbestandteile[] = $tmpgb;
}
}
return $gehaltsbestandteile;
}
public function getGehaltsbestandteil($id)
{
$this->addSelect('*');
$query = $this->load($id, $this->getEncryptedColumns());
$gehaltsbestandteil = null;
if( null !== ($row = getData($query)) )
{
$gehaltsbestandteil = new Gehaltsbestandteil();
$gehaltsbestandteil->hydrateByStdClass($row[0], true);
}
return $gehaltsbestandteil;
}
}

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