From bf1bc8d1a97dbb52c2d1bd30a295a3909058da22 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Sun, 13 Oct 2024 13:32:15 +0200 Subject: [PATCH 01/93] added new contact type email unverifiziert and adresse type meldeadresse (mainly for electronic onboarding) --- system/dbupdate_3.4.php | 1 + ...14_electronic_onboarding_anbindung_ida.php | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index 11880fd55..d3b7b454d 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -58,6 +58,7 @@ require_once('dbupdate_3.4/17513_Entwicklungsteam.php'); require_once('dbupdate_3.4/28575_softwarebereitstellung.php'); require_once('dbupdate_3.4/41150_oe-pfad_db_view.php'); require_once('dbupdate_3.4/44031_stv_favorites.php'); +require_once('dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php'); // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; diff --git a/system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php b/system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php new file mode 100644 index 000000000..ccc0a5827 --- /dev/null +++ b/system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php @@ -0,0 +1,30 @@ +db_query("SELECT 1 FROM public.tbl_kontakttyp WHERE kontakttyp='email_unverifiziert'")) +{ + if($db->db_num_rows($result)==0) + { + $qry = "INSERT INTO public.tbl_kontakttyp(kontakttyp, beschreibung, bezeichnung_mehrsprachig) VALUES('email_unverifiziert', 'Unverifizierte E-Mail', '{\"Unverifizierte E-Mail\", \"Unverified email\"}');"; + + if(!$db->db_query($qry)) + echo 'Kontakttyp: '.$db->db_last_error().'
'; + else + echo '
Neuen Kontakttyp E-Mail unverifiziert in public.tbl_kontakttyp hinzugefügt'; + } +} + +// public.tbl_adressentyp: add type Meldeadresse +if($result = $db->db_query("SELECT 1 FROM public.tbl_adressentyp WHERE adressentyp_kurzbz='m'")) +{ + if($db->db_num_rows($result)==0) + { + $qry = "INSERT INTO public.tbl_adressentyp(adressentyp_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES('m', 'Meldeadresse', '{\"Meldeadresse\", \"Registered adress\"}', 6);"; + + if(!$db->db_query($qry)) + echo 'Adressentyp: '.$db->db_last_error().'
'; + else + echo '
Neue Adressentyp Meldeadresse in public.tbl_adressentyp hinzugefügt'; + } +} From b8ff37eb8edfd28c897119d032c517533663574f Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Sat, 19 Oct 2024 17:25:09 +0200 Subject: [PATCH 02/93] added kontakt verifikation table for saving of kontakt verifikation data, added model for the table --- .../person/Kontaktverifikation_model.php | 42 ++++++++++++++++ ...14_electronic_onboarding_anbindung_ida.php | 48 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 application/models/person/Kontaktverifikation_model.php diff --git a/application/models/person/Kontaktverifikation_model.php b/application/models/person/Kontaktverifikation_model.php new file mode 100644 index 000000000..b15439edb --- /dev/null +++ b/application/models/person/Kontaktverifikation_model.php @@ -0,0 +1,42 @@ +dbTable = 'public.tbl_kontakt_verifikation'; + $this->pk = 'kontakt_verifikation_id'; + } + + /** + * Gets contact verification for a person and a verification code + * @param person_id + * @param kontakttyp + * @param verifikation_code + * @param expiration_days number of days after which verifikation code expires + * @return object success or error + */ + public function getKontaktVerifikation($person_id, $kontakttyp, $verifikation_code, $expiration_days = 1) + { + $qry = " + SELECT + kt.kontakt_id, + kv.verifikation_code + FROM + public.tbl_kontakt_verifikation kv + JOIN public.tbl_kontakt kt USING(kontakt_id) + WHERE kt.person_id = ? + AND kt.kontakttyp = ? + AND kv.verifikation_code = ? + AND kv.erstelldatum >= NOW() - INTERVAL '".$this->escape($expiration_days)." days' + ORDER BY + kt.kontakt_id DESC + LIMIT 1"; + + return $this->execQuery($qry, array($person_id, $kontakttyp, $verifikation_code)); + } +} diff --git a/system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php b/system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php index ccc0a5827..b204d45aa 100644 --- a/system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php +++ b/system/dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php @@ -28,3 +28,51 @@ if($result = $db->db_query("SELECT 1 FROM public.tbl_adressentyp WHERE adressent echo '
Neue Adressentyp Meldeadresse in public.tbl_adressentyp hinzugefügt'; } } + +if (!$result = @$db->db_query('SELECT 1 FROM public.tbl_kontakt_verifikation LIMIT 1')) +{ + $qry = "CREATE SEQUENCE public.tbl_kontakt_verifikation_kontakt_verifikation_id_seq + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + START WITH 1 + CACHE 1 + NO CYCLE; + + CREATE TABLE public.tbl_kontakt_verifikation + ( + kontakt_verifikation_id integer DEFAULT nextval('public.tbl_kontakt_verifikation_kontakt_verifikation_id_seq'::regclass), + kontakt_id integer UNIQUE NOT NULL, + verifikation_code varchar(32) UNIQUE NOT NULL, + erstelldatum timestamp without time zone, + verifikation_datum timestamp without time zone, + app varchar(32), + CONSTRAINT pk_tbl_kontakt_verifikation_id PRIMARY KEY (kontakt_verifikation_id) + ); + + ALTER TABLE public.tbl_kontakt_verifikation ADD CONSTRAINT fk_tbl_kontakt_verifikation_kontakt_id FOREIGN KEY (kontakt_id) + REFERENCES public.tbl_kontakt (kontakt_id) + ON DELETE CASCADE ON UPDATE CASCADE; + + ALTER TABLE public.tbl_kontakt_verifikation ADD CONSTRAINT fk_tbl_kontakt_verifikation_app FOREIGN KEY (app) + REFERENCES system.tbl_app (app) + ON DELETE RESTRICT ON UPDATE CASCADE; + + COMMENT ON TABLE public.tbl_kontakt_verifikation IS 'Contact verification'; + COMMENT ON COLUMN public.tbl_kontakt_verifikation.kontakt_id IS 'Contact to verify'; + COMMENT ON COLUMN public.tbl_kontakt_verifikation.verifikation_code IS 'Code generated for verification'; + COMMENT ON COLUMN public.tbl_kontakt_verifikation.erstelldatum IS 'Time when verification code was generated'; + COMMENT ON COLUMN public.tbl_kontakt_verifikation.verifikation_datum IS 'Time when contact was verified'; + COMMENT ON COLUMN public.tbl_kontakt_verifikation.app IS 'App where contact was verified'; + + GRANT SELECT, UPDATE, INSERT, DELETE ON public.tbl_kontakt_verifikation TO web; + GRANT SELECT, UPDATE, INSERT, DELETE ON public.tbl_kontakt_verifikation TO vilesci; + GRANT SELECT, UPDATE ON public.tbl_kontakt_verifikation_kontakt_verifikation_id_seq TO vilesci; + GRANT SELECT, UPDATE ON public.tbl_kontakt_verifikation_kontakt_verifikation_id_seq TO web; + "; + + if(!$db->db_query($qry)) + echo 'public.tbl_kontakt_verifikation: '.$db->db_last_error().'
'; + else + echo ' public.tbl_kontakt_verifikation: Tabelle hinzugefuegt
'; +} From add9263d35ff2a1883c5336a5329144714118882 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 11 Nov 2024 17:17:33 +0100 Subject: [PATCH 03/93] added Electronic Onboarding phrases --- system/phrasesupdate.php | 366 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 364 insertions(+), 2 deletions(-) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 7ef0269c9..29d5d6132 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -31025,8 +31025,370 @@ array( 'insertvon' => 'system' ) ) - ) - + ), + //**************************** FHC-Core-ElectronicOnboarding + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'emailFehlt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Email fehlt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Email is missing', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'emailUngueltig', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Email ist ungültig', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The email is not valid', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'emailRegistriert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Diese Email ist bereits registriert. Bitte verwenden sie eine andere Email oder loggen sie sich mit einer anderen Methode ein.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The email is already registered. Please choose a different email or use a different login method.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungZugangEmailBetreff', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Zugang zu Ihrer Bewerbung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Access to your application', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungZugangEmailAnredeWeiblich', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sehr geehrte Frau', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Dear Ms', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungZugangEmailAnredeMaennlich', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sehr geehrter Herr', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Dear Mr', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungZugangEmailAnredeNeutral', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sehr geehrte/r', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Dear', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'registrierungVerifzierenFuer', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Registrierung verifizieren für', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Verify registration for', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'registrierungVerifzieren', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Registrierung verifizieren', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Verify registration', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'vorname', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Vorname', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'First name', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'nachname', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Nachname', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Last name', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'geburtsdatum', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Geburtsdatum', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Birth date', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'emailAdresse', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'E-Mail Adresse', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'E-mail address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'emailGesendet', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die E-Mail mit dem Link zu Ihrer Bewerbung wurde erfolgreich an {0} verschickt.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The email with the link to your application has been successfully sent to {0}.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'emailGesendetHinweis', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'In der Regel erhalten Sie das Mail in wenigen Minuten. Wenn Sie nach 24 Stunden noch kein Mail erhalten haben, + kontaktieren Sie bitte unsere {0}Studienberatung{1}', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'You should receive an e-mail within a few minutes. If you receive no e-mail within 24 hours please contact + our {0}student counselling team{1}.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'fehlerBeiRegistrierung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Fehler bei der Registrierung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Error when registering', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'fehlerBeiRegistrierungText', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Da ist etwas schief gelaufen. Wir bitten um Entschuldigung.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Sorry, something went wrong.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'fehlerBeiRegistrierungNochmalVersuchen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Nochmals versuchen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Try again', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From b63146a8d89cdc4f08213350170346b1956cd560 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 20 Nov 2024 15:03:59 +0100 Subject: [PATCH 04/93] added MeldezettelJob for accepting Meldezettel of students with Meldeadresse --- .../controllers/jobs/MeldezettelJob.php | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 application/controllers/jobs/MeldezettelJob.php diff --git a/application/controllers/jobs/MeldezettelJob.php b/application/controllers/jobs/MeldezettelJob.php new file mode 100644 index 000000000..329597985 --- /dev/null +++ b/application/controllers/jobs/MeldezettelJob.php @@ -0,0 +1,86 @@ +_ci =& get_instance(); + + $this->_ci->load->model('crm/Dokumentprestudent_model', 'DokumentprestudentModel'); + } + + /** + * Sets Meldezettel to "accepted" for all students with Meldeadresse. + */ + public function acceptMeldezettel() + { + $this->logInfo('Start Meldezettel Job'); + + $params = array(self::DOKUMENT_KURZBZ); + + $qry = " + -- get all prestudents with meldeadresse, but no accepted Meldezettel + SELECT + DISTINCT prestudent_id + FROM + public.tbl_adresse + JOIN public.tbl_person USING (person_id) + JOIN public.tbl_prestudent ps USING (person_id) + WHERE + typ = 'm' + AND NOT EXISTS ( + SELECT + 1 + FROM + public.tbl_dokumentprestudent + WHERE + prestudent_id = ps.prestudent_id + AND dokument_kurzbz = ? + )"; + + // get all prestudents with Meldeadresse and no accpeted Meldezettel + $result = $this->_ci->DokumentprestudentModel->execReadOnlyQuery($qry, $params); + + if (isError($result)) + { + $this->logError(getError($result)); + } + + $count = 0; + + if (hasData($result)) + { + $prestudents = getData($result); + + foreach ($prestudents as $prestudent) + { + // set Meldezettel to accepted + $result = $this->_ci->DokumentprestudentModel->insert( + array( + 'prestudent_id' => $prestudent->prestudent_id, + 'dokument_kurzbz' => self::DOKUMENT_KURZBZ, + 'datum' => date('Y-m-d'), + 'insertamum' => strftime('%Y-%m-%d %H:%M'), + 'insertvon' => self::INSERT_VON + ) + ); + + if (isError($result)) + $this->logError(getError($result)); + else + $count++; + } + } + + $this->logInfo('End Meldezettel Job', array('Number of changes ' => $count)); + } +} From 0a97b39efbb877ff3f7a07ca0d531434b54cb3ca Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 24 Dec 2024 19:14:04 +0100 Subject: [PATCH 05/93] added phrases for electronic onboarding verification page --- .../person/Kontaktverifikation_model.php | 2 +- system/phrasesupdate.php | 137 +++++++++++++++++- 2 files changed, 132 insertions(+), 7 deletions(-) diff --git a/application/models/person/Kontaktverifikation_model.php b/application/models/person/Kontaktverifikation_model.php index b15439edb..17bcb1c35 100644 --- a/application/models/person/Kontaktverifikation_model.php +++ b/application/models/person/Kontaktverifikation_model.php @@ -29,7 +29,7 @@ class Kontaktverifikation_model extends DB_Model FROM public.tbl_kontakt_verifikation kv JOIN public.tbl_kontakt kt USING(kontakt_id) - WHERE kt.person_id = ? + WHERE kt.person_id = ? AND kt.kontakttyp = ? AND kv.verifikation_code = ? AND kv.erstelldatum >= NOW() - INTERVAL '".$this->escape($expiration_days)." days' diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 8d7bdd939..843a055a1 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -31310,18 +31310,18 @@ array( array( 'app' => 'core', 'category' => 'onboarding', - 'phrase' => 'registrierungVerifzierenFuer', + 'phrase' => 'bewerbungVerifizierung', 'insertvon' => 'system', 'phrases' => array( array( 'sprache' => 'German', - 'text' => 'Registrierung verifizieren für', + 'text' => 'Verifizierung Ihrer Bewerbung', 'description' => '', 'insertvon' => 'system' ), array( 'sprache' => 'English', - 'text' => 'Verify registration for', + 'text' => 'Application verification', 'description' => '', 'insertvon' => 'system' ) @@ -31330,18 +31330,143 @@ array( array( 'app' => 'core', 'category' => 'onboarding', - 'phrase' => 'registrierungVerifzieren', + 'phrase' => 'bewerbungVerifzieren', 'insertvon' => 'system', 'phrases' => array( array( 'sprache' => 'German', - 'text' => 'Registrierung verifizieren', + 'text' => 'Bewerbung verifizieren', 'description' => '', 'insertvon' => 'system' ), array( 'sprache' => 'English', - 'text' => 'Verify registration', + 'text' => 'Verify application', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungVerifizierungEinleitung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Wenn Ihre Daten stimmen, geben Sie bitte Ihre E-Mail Adresse ein und drücken Sie auf "Bewerbung verfifizieren". +Danach erhalten Sie eine E-Mail mit dem Link zu Ihrer Bewerbung an die angegebene Adresse. +Dort können Sie Studienrichtungen hinzufügen, Ihre Daten vervollständigen, und sich unverbindlich bewerben.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'If your data is correct, please enter your email and click "Verify application". +We will then send you a link via e-mail to the address specified. There, you can add personal information or degree programs and submit non-binding applications.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungVerifizierungKontakthinweis', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Wenn Sie mehr Informationen benötigen, steht Ihnen unsere Studienberatung gerne persönlich, telefonisch, per E-Mail oder WhatsApp zur Verfügung.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Should you require any additional information, please do not hesitate to contact our student counselling team in person, by phone, or via e-mail or WhatsApp.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungVerifizierungDatenschutzhinweis', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Datenschutz-Hinweis', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Privacy information', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungVerifizierungDatenschutzhinweisText', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die uns von Ihnen zum Zwecke der Bewerbung bekanntgegebenen Daten werden von uns ausschließlich zur Abwicklung der Bewerbung auf der Grundlage von vor- bzw vertraglichen Zwecken verarbeitet und mit der unten beschriebenen Ausnahme bei Unklarheiten betreffend die Zugangsvoraussetzungen nicht an Dritte weitergegeben. +Kommt es zu keinem weiteren Kontakt bzw zu keiner Aufnahme, löschen wir Ihre Daten nach drei Jahren.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The data communicated to us by you for the purpose of the application will be used by us exclusively for the processing of the application on the basis of pre-contractual or contractual purposes and will not be passed on to third parties with the exception described below in case of uncertainties regarding the entry requirements. +If there is no further contact or enrolment, your data will be deleted after three years.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungVerifizierungInformationenDatenschutzGrundverordnung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Informationen zu Ihren Betroffenenrechten finden Sie hier:', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Information on your data subject rights can be found here:', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bewerbungVerifizierungDatenschutzFragen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bei Fragen stehen wir Ihnen jederzeit unter folgender Mail zur Verfügung: ', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'If you have any questions, please contact us at ', 'description' => '', 'insertvon' => 'system' ) From 115b35ad7b40f3b27a161c5a8859ca019f1924e5 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 8 Jan 2025 14:52:32 +0100 Subject: [PATCH 06/93] electronic onboarding: changed phrase for error display --- system/phrasesupdate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 843a055a1..4de9cbb03 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -31622,13 +31622,13 @@ If there is no further contact or enrolment, your data will be deleted after thr 'phrases' => array( array( 'sprache' => 'German', - 'text' => 'Da ist etwas schief gelaufen. Wir bitten um Entschuldigung.', + 'text' => 'Es ist ein Fehler bei der Registrierung aufgetreten.', 'description' => '', 'insertvon' => 'system' ), array( 'sprache' => 'English', - 'text' => 'Sorry, something went wrong.', + 'text' => 'An error occured during registration.', 'description' => '', 'insertvon' => 'system' ) From 08cb3d3809b34b43eb87558a02a5ae702e4c8681 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Thu, 16 Jan 2025 21:02:01 +0100 Subject: [PATCH 07/93] electronic onboarding phrase typo fix --- system/phrasesupdate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 4de9cbb03..7f030e62b 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -31355,7 +31355,7 @@ array( 'phrases' => array( array( 'sprache' => 'German', - 'text' => 'Wenn Ihre Daten stimmen, geben Sie bitte Ihre E-Mail Adresse ein und drücken Sie auf "Bewerbung verfifizieren". + 'text' => 'Wenn Ihre Daten stimmen, geben Sie bitte Ihre E-Mail Adresse ein und drücken Sie auf "Bewerbung verifizieren". Danach erhalten Sie eine E-Mail mit dem Link zu Ihrer Bewerbung an die angegebene Adresse. Dort können Sie Studienrichtungen hinzufügen, Ihre Daten vervollständigen, und sich unverbindlich bewerben.', 'description' => '', From 39ada202774fbb77811a2cd54bd96f2a046917aa Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 22 Jan 2025 15:26:25 +0100 Subject: [PATCH 08/93] Electronic Onboarding: added phrases --- system/phrasesupdate.php | 102 +++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 20 deletions(-) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 7f030e62b..e177274ec 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -31307,26 +31307,6 @@ array( ) ) ), - array( - 'app' => 'core', - 'category' => 'onboarding', - 'phrase' => 'bewerbungVerifizierung', - 'insertvon' => 'system', - 'phrases' => array( - array( - 'sprache' => 'German', - 'text' => 'Verifizierung Ihrer Bewerbung', - 'description' => '', - 'insertvon' => 'system' - ), - array( - 'sprache' => 'English', - 'text' => 'Application verification', - 'description' => '', - 'insertvon' => 'system' - ) - ) - ), array( 'app' => 'core', 'category' => 'onboarding', @@ -31654,6 +31634,88 @@ If there is no further contact or enrolment, your data will be deleted after thr ) ) ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'zustimmungDatenuebermittlung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Können in Ausnahmefällen die Zugangsvoraussetzungen von der FH Technikum Wien nicht abschließend abgeklärt werden, erteile ich die Zustimmung, dass die FH Technikum Wien die Dokumente zur Überprüfung an die zuständigen Behörden weiterleiten kann.
+Ich wurde darüber informiert, dass ich nicht verpflichtet bin, der Übermittlung meiner Daten zuzustimmen. Diese Zustimmung ist allerdings notwendig, um die Bewerbung berücksichtigen zu können.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'If in exceptional cases the admission requirements can not be finally clarified by the UAS Technikum Wien, I give my consent that the UAS Technikum Wien can forward the documents to the competent authorities for verification.
+I have been informed that I am under no obligation to consent to the transmission of my data. However, this consent is necessary in order for the application to be considered.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'zustimmungDatenschutzerklaerung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ich habe die Datenschutzerklärung zu Kenntnis genommen.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'I have taken note of the privacy policy.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bitteDatenuebermittlungZustimmen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sie müssen der Datenübermittlung zustimmen, um Ihre Bewerbung abschicken zu können.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'You have to consent the transmission of your data to send the application.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'onboarding', + 'phrase' => 'bitteDatenschutzerklaerungZustimmen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sie müssen der Datenschutzerklärung zustimmen, um Ihre Bewerbung abschicken zu können.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'You have to consent to the privacy statement to send the application.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ) ); From ea2be8026b463c8cf9c7132197aea82831aa9886 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 12 Mar 2025 08:06:23 +0100 Subject: [PATCH 09/93] filter hidden from kontakttyp, show typ.beschreibung in dropdown --- .../controllers/api/frontend/v1/stv/Kontakt.php | 15 ++++++++------- .../Details/Kontakt/Contact.js | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Kontakt.php b/application/controllers/api/frontend/v1/stv/Kontakt.php index fd16fff06..1c3c0c95d 100644 --- a/application/controllers/api/frontend/v1/stv/Kontakt.php +++ b/application/controllers/api/frontend/v1/stv/Kontakt.php @@ -439,6 +439,7 @@ class Kontakt extends FHCAPI_Controller $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); } $this->terminateWithSuccess((getData($result) ?: [])); + } public function getKontakttypen() @@ -446,13 +447,13 @@ class Kontakt extends FHCAPI_Controller $this->load->model('person/Kontakttyp_model', 'KontakttypModel'); $result = $this->KontakttypModel->load(); - if (isError($result)) { - $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - } - else - { - $this->terminateWithSuccess(getData($result) ?: []); - } + + $data = $this->getDataOrTerminateWithError($result); + + $filteredData = array_filter($data, function ($item) { + return $item->kontakttyp !== "hidden"; + }); + $this->terminateWithSuccess($filteredData); } public function loadContact() diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Contact.js b/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Contact.js index 87dc70eb1..0bda648a9 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Contact.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Contact.js @@ -322,7 +322,7 @@ export default{ v-model="contactData.kontakttyp"> > - + From f96bfbe0004a41312fb64d940bf9686329939a20 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Wed, 28 May 2025 07:51:10 +0200 Subject: [PATCH 10/93] =?UTF-8?q?lehrf=C3=A4cherverteilung=20v1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/controllers/LVVerwaltung.php | 42 + .../api/frontend/v1/Lehrveranstaltung.php | 243 ++++++ .../api/frontend/v1/lv/DirektGruppe.php | 108 +++ .../api/frontend/v1/lv/Favorites.php | 47 ++ .../controllers/api/frontend/v1/lv/Gruppe.php | 189 +++++ .../api/frontend/v1/lv/Lehreinheit.php | 438 +++++++++++ .../controllers/api/frontend/v1/lv/Lektor.php | 380 +++++++++ .../controllers/api/frontend/v1/lv/Setup.php | 116 +++ .../api/frontend/v1/lv/StgTree.php | 91 +++ .../controllers/api/frontend/v1/lv/Tags.php | 24 + .../frontend/v1/notiz/NotizLehreinheit.php | 21 + application/libraries/LektorLib.php | 342 +++++++++ .../models/accounting/Vertrag_model.php | 70 ++ .../models/education/Lehreinheit_model.php | 438 +++++++++++ .../education/Lehreinheitgruppe_model.php | 208 +++++ .../Lehreinheitmitarbeiter_model.php | 71 ++ .../education/Lehrveranstaltung_model.php | 225 ++++++ .../Organisationseinheit_model.php | 30 + .../models/organisation/Studienplan_model.php | 21 + application/models/person/Notiz_model.php | 54 +- .../models/ressource/Mitarbeiter_model.php | 14 + .../models/ressource/Stundenplandev_model.php | 83 ++ .../models/ressource/Stundensatz_model.php | 16 + .../Dienstverhaeltnis_model.php | 21 + application/views/LVVerwaltung.php | 39 + public/css/Lvverwaltung.css | 27 + public/js/api/factory/notiz.js | 5 +- public/js/api/factory/notiz/lehreinheit.js | 29 + public/js/api/lehrveranstaltung.js | 28 + public/js/api/lehrveranstaltung/details.js | 30 + .../js/api/lehrveranstaltung/direktgruppe.js | 26 + public/js/api/lehrveranstaltung/gruppe.js | 56 ++ .../js/api/lehrveranstaltung/lehreinheit.js | 41 + public/js/api/lehrveranstaltung/lektor.js | 78 ++ public/js/api/lehrveranstaltung/setup.js | 9 + .../api/lehrveranstaltung/studiengangtree.js | 43 ++ public/js/api/lehrveranstaltung/tag.js | 54 ++ public/js/api/lehrveranstaltung/vertrag.js | 22 + public/js/apps/LVVerwaltung.js | 46 ++ .../LVVerwaltung/Details/Direktinskription.js | 155 ++++ .../components/LVVerwaltung/Details/Form.js | 209 +++++ .../LVVerwaltung/Details/Gruppen.js | 195 +++++ .../components/LVVerwaltung/LVVerwaltung.js | 282 +++++++ .../components/LVVerwaltung/Lektor/Daten.js | 270 +++++++ .../components/LVVerwaltung/Lektor/Table.js | 223 ++++++ .../components/LVVerwaltung/Lektor/Vertrag.js | 161 ++++ .../js/components/LVVerwaltung/Setup/Table.js | 683 +++++++++++++++++ .../js/components/LVVerwaltung/Setup/Tabs.js | 62 ++ .../components/LVVerwaltung/Tabs/Details.js | 133 ++++ .../js/components/LVVerwaltung/Tabs/Lektor.js | 70 ++ .../js/components/LVVerwaltung/Tabs/Notiz.js | 33 + .../js/components/Stv/Studentenverwaltung.js | 4 +- .../Stv/Studentenverwaltung/Verband.js | 69 +- public/js/components/Tag/Tag.js | 12 +- .../tabulator/filters/extendedHeaderFilter.js | 110 ++- system/dbupdate_3.4.php | 1 + .../60882_lehrfaecherverteilung_favorites.php | 16 + system/phrasesupdate.php | 723 +++++++++++++++++- 58 files changed, 7146 insertions(+), 90 deletions(-) create mode 100644 application/controllers/LVVerwaltung.php create mode 100644 application/controllers/api/frontend/v1/Lehrveranstaltung.php create mode 100644 application/controllers/api/frontend/v1/lv/DirektGruppe.php create mode 100644 application/controllers/api/frontend/v1/lv/Favorites.php create mode 100644 application/controllers/api/frontend/v1/lv/Gruppe.php create mode 100644 application/controllers/api/frontend/v1/lv/Lehreinheit.php create mode 100644 application/controllers/api/frontend/v1/lv/Lektor.php create mode 100644 application/controllers/api/frontend/v1/lv/Setup.php create mode 100644 application/controllers/api/frontend/v1/lv/StgTree.php create mode 100644 application/controllers/api/frontend/v1/lv/Tags.php create mode 100644 application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php create mode 100644 application/libraries/LektorLib.php create mode 100644 application/views/LVVerwaltung.php create mode 100644 public/css/Lvverwaltung.css create mode 100644 public/js/api/factory/notiz/lehreinheit.js create mode 100644 public/js/api/lehrveranstaltung.js create mode 100644 public/js/api/lehrveranstaltung/details.js create mode 100644 public/js/api/lehrveranstaltung/direktgruppe.js create mode 100644 public/js/api/lehrveranstaltung/gruppe.js create mode 100644 public/js/api/lehrveranstaltung/lehreinheit.js create mode 100644 public/js/api/lehrveranstaltung/lektor.js create mode 100644 public/js/api/lehrveranstaltung/setup.js create mode 100644 public/js/api/lehrveranstaltung/studiengangtree.js create mode 100644 public/js/api/lehrveranstaltung/tag.js create mode 100644 public/js/api/lehrveranstaltung/vertrag.js create mode 100644 public/js/apps/LVVerwaltung.js create mode 100644 public/js/components/LVVerwaltung/Details/Direktinskription.js create mode 100644 public/js/components/LVVerwaltung/Details/Form.js create mode 100644 public/js/components/LVVerwaltung/Details/Gruppen.js create mode 100644 public/js/components/LVVerwaltung/LVVerwaltung.js create mode 100644 public/js/components/LVVerwaltung/Lektor/Daten.js create mode 100644 public/js/components/LVVerwaltung/Lektor/Table.js create mode 100644 public/js/components/LVVerwaltung/Lektor/Vertrag.js create mode 100644 public/js/components/LVVerwaltung/Setup/Table.js create mode 100644 public/js/components/LVVerwaltung/Setup/Tabs.js create mode 100644 public/js/components/LVVerwaltung/Tabs/Details.js create mode 100644 public/js/components/LVVerwaltung/Tabs/Lektor.js create mode 100644 public/js/components/LVVerwaltung/Tabs/Notiz.js create mode 100644 system/dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php diff --git a/application/controllers/LVVerwaltung.php b/application/controllers/LVVerwaltung.php new file mode 100644 index 000000000..2a79d6375 --- /dev/null +++ b/application/controllers/LVVerwaltung.php @@ -0,0 +1,42 @@ +method] = ['admin:r', 'assistenz:r']; + parent::__construct($permissions); + + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + } + + /** + * @return void + */ + public function _remap() + { + $this->load->view('LVVerwaltung', [ + 'permissions' => [ + 'lehre/lehrveranstaltung' => $this->permissionlib->isBerechtigt('lehre/lehrveranstaltung'), + 'lv-plan/gruppenentfernen' => $this->permissionlib->isBerechtigt('lv-plan/gruppenentfernen'), + 'lv-plan/lektorentfernen' => $this->permissionlib->isBerechtigt('lv-plan/lektorentfernen'), + ], + 'variables' => [ + 'semester_aktuell' => $this->variablelib->getVar('semester_aktuell') + ], + 'configs' => [ + 'showVertragsdetails' => defined('FAS_LV_LEKTORINNENZUTEILUNG_VERTRAGSDETAILS_ANZEIGEN') && FAS_LV_LEKTORINNENZUTEILUNG_VERTRAGSDETAILS_ANZEIGEN, + 'showGewichtung' => defined('CIS_GESAMTNOTE_GEWICHTUNG') && CIS_GESAMTNOTE_GEWICHTUNG, + 'lehreinheitAnmerkungDefault' => defined('LEHREINHEIT_ANMERKUNG_DEFAULT') ? LEHREINHEIT_ANMERKUNG_DEFAULT : '', + 'lehreinheitRaumtypDefault' => defined('DEFAULT_LEHREINHEIT_RAUMTYP') ? DEFAULT_LEHREINHEIT_RAUMTYP : '', + 'lehreinheitRaumtypAlternativeDefault' => defined('DEFAULT_LEHREINHEIT_RAUMTYP_ALTERNATIV') ? DEFAULT_LEHREINHEIT_RAUMTYP_ALTERNATIV : '' + ] + ]); + + } +} diff --git a/application/controllers/api/frontend/v1/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/Lehrveranstaltung.php new file mode 100644 index 000000000..1b2e2bc35 --- /dev/null +++ b/application/controllers/api/frontend/v1/Lehrveranstaltung.php @@ -0,0 +1,243 @@ +. + */ + +if (!defined('BASEPATH')) + exit('No direct script access allowed'); + +class Lehrveranstaltung extends FHCAPI_Controller +{ + private $_ci; + private $_uid; + + public function __construct() + { + parent::__construct([ + 'loadByEmployee' => ['admin:r', 'assistenz:r'], + 'loadByStudiengang' => ['admin:r', 'assistenz:r'], + 'loadByLV' => ['admin:r', 'assistenz:r'], + ]); + + $this->_ci = &get_instance(); + $this->_setAuthUID(); + + $this->_ci->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); + } + public function loadByEmployee($mitarbeiter_uid = null, $stg_kz = null) + { + if (is_null($mitarbeiter_uid)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $studiensemester_kurzbz = $this->_ci->variablelib->getVar('semester_aktuell'); + + $lehrveranstaltungen = $this->_ci->LehreinheitModel->getLvsByEmployee($mitarbeiter_uid, $studiensemester_kurzbz, $stg_kz); + $lehrveranstaltungen_data = $this->getDataOrTerminateWithError($lehrveranstaltungen); + + $tree = []; + + foreach ($lehrveranstaltungen_data as $lehrveranstaltung) + { + $lehreinheiten = $this->_ci->LehreinheitModel->getLEByLV($lehrveranstaltung->lehrveranstaltung_id, $studiensemester_kurzbz, $mitarbeiter_uid); + $lehreinheiten_data = $this->getDataOrTerminateWithError($lehreinheiten); + + if (!isset($lehrveranstaltung->_children)) + { + $lehrveranstaltung->_children = $lehreinheiten_data; + } + $tree[] = $lehrveranstaltung; + } + + $this->terminateWithSuccess($tree); + } + + public function loadByStudiengang($studiengang_kz = null, $semester = null) + { + if (is_null($studiengang_kz) || !ctype_digit((string)$studiengang_kz)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $verband = null; + if (!is_null($semester) && !is_numeric($semester)) + { + $verband = $semester; + $semester = null; + } + + $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $studiensemester_kurzbz = $this->_ci->variablelib->getVar('semester_aktuell'); + $studienplan_data = $this->_ci->StudienplanModel->getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $semester, $verband); + + $studienplan_ids = array(); + $only_ids = array(); + $placeholders = array(); + + if (hasData($studienplan_data)) + { + foreach (getData($studienplan_data) as $studienplan) { + $placeholders[] = "(?, ?)"; + $studienplan_ids[] = $studienplan->studienplan_id; + $studienplan_ids[] = $studienplan->semester; + $only_ids[] = $studienplan->studienplan_id; + } + } + + $lehrveranstaltungen_data = $this->_ci->LehrveranstaltungModel->getLvsByStudiengang($studienplan_ids, $placeholders, $only_ids, $studiengang_kz, $studiensemester_kurzbz, $semester, $verband); + $lehrveranstaltungen_data = hasData($lehrveranstaltungen_data) ? getData($lehrveranstaltungen_data) : array(); + + + $tree = []; + foreach ($lehrveranstaltungen_data as $row) + { + $rowData = $row; + + $lehreinheiten_data = $this->_ci->LehreinheitModel->getByLvidStudiensemester($row->lehrveranstaltung_id, $studiensemester_kurzbz); + + if (hasData($lehreinheiten_data)) + { + $lehreinheiten = getData($lehreinheiten_data); + $rowData->_children = $lehreinheiten; + } + + if (!isEmptyString($row->studienplan_lehrveranstaltung_id_parent)) + { + $child = $this->_ci->StudienplanModel->loadStudienplanLehrveranstaltung($row->studienplan_lehrveranstaltung_id_parent); + + if (hasData($child)) + { + $child = getData($child)[0]; + $searchId = $child->lehrveranstaltung_id; + + foreach ($lehrveranstaltungen_data as &$searchParent) + { + if ($searchParent->lehrveranstaltung_id === $searchId) + { + if (!isset($searchParent->_children)) + { + $searchParent->_children = []; + } + + if (is_array($searchParent->_children)) + { + $searchParent->_children[] = $row; + } + else + { + $searchParent->_children = [$searchParent->_children, $row]; + } + break; + } + } + + } + } + else + { + $tree[] = $rowData; + } + } + + $counter = 0; + $this->assignUniqueIndex($tree, $counter); + $this->terminateWithSuccess($tree); + } + + + public function loadByLV($lehrveranstaltung_id = null) + { + if (is_null($lehrveranstaltung_id) || !ctype_digit((string)$lehrveranstaltung_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->_ci->LehrveranstaltungModel->addSelect('lehrveranstaltung_id, lehrform_kurzbz, lehre, bezeichnung as lvbezeichnung'); + $lehrveranstaltung_result = $this->_ci->LehrveranstaltungModel->loadWhere(array('lehrveranstaltung_id' => $lehrveranstaltung_id)); + $lehrveranstaltung_result = $this->getDataOrTerminateWithError($lehrveranstaltung_result); + $lehrveranstaltung = $lehrveranstaltung_result[0]; + + $this->_ci->LehreinheitModel->addSelect('lehrveranstaltung_id_kompatibel'); + $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung_kompatibel', 'lehrveranstaltung_id'); + $lehrfaecher = $this->_ci->LehreinheitModel->loadWhere(array('lehrveranstaltung_id' => $lehrveranstaltung->lehrveranstaltung_id)); + + $lehrfaecher_array = []; + if (hasData($lehrfaecher)) + $lehrfaecher_array = array_merge($lehrfaecher_array, array_column(getData($lehrfaecher), 'lehrveranstaltung_id_kompatibel')); + + $lehrfaecher_array[] = $lehrveranstaltung->lehrveranstaltung_id; + + $this->_ci->LehrveranstaltungModel->addDistinct('lehrfach_id'); + $this->_ci->LehrveranstaltungModel->addSelect("tbl_lehrveranstaltung.lehrveranstaltung_id, CONCAT(tbl_lehrveranstaltung.bezeichnung || '(' || tbl_lehrveranstaltung.oe_kurzbz || ')') as lehrfach"); + $this->_ci->LehrveranstaltungModel->db->where_in('tbl_lehrveranstaltung.lehrveranstaltung_id', $lehrfaecher_array); + $lehrfaecher_result = $this->_ci->LehrveranstaltungModel->load(); + + $lehrfaecher_array = hasData($lehrfaecher_result) ? getData($lehrfaecher_result) : array(); + + $lehrveranstaltung->lehrfaecher = $lehrfaecher_array; + $this->terminateWithSuccess($lehrveranstaltung); + } + + /* + * (david) ggf. im naechsten release + * public function loadByOrganization($oe_kurzbz) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + $lehrveranstaltungen = $this->LehrveranstaltungModel->getLvsByOrganization($oe_kurzbz); + $lehrveranstaltungen_data = $this->getDataOrTerminateWithError($lehrveranstaltungen); + $tree = []; + + foreach ($lehrveranstaltungen_data as $lehrveranstaltung) + { + $lehreinheiten = $this->LehreinheitModel->getLEByLV($lehrveranstaltung->lehrveranstaltung_id, $studiensemester_kurzbz); + $lehreinheiten_data = $this->getDataOrTerminateWithError($lehreinheiten); + + if (!isset($lehrveranstaltung->_children)) + { + + $lehrveranstaltung->_children = $lehreinheiten_data; + } + $tree[] = $lehrveranstaltung; + } + $this->terminateWithSuccess($tree); + }*/ + + /*public function loadByFachbereich($fachbereich, $mitarbeiter_uid = null) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + $this->LehreinheitModel->getLvsByFachbereich($fachbereich, $studiensemester_kurzbz, $mitarbeiter_uid); + }*/ + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) + show_error('User authentification failed'); + } + + private function assignUniqueIndex(&$nodes, &$counter) + { + foreach ($nodes as &$node) + { + $node->uniqueindex = $counter++; + if (!empty($node->_children) && is_array($node->_children)) + { + $this->assignUniqueIndex($node->_children, $counter); + } + } + } +} diff --git a/application/controllers/api/frontend/v1/lv/DirektGruppe.php b/application/controllers/api/frontend/v1/lv/DirektGruppe.php new file mode 100644 index 000000000..fe1737f6a --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/DirektGruppe.php @@ -0,0 +1,108 @@ +. + */ + +if (!defined('BASEPATH')) + exit('No direct script access allowed'); + +class DirektGruppe extends FHCAPI_Controller +{ + private $_ci; + public function __construct() + { + parent::__construct([ + 'add' => ['admin:rw', 'assistenz:rw'], + 'delete' => ['admin:rw', 'assistenz:rw'], + 'getByLehreinheit' => ['admin:r', 'assistenz:r'], + ]); + + $this->_ci = &get_instance(); + + $this->loadPhrases([ + 'ui' + ]); + $this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel'); + $this->_ci->load->model('education/lehreinheit_model', 'LehreinheitModel'); + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + } + + public function add() + { + $uid = $this->input->post('uid'); + $lehreinheit_id = $this->input->post('lehreinheit_id'); + + $this->checkPermission($lehreinheit_id, $uid); + + $result = $this->_ci->LehreinheitgruppeModel->direktUserAdd($uid, $lehreinheit_id); + + if (isError($result)) + $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess($result); + } + + public function delete() + { + $uid = $this->input->post('uid'); + $lehreinheit_id = $this->input->post('lehreinheit_id'); + + $this->checkPermission($lehreinheit_id, $uid); + + $result = $this->_ci->LehreinheitgruppeModel->direktUserDelete($uid, $lehreinheit_id); + + if (isError($result)) + $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess($result); + } + + public function getByLehreinheit($lehreinheit_id = null) + { + $this->checkPermission($lehreinheit_id); + $gruppen = $this->_ci->LehreinheitgruppeModel->getDirectGroup($lehreinheit_id); + $this->terminateWithSuccess(hasData($gruppen) ? getData($gruppen) : array()); + } + + private function checkPermission($lehreinheit_id, $uid = false) + { + if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $lehreinheit_result = $this->_ci->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit_result) || isError($lehreinheit_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + if ($uid) + { + $benuzuer_result = $this->_ci->BenutzerModel->load(array($uid)); + if (!hasData($benuzuer_result) || isError($benuzuer_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + } + + $result = $this->_ci->LehreinheitModel->getOes($lehreinheit_id); + + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + $oe_array = $result; + + if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && + !$this->_ci->permissionlib->isBerechtigtMultipleOe('assistenz', $oe_array, 'suid')) + $this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess')); + } +} diff --git a/application/controllers/api/frontend/v1/lv/Favorites.php b/application/controllers/api/frontend/v1/lv/Favorites.php new file mode 100644 index 000000000..080a4ec6e --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/Favorites.php @@ -0,0 +1,47 @@ + self::PERM_LOGGED, + 'set' => self::PERM_LOGGED + ]); + + // Load models + $this->load->model('system/Variable_model', 'VariableModel'); + } + + public function index() + { + $result = $this->VariableModel->getVariables(getAuthUID(), ['lv_favorites']); + + $data = $this->getDataOrTerminateWithError($result); + + if (!$data) + $this->terminateWithSuccess(null); + else + $this->terminateWithSuccess(isset($data['lv_favorites']) ? $data['lv_favorites'] : null); + } + + public function set() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('favorites', 'Favorites', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $favorites = $this->input->post('favorites'); + + $result = $this->VariableModel->setVariable(getAuthUID(), 'lv_favorites', $favorites); + + $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(true); + } +} diff --git a/application/controllers/api/frontend/v1/lv/Gruppe.php b/application/controllers/api/frontend/v1/lv/Gruppe.php new file mode 100644 index 000000000..01c11f98f --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/Gruppe.php @@ -0,0 +1,189 @@ + ['admin:rw', 'assistenz:rw'], + 'delete' => ['admin:rw', 'assistenz:rw'], + 'deleteFromLVPlan' => ['admin:rw', 'assistenz:rw'], + 'getBenutzer' => ['admin:r', 'assistenz:r'], + 'getAll' => ['admin:r', 'assistenz:r'], + 'getByLehreinheit' => ['admin:r', 'assistenz:r'], + ]); + + $this->_ci = &get_instance(); + $this->_setAuthUID(); + $this->_ci->load->model('organisation/Gruppe_model', 'GruppeModel'); + $this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); + $this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel'); + $this->_ci->load->model('person/Person_model', 'PersonModel'); + $this->_ci->load->model('ressource/stundenplandev_model', 'StundenplandevModel'); + } + + public function delete() + { + $lehreinheitgruppe_id = $this->input->post('lehreinheitgruppe_id'); + $lehreinheit_id = $this->input->post('lehreinheit_id'); + + if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id) || is_null($lehreinheitgruppe_id) || !ctype_digit((string)$lehreinheitgruppe_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $lehreinheitgruppe_result = $this->_ci->LehreinheitgruppeModel->loadWhere(array('lehreinheitgruppe_id' => $lehreinheitgruppe_id)); + if (!hasData($lehreinheitgruppe_result) || isError($lehreinheitgruppe_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->checkPermission($lehreinheit_id); + + $result = $this->_ci->LehreinheitgruppeModel->deleteGroup($lehreinheit_id, $lehreinheitgruppe_id); + + if (isError($result)) + $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess($result); + } + + public function add() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $gid = $this->input->post('gid'); + $lehrverband = $this->input->post('lehrverband'); + + if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id) || is_null($gid) || !ctype_digit((string)$gid) || is_null($lehrverband)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $gruppe_result = $this->_ci->GruppeModel->loadWhere(array('gid' => $gid)); + if (!hasData($gruppe_result) || isError($gruppe_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->checkPermission($lehreinheit_id); + + $result = $this->_ci->LehreinheitgruppeModel->addGroup($lehreinheit_id, $gid, !($lehrverband === 'false')); + + if (isError($result)) + $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess($result); + } + + public function getByLehreinheit($lehreinheit_id = null) + { + if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->checkPermission($lehreinheit_id); + + $gruppen = $this->_ci->LehreinheitgruppeModel->getByLehreinheit($lehreinheit_id); + $this->terminateWithSuccess(hasData($gruppen) ? getData($gruppen) : array()); + } + + public function deleteFromLVPlan() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $lehreinheitgruppe_id = $this->input->post('lehreinheitgruppe_id'); + + if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id) || is_null($lehreinheitgruppe_id) || !ctype_digit((string)$lehreinheitgruppe_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $lehreinheitgruppe_result = $this->_ci->LehreinheitgruppeModel->loadWhere(array('lehreinheitgruppe_id' => $lehreinheitgruppe_id)); + if (!hasData($lehreinheitgruppe_result) || isError($lehreinheitgruppe_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->checkPermission($lehreinheit_id); + + $result = $this->_ci->StundenplandevModel->deleteGroupPlanning($lehreinheit_id, $lehreinheitgruppe_id); + + if (isError($result)) + $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess($result); + } + + + public function getAll() + { + $this->_ci->GruppeModel->addSelect('gruppe_kurzbz, + studiengang_kz, + semester, + bezeichnung, + gid, + \'false\' as lehrverband'); + $gruppen_result = $this->_ci->GruppeModel->loadWhere(array('sichtbar' => true, 'aktiv' => true, 'lehre' => true, 'direktinskription' => false)); + + $gruppen_array = array(); + + if (isError($gruppen_result)) + $this->terminateWithError(getError($gruppen_result), self::ERROR_TYPE_GENERAL); + + if (hasData($gruppen_result)) + $gruppen_array = getData($gruppen_result); + + $this->_ci->LehrverbandModel->addSelect('CONCAT(UPPER(CONCAT(typ, kurzbz)), \'\', semester, verband, COALESCE(gruppe,\'\')) as gruppe_kurzbz, + studiengang_kz, + semester, + tbl_lehrverband.bezeichnung, + gid, + \'true\' as lehrverband'); + $this->_ci->LehrverbandModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $this->_ci->LehrverbandModel->addOrder('verband'); + $this->_ci->LehrverbandModel->addOrder('gruppe'); + $lehrverband_result = $this->_ci->LehrverbandModel->loadWhere(array('tbl_lehrverband.aktiv' => true)); + + $lehrverband_array = array(); + + if (isError($lehrverband_result)) + $this->terminateWithError(getError($lehrverband_result), self::ERROR_TYPE_GENERAL); + + if (hasData($lehrverband_result)) + $lehrverband_array = getData($lehrverband_result); + + $all_gruppen = array_merge($gruppen_array, $lehrverband_array); + + $this->terminateWithSuccess($all_gruppen); + } + + public function getBenutzer() + { + $this->_ci->PersonModel->addSelect('vorname, nachname, uid, semester, UPPER(CONCAT(tbl_studiengang.typ, tbl_studiengang.kurzbz)) as studiengang'); + $this->_ci->PersonModel->addJoin('public.tbl_benutzer', 'person_id'); + $this->_ci->PersonModel->addJoin('public.tbl_mitarbeiter', 'uid = mitarbeiter_uid', 'LEFT'); + $this->_ci->PersonModel->addJoin('public.tbl_student', 'uid = student_uid', 'LEFT'); + $this->_ci->PersonModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT'); + + $personen = $this->_ci->PersonModel->loadWhere(array('tbl_benutzer.aktiv' => true)); + $this->terminateWithSuccess(hasData($personen) ? getData($personen) : array()); + } + + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) + show_error('User authentification failed'); + } + + private function checkPermission($lehreinheit_id) + { + $lehreinheit_result = $this->_ci->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit_result) || isError($lehreinheit_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $result = $this->_ci->LehreinheitModel->getOes($lehreinheit_id); + + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $oe_array = $result; + + if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && + !$this->_ci->permissionlib->isBerechtigtMultipleOe('assistenz', $oe_array, 'suid') && + !$this->_ci->permissionlib->isBerechtigtMultipleOe('lv-plan', $oe_array, 'suid')) + $this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess')); + } + +} diff --git a/application/controllers/api/frontend/v1/lv/Lehreinheit.php b/application/controllers/api/frontend/v1/lv/Lehreinheit.php new file mode 100644 index 000000000..84ee66d5d --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/Lehreinheit.php @@ -0,0 +1,438 @@ + ['admin:rw', 'assistenz:rw'], + 'copy' => ['admin:rw', 'assistenz:rw'], + 'delete' => ['admin:rw', 'assistenz:rw'], + 'update' => ['admin:rw', 'assistenz:rw'], + + 'get' => ['admin:r', 'assistenz:r'], + 'getStudiensemester' => ['admin:r', 'assistenz:r'], + 'getLehrfach' => ['admin:r', 'assistenz:r'], + 'getSprache' => ['admin:r', 'assistenz:r'], + 'getRaumtyp' => ['admin:r', 'assistenz:r'], + 'getLehrform' => ['admin:r', 'assistenz:r'] + ]); + + $this->_ci = &get_instance(); + $this->_setAuthUID(); + $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); + $this->_ci->load->library('PhrasesLib'); + $this->loadPhrases( + array( + 'global', + 'ui' + ) + ); + + $this->_ci->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel'); + $this->_ci->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + } + + public function get($lehreinheit_id) + { + $lehreinheit = $this->checkLehreinheit($lehreinheit_id); + $lehreinheit->lehrfaecher = $this->getLehrfaecher($lehreinheit); + $this->terminateWithSuccess($lehreinheit); + } + + private function getLehrfaecher($lehreinheit) + { + $lehrfacher_array = array($lehreinheit->lehrfach_id); + $this->_ci->LehreinheitModel->addSelect('lehrveranstaltung_id_kompatibel'); + $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung_kompatibel', 'lehrveranstaltung_id'); + $lehrfaecher = $this->_ci->LehreinheitModel->loadWhere(array('lehrveranstaltung_id' => $lehreinheit->lehrveranstaltung_id)); + + + if (hasData($lehrfaecher)) + $lehrfaecher_array = array_merge($lehrfacher_array, array_column(getData($lehrfaecher), 'lehrveranstaltung_id_kompatibel')); + + $lehrfaecher_array[] = $lehreinheit->lehrveranstaltung_id; + + $this->_ci->LehrveranstaltungModel->addDistinct('lehrfach_id'); + $this->_ci->LehrveranstaltungModel->addSelect("tbl_lehrveranstaltung.lehrveranstaltung_id, CONCAT(tbl_lehrveranstaltung.bezeichnung || '(' || tbl_lehrveranstaltung.oe_kurzbz || ')') as lehrfach"); + $this->_ci->LehrveranstaltungModel->db->where_in('tbl_lehrveranstaltung.lehrveranstaltung_id', $lehrfaecher_array); + $lehrfaecher_result = $this->_ci->LehrveranstaltungModel->load(); + + return hasData($lehrfaecher_result) ? getData($lehrfaecher_result) : array(); + } + + public function add() + { + $lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id'); + + if (is_null($lehrveranstaltung_id) || !ctype_digit((string)$lehrveranstaltung_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $lehrveranstaltung_result = $this->_ci->LehrveranstaltungModel->loadWhere(array('lehrveranstaltung_id' => $lehrveranstaltung_id)); + + if (!hasData($lehrveranstaltung_result) || isError($lehrveranstaltung_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $lehrveranstaltung = getData($lehrveranstaltung_result)[0]; + + $oe_result = $this->_ci->LehrveranstaltungModel->getAllOe($lehrveranstaltung->lehrveranstaltung_id, $lehrveranstaltung->studiengang_kz); + $oe_array = hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array(); + + if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && + !$this->_ci->permissionlib->isBerechtigtMultipleOe('assistenz', $oe_array, 'suid') && + !$this->_ci->permissionlib->isBerechtigtMultipleOe('lv-plan', $oe_array, 'suid')) + $this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess')); + + $this->_ci->load->library('form_validation'); + + $updatableFields = array( + 'lehrveranstaltung_id', + 'studiensemester_kurzbz', + 'lehrfach_id', + 'lehrform_kurzbz', + 'stundenblockung', + 'wochenrythmus', + 'gewicht', + 'start_kw', + 'raumtyp', + 'raumtypalternativ', + 'sprache', + 'lehre', + 'anmerkung', + 'lvnr', + 'unr', + ); + + foreach ($updatableFields as $field) + { + switch ($field) { + case 'lehrveranstaltung_id': + $this->form_validation->set_rules($field, 'Lehrveranstaltung ID', 'required|integer'); + break; + case 'studiensemester_kurzbz': + $this->form_validation->set_rules($field, 'Studiensemester', 'required|max_length[16]'); + break; + case 'lehrfach_id': + $this->form_validation->set_rules($field, 'Lehrfach ID', 'required|integer'); + break; + case 'lehrform_kurzbz': + $this->form_validation->set_rules($field, 'Lehrform', 'required|max_length[8]'); + break; + case 'stundenblockung': + $this->form_validation->set_rules($field, 'Stundenblockung', 'required|integer|greater_than_equal_to[0]'); + break; + case 'wochenrythmus': + $this->form_validation->set_rules($field, 'Wochenrhytmus', 'required|integer|greater_than_equal_to[0]'); + break; + case 'start_kw': + $this->form_validation->set_rules($field, 'Start KW', 'integer|greater_than[0]|less_than_equal_to[53]'); + break; + case 'gewicht': + $this->form_validation->set_rules($field, 'Gewicht', 'numeric'); + break; + case 'raumtyp': + $this->form_validation->set_rules($field, 'Raumtyp', 'required|max_length[16]'); + break; + case 'raumtypalternativ': + $this->form_validation->set_rules($field, 'Raumtyp Alternativ', 'required|max_length[16]'); + break; + case 'sprache': + $this->form_validation->set_rules($field, 'Sprache', 'required|max_length[16]'); + break; + case 'lvnr': + $this->form_validation->set_rules($field, 'LVNR', 'integer'); + break; + case 'unr': + $this->form_validation->set_rules($field, 'UNR', 'integer'); + break; + case 'lehre': + $this->form_validation->set_rules($field, 'Lehre', 'trim'); + break; + case 'anmerkung': + $this->form_validation->set_rules($field, 'Anmerkung', 'trim'); + break; + } + } + + if ($this->form_validation->run() === false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + + $updateData = array(); + foreach ($updatableFields as $field) + { + $value = $this->input->post($field); + + if ($value !== null) + { + $updateData[$field] = $value; + } + } + + $updateData['insertvon'] = $this->_uid; + $updateData['insertamum'] = date('Y-m-d H:i:s'); + + $result = $this->_ci->LehreinheitModel->insert( + $updateData + ); + + $this->terminateWithSuccess($result); + } + + public function copy() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $art = $this->input->post('art'); + + $lehreinheit_old = $this->checkLehreinheit($lehreinheit_id); + $this->checkPermission($lehreinheit_old->lehreinheit_id); + + $lehreinheit_new = $lehreinheit_old; + + $lehreinheit_new->unr = null; + unset($lehreinheit_new->lehreinheit_id); + $lehreinheit_new->updateamum = date('Y-m-d H:i:s'); + $lehreinheit_new->updatevon = $this->_uid; + $lehreinheit_new->insertamum = date('Y-m-d H:i:s'); + $lehreinheit_new->insertvon = $this->_uid; + + $insert_result = $this->_ci->LehreinheitModel->insert($lehreinheit_new); + + if (isError($insert_result)) + $this->terminateWithError(getError($insert_result), self::ERROR_TYPE_GENERAL); + + $lehreinheit_id_new = getData($insert_result); + + if (in_array($art, array('gruppen', 'alle'))) + { + $gruppen_result = $this->_ci->LehreinheitgruppeModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + + if (isError($gruppen_result)) + $this->terminateWithError(getError($gruppen_result), self::ERROR_TYPE_GENERAL); + + if (hasData($gruppen_result)) + { + $gruppen = getData($gruppen_result); + + foreach ($gruppen as $gruppe) + { + $gruppe_new = $gruppe; + unset($gruppe_new->lehreinheitgruppe_id); + $gruppe_new->lehreinheit_id = $lehreinheit_id_new; + $gruppe_new->insertamum = date('Y-m-d H:i:s'); + $gruppe_new->insertvon = $this->_uid; + $gruppe_new->updateamum = date('Y-m-d H:i:s'); + $gruppe_new->updatevon = $this->_uid; + + $gruppe_new_result = $this->_ci->LehreinheitgruppeModel->insert($gruppe_new); + + if (isError($gruppe_new_result)) + $this->terminateWithError(getError($gruppe_new_result), self::ERROR_TYPE_GENERAL); + } + } + } + + if (in_array($art, array('lektoren', 'alle'))) + { + $lektoren_result = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + + if (isError($lektoren_result)) + $this->terminateWithError(getError($lektoren_result), self::ERROR_TYPE_GENERAL); + + if (hasData($lektoren_result)) + { + $lektoren = getData($lektoren_result); + + foreach ($lektoren as $lektor) + { + + $lektor_new = $lektor; + $lektor_new->lehreinheit_id = $lehreinheit_id_new; + $lektor_new->insertamum = date('Y-m-d H:i:s'); + $lektor_new->insertvon = $this->_uid; + $lektor_new->updateamum = date('Y-m-d H:i:s'); + $lektor_new->updatevon = $this->_uid; + unset($lektor_new->vertrag_id); + + $lektor_new_result = $this->_ci->LehreinheitmitarbeiterModel->insert((array)$lektor_new); + + if (isError($lektor_new_result)) + $this->terminateWithError(getError($lektor_new_result), self::ERROR_TYPE_GENERAL); + } + } + } + + $this->terminateWithSuccess("Erfolgeich gespeichert"); + } + + public function delete() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $lehreinheit = $this->checkLehreinheit($lehreinheit_id); + $this->checkPermission($lehreinheit->lehreinheit_id); + + $result = $this->_ci->LehreinheitModel->deleteLehreinheit($lehreinheit->lehreinheit_id); + + if (isError($result)) + $this->terminateWithValidationErrors(getError($result)); + + $this->terminateWithSuccess('Erfolgreich geloescht'); + } + + public function update() + { + $lehreinheit = $this->checkLehreinheit($this->input->post('lehreinheit_id')); + + $this->checkPermission($lehreinheit->lehreinheit_id); + + $this->_ci->load->library('form_validation'); + + $formData = $this->input->post('formData'); + + $updatableFields = array( + 'lehrveranstaltung_id', + 'studiensemester_kurzbz', + 'lehrfach_id', + 'lehrform_kurzbz', + 'stundenblockung', + 'wochenrythmus', + 'gewicht', + 'start_kw', + 'raumtyp', + 'raumtypalternativ', + 'sprache', + 'lehre', + 'anmerkung', + 'lvnr', + 'unr', + ); + + $this->form_validation->set_data($formData); + + foreach ($updatableFields as $field) + { + if (array_key_exists($field, $formData)) + { + switch ($field) + { + case 'lehrveranstaltung_id': + $this->form_validation->set_rules($field, 'Lehrveranstaltung ID', 'required|integer'); + break; + case 'studiensemester_kurzbz': + $this->form_validation->set_rules($field, 'Studiensemester', 'required|max_length[16]'); + break; + case 'lehrfach_id': + $this->form_validation->set_rules($field, 'Lehrfach ID', 'required|integer'); + break; + case 'lehrform_kurzbz': + $this->form_validation->set_rules($field, 'Lehrform', 'required|max_length[8]'); + break; + case 'stundenblockung': + $this->form_validation->set_rules($field, 'Stundenblockung', 'required|integer|greater_than_equal_to[0]'); + break; + case 'wochenrythmus': + $this->form_validation->set_rules($field, 'Wochenrhytmus', 'required|integer|greater_than_equal_to[0]'); + break; + case 'start_kw': + $this->form_validation->set_rules($field, 'Start KW', 'integer|greater_than[0]|less_than_equal_to[53]'); + break; + case 'gewicht': + $this->form_validation->set_rules($field, 'Gewicht', 'numeric'); + break; + case 'raumtyp': + $this->form_validation->set_rules($field, 'Raumtyp', 'required|max_length[16]'); + break; + case 'raumtypalternativ': + $this->form_validation->set_rules($field, 'Raumtyp Alternativ', 'required|max_length[16]'); + break; + case 'sprache': + $this->form_validation->set_rules($field, 'Sprache', 'required|max_length[16]'); + break; + case 'lvnr': + $this->form_validation->set_rules($field, 'LVNR', 'integer'); + break; + case 'unr': + $this->form_validation->set_rules($field, 'UNR', 'integer'); + break; + case 'lehre': + $this->form_validation->set_rules($field, 'Lehre', 'trim'); + break; + case 'anmerkung': + $this->form_validation->set_rules($field, 'Anmerkung', 'trim'); + break; + } + } + } + + if ($this->form_validation->run() === false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $updateData = []; + foreach ($updatableFields as $field) + { + if (array_key_exists($field, $formData)) + { + $updateData[$field] = $formData[$field]; + } + } + + + $updateData['updatevon'] = $this->_uid; + $updateData['updateamum'] = date('Y-m-d H:i:s'); + $result = $this->_ci->LehreinheitModel->update( + [ + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + ], + $updateData + ); + + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $this->terminateWithSuccess($this->p->t('global', 'gespeichert')); + } + + + private function checkPermission($lehreinheit_id) + { + $result = $this->_ci->LehreinheitModel->getOes($lehreinheit_id); + + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + $oe_array = $result; + + if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && + !$this->_ci->permissionlib->isBerechtigtMultipleOe('assistenz', $oe_array, 'suid') && + !$this->_ci->permissionlib->isBerechtigtMultipleOe('lv-plan', $oe_array, 'suid')) + $this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess')); + } + private function checkLehreinheit($lehreinheit_id) + { + if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $lehreinheit_result = $this->_ci->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit_result) || isError($lehreinheit_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + return getData($lehreinheit_result)[0]; + } + + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) + show_error('User authentification failed'); + } +} diff --git a/application/controllers/api/frontend/v1/lv/Lektor.php b/application/controllers/api/frontend/v1/lv/Lektor.php new file mode 100644 index 000000000..332bc47b6 --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/Lektor.php @@ -0,0 +1,380 @@ + ['admin:rw', 'assistenz:rw'], + 'update' => ['admin:rw', 'assistenz:rw'], + 'cancelVertrag' => ['admin:rw', 'assistenz:rw'], + 'deleteLVPlan' => ['admin:rw', 'assistenz:rw'], + 'deletePerson' => ['admin:rw', 'assistenz:rw'], + 'getLehrfunktionen' => ['admin:r', 'assistenz:r'], + 'getLektoren' => ['admin:r', 'assistenz:r'], + 'getLektorenByLE' => ['admin:r', 'assistenz:r'], + 'getLektorDaten' => ['admin:r', 'assistenz:r'], + 'getLektorVertrag' => ['admin:r', 'assistenz:r'], + + ]); + + $this->_ci = &get_instance(); + $this->_setAuthUID(); + $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); + $this->_ci->load->library('PermissionLib'); + $this->_ci->load->library('LektorLib'); + $this->_ci->load->library('form_validation'); + $this->loadPhrases([ + 'ui' + ]); + + $this->_ci->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->_ci->load->model('education/lehreinheit_model', 'LehreinheitModel'); + $this->_ci->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + $this->_ci->load->model('ressource/stundenplandev_model', 'StundenplandevModel'); + $this->_ci->load->model('ressource/Stundensatz_model', 'StundensatzModel'); + + } + + private function checkMitarbeiter($mitarbeiter_uid) + { + if (is_null($mitarbeiter_uid)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $mitarbeiter_result = $this->_ci->MitarbeiterModel->load($mitarbeiter_uid); + + if (!hasData($mitarbeiter_result) || isError($mitarbeiter_result)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + } + + public function add() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $mitarbeiter_uid = $this->input->post('mitarbeiter_uid'); + + $this->checkLehreinheit($lehreinheit_id); + $this->checkMitarbeiter($mitarbeiter_uid); + $lehrfach_permission = $this->checkLehrfachPermission($lehreinheit_id, array('assistenz', 'admin')); + $lehreinheit_permission = $this->checkPermission($lehreinheit_id, array('admin', 'assistenz', 'lv-plan')); + + if (!$lehrfach_permission && !$lehreinheit_permission) + $this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess')); + + $result = $this->_ci->lektorlib->addLektorToLehreinheit($lehreinheit_id, $mitarbeiter_uid); + + if (isError($result)) $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess("Erfolgreich gespeichert"); + } + + public function update() + { + $formData = $this->input->post('formData'); + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $mitarbeiter_uid = $this->input->post('mitarbeiter_uid'); + + $this->checkLehreinheit($lehreinheit_id); + $this->checkMitarbeiter($mitarbeiter_uid); + + $updatableFields = array( + 'lehrfunktion_kurzbz', + 'planstunden', + 'stundensatz', + 'faktor', + 'anmerkung', + 'bismelden', + 'semesterstunden', + 'mitarbeiter_uid' + ); + + $this->form_validation->set_data($formData); + + foreach ($updatableFields as $field) + { + if (array_key_exists($field, $formData)) + { + switch ($field) + { + case 'lehrfunktion_kurzbz': + $this->form_validation->set_rules($field, 'Lehrfunktion', 'required|max_length[16]'); + break; + case 'planstunden': + $this->form_validation->set_rules($field, 'Planstunden', 'integer|greater_than_equal_to[0]'); + break; + case 'stundensatz': + $this->form_validation->set_rules($field, 'Stundensatz', 'numeric|greater_than_equal_to[0]'); + break; + case 'faktor': + $this->form_validation->set_rules($field, 'Faktor', 'numeric|greater_than_equal_to[0]'); + break; + case 'anmerkung': + $this->form_validation->set_rules($field, 'Anmerkung', 'max_length[256]'); + break; + case 'bismelden': + $this->form_validation->set_rules($field, 'Bis Melden', 'trim'); + break; + case 'semesterstunden': + $this->form_validation->set_rules($field, 'Semesterstunden', 'callback__check_semesterstunden'); + break; + case 'mitarbeiter_uid': + $this->form_validation->set_rules($field, 'Semesterstunden', 'required|max_length[32]'); + break; + } + } + } + if (!$this->form_validation->run()) + { + $this->terminateWithError($this->form_validation->error_array()); + } + + if (isset($formData['semesterstunden']) && (!is_numeric($formData['semesterstunden']) || $formData['semesterstunden'] === '')) + { + $formData['semesterstunden'] = null; + } + + $lehreinheit_permission = $this->checkPermission($lehreinheit_id, array('admin', 'assistenz', 'lv-plan')); + + if (!$lehreinheit_permission) + $this->terminateWithError($this->p->t('ui', 'error_fieldWriteAccess')); + + $result = $this->_ci->lektorlib->updateLektorFromLehreinheit($lehreinheit_id, $mitarbeiter_uid, $formData); + + if (isError($result)) $this->terminateWithError(getError($result)); + $this->terminateWithSuccess("Erfolgreich geupdated"); + } + + public function _check_semesterstunden($value) + { + if ($value === null || $value === '') { + return true; + } + + if (!is_numeric($value)) + { + $this->form_validation->set_message( + '_check_semesterstunden', + 'Das Feld {field} muss eine Zahl sein.' + ); + return false; + } + + if ($value < 0) + { + $this->form_validation->set_message( + '_check_semesterstunden', + 'Das Feld {field} muss eine Zahl größer oder gleich 0 sein.' + ); + return false; + } + + return true; + } + public function getLehrfunktionen() + { + $this->_ci->load->model('education/Lehrfunktion_model', 'LehrfunktionModel'); + $this->_ci->LehrfunktionModel->addOrder('lehrfunktion_kurzbz'); + $this->terminateWithSuccess(getData($this->_ci->LehrfunktionModel->load())); + } + + public function getLektoren() + { + $this->_ci->MitarbeiterModel->addSelect('uid, person_id, vorname, nachname'); + $this->_ci->MitarbeiterModel->addJoin('public.tbl_benutzer', 'uid = mitarbeiter_uid'); + $this->_ci->MitarbeiterModel->addJoin('public.tbl_person', 'person_id'); + $this->terminateWithSuccess(getData($this->_ci->MitarbeiterModel->loadWhere(array('public.tbl_benutzer.aktiv' => true)))); + } + + private function checkLehreinheit($lehreinheit_id) + { + if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $lehreinheit_result = $this->_ci->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit_result) || isError($lehreinheit_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + return getData($lehreinheit_result)[0]; + + } + public function getLektorenByLE($lehreinheit_id = null) + { + $this->checkLehreinheit($lehreinheit_id); + $le_mitarbeiter_data = $this->_ci->LehreinheitmitarbeiterModel->getLektorenByLe($lehreinheit_id); + $this->terminateWithSuccess(hasData($le_mitarbeiter_data) ? getData($le_mitarbeiter_data) : array()); + } + + public function getLektorDaten($lehreinheit_id = null, $mitarbeiter_uid = null) + { + $lehreinheit = $this->checkLehreinheit($lehreinheit_id); + + if (is_null($mitarbeiter_uid)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $mitarbeiter_result = $this->_ci->MitarbeiterModel->load($mitarbeiter_uid); + + if (!hasData($mitarbeiter_result) || isError($mitarbeiter_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->load->model('organisation/Studiensemester_model','StudiensemesterModel'); + $studiensemester_result = $this->_ci->StudiensemesterModel->loadWhere(array('studiensemester_kurzbz' => $lehreinheit->studiensemester_kurzbz)); + $studiensemester = getData($studiensemester_result)[0]; + + $defaultStundensatz = $this->_ci->StundensatzModel->getDefaultStundensatz($mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre'); + + $le_mitarbeiter_result = $this->_ci->LehreinheitmitarbeiterModel->getByLeLektor($lehreinheit_id, $mitarbeiter_uid); + + $le_mitarbeiter_data = array(); + if (hasData($le_mitarbeiter_result)) + { + $le_mitarbeiter_data = getData($le_mitarbeiter_result)[0]; + $le_mitarbeiter_data->default_stundensatz = $defaultStundensatz; + } + $vertrag = $this->getLektorVertrag($lehreinheit_id, $mitarbeiter_uid); + $le_mitarbeiter_data->vertrag = $vertrag; + $this->terminateWithSuccess($le_mitarbeiter_data); + } + + private function getLektorVertrag($lehreinheit_id = null, $mitarbeiter_uid = null) + { + $this->_ci->load->model('accounting/Vertrag_model', 'VertragModel'); + $vertrag = $this->_ci->VertragModel->getVertrag($mitarbeiter_uid, $lehreinheit_id); + return hasData($vertrag) ? getData($vertrag)[0] : null; + } + + private function checkLehrfachPermission($lehreinheit_id, $permissions) + { + $lehrfach_oe_kurzbz = $this->_ci->LehreinheitModel->getLehrfachOe($lehreinheit_id); + + if (isError($lehrfach_oe_kurzbz)) + $this->terminateWithError(getError($lehrfach_oe_kurzbz), self::ERROR_TYPE_GENERAL); + + $lehrfach_oe_kurzbz = array(''); + if (hasData($lehrfach_oe_kurzbz)) + $lehrfach_oe_kurzbz = array_column(getData($lehrfach_oe_kurzbz), 'oe_kurzbz'); + + + return $this->checkPermissionGenerel($permissions, $lehrfach_oe_kurzbz); + } + + private function checkPermissionGenerel($permissions, $oe_array) + { + $hasPermission = false; + foreach ($permissions as $permission) + { + if ($this->_ci->permissionlib->isBerechtigtMultipleOe($permission, $oe_array, 'suid')) + { + $hasPermission = true; + break; + } + } + + return $hasPermission; + } + + private function checkPermission($lehreinheit_id, $permissions) + { + $result = $this->_ci->LehreinheitModel->getOes($lehreinheit_id); + + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + $oe_array = $result; + + return $this->checkPermissionGenerel($permissions, $oe_array); + } + public function cancelVertrag() + { + $vertrag_id = $this->input->post('vertrag_id'); + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $mitarbeiter_uid = $this->input->post('mitarbeiter_uid'); + + $this->checkLehreinheit($lehreinheit_id); + $this->checkPermission($lehreinheit_id, array('admin', 'lehre/lehrauftrag_bestellen')); + + if (is_null($vertrag_id) || !ctype_digit((string)$vertrag_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $vertrag_result = $this->_ci->VertragModel->load($vertrag_id); + + if (!hasData($vertrag_result) || isError($vertrag_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + if (is_null($mitarbeiter_uid)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $mitarbeiter_result = $this->_ci->MitarbeiterModel->load($mitarbeiter_uid); + + if (!hasData($mitarbeiter_result) || isError($mitarbeiter_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $result = $this->_ci->VertragModel->cancelVertrag($vertrag_id, $mitarbeiter_uid); + + if (isError($result)) + $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess($result); + } + + public function deletePerson() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $mitarbeiter_uid = $this->input->post('mitarbeiter_uid'); + + $this->checkLehreinheit($lehreinheit_id); + $this->checkPermission($lehreinheit_id, array('admin', 'assistenz', 'lv-plan')); + + if (is_null($mitarbeiter_uid)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $mitarbeiter_result = $this->_ci->MitarbeiterModel->load($mitarbeiter_uid); + + if (!hasData($mitarbeiter_result) || isError($mitarbeiter_result)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $delete_result =$this->_ci->LehreinheitmitarbeiterModel->deleteLektorFromLe($lehreinheit_id, $mitarbeiter_uid); + + if (isError($delete_result)) + $this->terminateWithError(getError($delete_result)); + + $this->terminateWithSuccess($delete_result); + } + + public function deleteLVPlan() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $mitarbeiter_uid = $this->input->post('mitarbeiter_uid'); + + $this->checkLehreinheit($lehreinheit_id); + $this->checkPermission($lehreinheit_id, array('lv-plan/lektorentfernen')); + + if (is_null($mitarbeiter_uid)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $mitarbeiter_result = $this->_ci->MitarbeiterModel->load($mitarbeiter_uid); + + if (!hasData($mitarbeiter_result) || isError($mitarbeiter_result)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + + $delete_result = $this->_ci->StundenplandevModel->deleteLektorPlanning($lehreinheit_id, $mitarbeiter_uid); + + if (isError($delete_result)) + $this->terminateWithError(getError($delete_result)); + + $this->terminateWithSuccess($delete_result); + } + + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) + show_error('User authentification failed'); + } +} diff --git a/application/controllers/api/frontend/v1/lv/Setup.php b/application/controllers/api/frontend/v1/lv/Setup.php new file mode 100644 index 000000000..cf73697a7 --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/Setup.php @@ -0,0 +1,116 @@ +. + */ + +if (!defined('BASEPATH')) + exit('No direct script access allowed'); + +class Setup extends FHCAPI_Controller +{ + private $_ci; + private $_uid; + + public function __construct() + { + parent::__construct([ + 'getTabs' => ['admin:r', 'assistenz:r'], + 'getStudiensemester' => ['admin:r', 'assistenz:r'], + 'getSprache' => ['admin:r', 'assistenz:r'], + 'getRaumtyp' => ['admin:r', 'assistenz:r'], + 'getLehrform' => ['admin:r', 'assistenz:r'], + ]); + + $this->_ci = &get_instance(); + $this->_setAuthUID(); + + $this->_ci->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); + } + + public function getTabs() + { + $tabs['details'] = array ( + 'title' => 'Details', + 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Details.js', + 'config' => [] + ); + $tabs['lektor'] = array ( + 'title' => 'LektorInnenzuteilung', + 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Lektor.js', + 'config' => [] + ); + $tabs['notiz'] = array ( + 'title' => 'Notizen', + 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Notiz.js', + 'config' => [] + ); + $this->terminateWithSuccess($tabs); + } + + public function getStudiensemester() + { + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->_ci->StudiensemesterModel->addOrder('start', 'DESC'); + $this->terminateWithSuccess(getData($this->_ci->StudiensemesterModel->load())); + } + public function getSprache() + { + $this->_ci->load->model('system/Sprache_model', 'SpracheModel'); + $this->terminateWithSuccess(getData($this->_ci->SpracheModel->load())); + } + + public function getRaumtyp() + { + $this->_ci->load->model('ressource/Raumtyp_model', 'RaumtypModel'); + $this->_ci->RaumtypModel->addOrder('raumtyp_kurzbz'); + $this->terminateWithSuccess(getData($this->_ci->RaumtypModel->loadWhere(array('aktiv' => true)))); + } + + public function getLehrform() + { + $language = $this->_getLanguageIndex(); + + $this->_ci->load->model('codex/lehrform_model', 'LehrformModel'); + + $this->_ci->LehrformModel->addSelect( + '*, + bezeichnung_kurz[('.$language.')] as bez_kurz, + bezeichnung_lang[('.$language.')] as bez + ' + ); + $this->terminateWithSuccess(getData($this->_ci->LehrformModel->load())); + } + + private function _getLanguageIndex() + { + $this->_ci->load->model('system/Sprache_model', 'SpracheModel'); + $this->_ci->SpracheModel->addSelect('index'); + $result = $this->_ci->SpracheModel->loadWhere(array('sprache' => getUserLanguage())); + + return hasData($result) ? getData($result)[0]->index : 1; + } + + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) + show_error('User authentification failed'); + } +} diff --git a/application/controllers/api/frontend/v1/lv/StgTree.php b/application/controllers/api/frontend/v1/lv/StgTree.php new file mode 100644 index 000000000..fe3047902 --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/StgTree.php @@ -0,0 +1,91 @@ +method] = ['admin:r', 'assistenz:r']; + parent::__construct($permissions); + + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + } + + public function _remap($method, $params = []) + { + if ($method == '' || $method == 'index') + return $this->getBase(); + + if (!$this->permissionlib->isBerechtigt('assistenz', 's', $method) + && !$this->permissionlib->isBerechtigt('admin', 's', $method) + ) { + return $this->_outputAuthError([$method => ['admin:r', 'assistenz:r']]); + } + + return $this->getStudiengang($method); + show_404(); + } + + protected function getBase() + { + $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz'); + + $this->StudiengangModel->addDistinct(); + $this->StudiengangModel->addSelect("v.studiengang_kz AS link"); + $this->StudiengangModel->addSelect( + "CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name", + false + ); + $this->StudiengangModel->addSelect('erhalter_kz'); + $this->StudiengangModel->addSelect('typ'); + $this->StudiengangModel->addSelect('kurzbz'); + $this->StudiengangModel->addSelect('studiengang_kz'); + $this->StudiengangModel->addSelect('studiengang_kz AS stg_kz'); + + $this->StudiengangModel->addOrder('erhalter_kz'); + $this->StudiengangModel->addOrder('typ'); + $this->StudiengangModel->addOrder('kurzbz'); + + $stgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: []; + $stgs = array_merge($stgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []); + + if (!$stgs) + $this->terminateWithSuccess([]); + + $this->StudiengangModel->db->where_in('studiengang_kz', $stgs); + + $result = $this->StudiengangModel->loadWhere(['v.aktiv' => true]); + + $list = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($list); + } + + protected function getStudiengang($studiengang_kz) + { + $link = $studiengang_kz . '/'; + + $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz'); + + $this->StudiengangModel->addDistinct(); + $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false); + $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester ORDER BY verband, gruppe LIMIT 1)) AS name", false); + $this->StudiengangModel->addSelect("TRUE AS leaf", false); + + $this->StudiengangModel->addSelect('semester'); + $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false); + + $this->StudiengangModel->addOrder('semester'); + + $result = $this->StudiengangModel->loadWhere([ + 'v.studiengang_kz' => $studiengang_kz, + 'v.aktiv' => true + ]); + $list = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($list); + } +} diff --git a/application/controllers/api/frontend/v1/lv/Tags.php b/application/controllers/api/frontend/v1/lv/Tags.php new file mode 100644 index 000000000..234ab3cba --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/Tags.php @@ -0,0 +1,24 @@ + self::BERECHTIGUNG_KURZBZ, + 'getTags' => self::BERECHTIGUNG_KURZBZ, + 'addTag' => self::BERECHTIGUNG_KURZBZ, + 'updateTag' => self::BERECHTIGUNG_KURZBZ, + 'doneTag' => self::BERECHTIGUNG_KURZBZ, + 'deleteTag' => self::BERECHTIGUNG_KURZBZ, + 'updateLehre' => self::BERECHTIGUNG_KURZBZ, + 'doneLehre' => self::BERECHTIGUNG_KURZBZ, + 'deleteLehre' => self::BERECHTIGUNG_KURZBZ, + ]); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php b/application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php new file mode 100644 index 000000000..f8e1f816b --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php @@ -0,0 +1,21 @@ + ['admin:r', 'assistenz:r'], + 'getNotizen' => ['admin:r', 'assistenz:r'], + 'loadNotiz' => ['admin:r', 'assistenz:r'], + 'addNewNotiz' => ['admin:rw', 'assistenz:rw'], + 'updateNotiz' => ['admin:rw', 'assistenz:rw'], + 'deleteNotiz' => ['admin:rw', 'assistenz:rw'], + 'loadDokumente' => ['admin:r', 'assistenz:r'], + 'getMitarbeiter' => ['admin:r', 'assistenz:r'], + 'isBerechtigt' => ['admin:r', 'assistenz:r'], + ]); + } +} \ No newline at end of file diff --git a/application/libraries/LektorLib.php b/application/libraries/LektorLib.php new file mode 100644 index 000000000..44c71cdaa --- /dev/null +++ b/application/libraries/LektorLib.php @@ -0,0 +1,342 @@ +_ci =& get_instance(); + $this->_ci->load->model('education/lehreinheit_model', 'LehreinheitModel'); + $this->_ci->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + $this->_ci->load->model('organisation/Studiensemester_model','StudiensemesterModel'); + $this->_ci->load->model('ressource/Stundensatz_model', 'StundensatzModel'); + $this->_ci->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel'); + $this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $this->_ci->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + } + + public function addLektorToLehreinheit($lehreinheit_id, $mitarbeiter_uid) + { + $this->_ci->LehreinheitModel->addSelect('tbl_lehreinheit.*, tbl_lehrveranstaltung.studiengang_kz, semesterstunden'); + $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); + $lehreinheit_result = $this->_ci->LehreinheitModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + + if (isError($lehreinheit_result)) return $lehreinheit_result; + + if (!hasData($lehreinheit_result)) return error("Lehreinheit not found"); + + $lehreinheit = getData($lehreinheit_result)[0]; + + $already_assigned = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit->lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + + if (isError($already_assigned)) return $already_assigned; + + if (hasData($already_assigned)) return error('Lektor already assigned'); + + $studiensemester_result = $this->_ci->StudiensemesterModel->loadWhere(array('studiensemester_kurzbz' => $lehreinheit->studiensemester_kurzbz)); + if (isError($studiensemester_result)) return $studiensemester_result; + $studiensemester = getData($studiensemester_result)[0]; + + $stundensatz = $this->_ci->StundensatzModel->getDefaultStundensatz($mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre'); + $echter_dv_result = $this->_ci->DienstverhaeltnisModel->existsDienstverhaeltnis($mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'echterdv'); + + $echter_dv = false; + + if (hasData($echter_dv_result)) + { + $echter_dv = true; + } + + $maxstunden = $this->getMaxStunden($mitarbeiter_uid, $studiensemester->studiensemester_kurzbz, $lehreinheit->studiengang_kz, $echter_dv); + + $newData['semesterstunden'] = 0; + $newData['planstunden'] = 0; + if (!is_null($lehreinheit->semesterstunden)) + { + $newData['semesterstunden'] = min($lehreinheit->semesterstunden, $maxstunden); + $newData['planstunden'] = min($lehreinheit->semesterstunden, $maxstunden); + } + + $newData['lehreinheit_id'] = $lehreinheit->lehreinheit_id; + $newData['mitarbeiter_uid'] = $mitarbeiter_uid; + $newData['lehrfunktion_kurzbz'] = 'Lektor'; + $newData['bismelden'] = true; + $newData['insertvon'] = getAuthUID(); + $newData['insertamum'] = date('Y-m-d H:i:s'); + $newData['stundensatz'] = $stundensatz; + $result = $this->_ci->LehreinheitmitarbeiterModel->insert($newData); + + if (isError($result)) return $result; + + return success("Lektor added successfully"); + } + + public function updateLektorFromLehreinheit($lehreinheit_id, $mitarbeiter_uid, $new_data) + { + $this->_ci->LehreinheitmitarbeiterModel->addSelect('lehre.tbl_lehreinheitmitarbeiter.*, lehre.tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.studiengang_kz'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); + $lehreinheit_result = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + + if (isError($lehreinheit_result)) return $lehreinheit_result; + + if (!hasData($lehreinheit_result)) return error("Lehreinheit not found"); + + $lehreinheit = getData($lehreinheit_result)[0]; + + //TODO kollision check, wird vorerst nicht implementiert -> nur über das FAS möglich + if (isset($new_data['mitarbeiter_uid']) && $new_data['mitarbeiter_uid'] !== $mitarbeiter_uid) + { + $this->_ci->load->model('ressource/stundenplandev_model', 'StundenplandevModel'); + $this->_ci->StundenplandevModel->addGroupBy('stundenplandev_id'); + $this->_ci->StundenplandevModel->addGroupBy('mitarbeiter_uid'); + $this->_ci->StundenplandevModel->addGroupBy('mitarbeiter_uid'); + $verplant = $this->_ci->StundenplandevModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + + if (hasData($verplant)) + return error('Wechsel vom Mitarbeiter nicht möglich da er bereits verplant ist!'); + } + $warning = ''; + if (isset($new_data['semesterstunden'])) + { + $studiengang_result = $this->_ci->StudiengangModel->loadWhere(array('studiengang_kz' => $lehreinheit->studiengang_kz)); + if (isError($studiengang_result)) return $studiengang_result; + if (!hasData($studiengang_result)) return error('Studiengang not found'); + $studiengang = getData($studiengang_result)[0]; + + $studiensemester_result = $this->_ci->StudiensemesterModel->loadWhere(array('studiensemester_kurzbz' => $lehreinheit->studiensemester_kurzbz)); + if (isError($studiensemester_result)) return $studiensemester_result; + $studiensemester = getData($studiensemester_result)[0]; + + $echter_dv_result = $this->_ci->DienstverhaeltnisModel->existsDienstverhaeltnis($mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'echterdv'); + + $echter_dv = false; + + if (hasData($echter_dv_result)) + { + $echter_dv = true; + } + + $neue_stunden_eingerechnet = isset($new_data['bismelden']) ? $new_data['bismelden'] : $lehreinheit->bismelden; + $alte_stunden_eingerechnet = $lehreinheit->bismelden; + + if (($new_data['semesterstunden'] > $lehreinheit->semesterstunden) || $neue_stunden_eingerechnet) + { + $stundengrenze_result = $this->_ci->OrganisationseinheitModel->getStundengrenze($studiengang->oe_kurzbz, $echter_dv); + if (isError($stundengrenze_result)) return $stundengrenze_result; + + $stundengrenze = getData($stundengrenze_result)[0]; + + $oe_result = $this->_ci->OrganisationseinheitModel->getChilds($stundengrenze->oe_kurzbz); + $oe_array = hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array(''); + + if ($alte_stunden_eingerechnet && $neue_stunden_eingerechnet) + $this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) - ($lehreinheit->semesterstunden) + {$this->_ci->LehreinheitmitarbeiterModel->db->escape($new_data['semesterstunden'])}) as summe"); + else if ($alte_stunden_eingerechnet && !$neue_stunden_eingerechnet) + $this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) - ($lehreinheit->semesterstunden)) as summe"); + else if (!$alte_stunden_eingerechnet && $neue_stunden_eingerechnet) + $this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden) + ({$this->_ci->LehreinheitmitarbeiterModel->db->escape($new_data['semesterstunden'])})) as summe"); + else if (!$alte_stunden_eingerechnet && !$neue_stunden_eingerechnet) + $this->_ci->LehreinheitmitarbeiterModel->addSelect("(SUM(tbl_lehreinheitmitarbeiter.semesterstunden)) as summe"); + + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + + $this->_ci->LehreinheitmitarbeiterModel->db->where('mitarbeiter_uid', (isset($new_data['mitarbeiter_uid']) ? $new_data['mitarbeiter_uid'] : $mitarbeiter_uid)); + $this->_ci->LehreinheitmitarbeiterModel->db->where('studiensemester_kurzbz', $lehreinheit->studiensemester_kurzbz); + $this->_ci->LehreinheitmitarbeiterModel->db->where('bismelden', true); + $this->_ci->LehreinheitmitarbeiterModel->db->where('lower(mitarbeiter_uid) NOT LIKE', '_dummy%'); + + $this->_ci->LehreinheitmitarbeiterModel->db->where_in('tbl_studiengang.oe_kurzbz', $oe_array); + + + if(defined('FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE') + && is_array(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE) + && count(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE) > 0) + { + $this->_ci->LehreinheitmitarbeiterModel->db->where_not_in('tbl_studiengang.oe_kurzbz', FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE); + } + + $summe_result = $this->_ci->LehreinheitmitarbeiterModel->load(); + + if (isError($summe_result)) return $summe_result; + + if (!hasData($summe_result)) return error('Fehler beim Ermitteln der Gesamtstunden'); + + $summe = getData($summe_result)[0]->summe; + + if ($summe > $stundengrenze->stunden) + { + + if (!$echter_dv && (!$this->_ci->permissionlib->isBerechtigt('admin'))) + { + if (!$this->LehrauftragAufFirma(isset($formData['mitarbeiter_uid']) ? $formData['mitarbeiter_uid'] : $mitarbeiter_uid)) + return error("ACHTUNG: Die maximal erlaubte Semesterstundenanzahl des Lektors von $summe Stunden ($stundengrenze->stunden) wurde ueberschritten!\n Daten wurden NICHT gespeichert!\n\n"); + } + else + { + $warning .= "ACHTUNG: Die maximal erlaubte Semesterstundenanzahl des Lektors von $summe Stunden ($stundengrenze->stunden) wurde ueberschritten!\n Daten wurden gespeichert!\n\n"; + } + + $stunden_limit_result = $this->getStundenInstitut($mitarbeiter_uid, $lehreinheit->studiensemester_kurzbz, $oe_array); + + if (hasData($stunden_limit_result)) + { + $stunden_limit_array = getData($stunden_limit_result); + foreach ($stunden_limit_array as $stunden_limit) + { + $warning .= $stunden_limit->summe . ' Stunden' . $stunden_limit->bezeichnung; + } + } + } + } + } + + $benutzer_result = $this->_ci->BenutzerModel->load(array(isset($formData['mitarbeiter_uid']) ? $formData['mitarbeiter_uid'] : $mitarbeiter_uid)); + + if (isError($benutzer_result)) return $benutzer_result; + + if (!hasData($benutzer_result)) return error('Benutzer not found'); + + $benutzer_aktiv = getData($benutzer_result)[0]->aktiv; + + if (!$benutzer_aktiv) + $warning .= "Achtung: Der/Die Benutzer*in ist inaktiv!\nBitte informieren Sie die Personalbteilung.\n\nDaten wurden gespeichert.\n\n"; + + $updatableFields = array( + 'semesterstunden', + 'planstunden', + 'stundensatz', + 'faktor', + 'anmerkung', + 'lehrfunktion_kurzbz', + 'mitarbeiter_uid', + 'bismelden' + ); + + $updateData = array(); + foreach ($updatableFields as $field) + { + $value = isset($new_data[$field]) ? $new_data[$field] : null; + + if ($value !== null) + { + $updateData[$field] = $value; + } + } + $updateData['updatevon'] = getAuthUID(); + $updateData['updateamum'] = date('Y-m-d H:i:s'); + + $result = $this->_ci->LehreinheitmitarbeiterModel->update(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid), $updateData); + + if (isError($result)) return $result; + + if ($warning !== '') return error($warning); + + return success('Successfully updated Lehreinheit'); + } + + private function getMaxStunden($mitarbeiter_uid, $studiensemester_kurzbz, $studiengang_kz, $echter_dv) + { + $maxstunden = 9999; + + $studiengang_result = $this->_ci->StudiengangModel->loadWhere(array('studiengang_kz' => $studiengang_kz)); + if (isError($studiengang_result)) return $studiengang_result; + + $studiengang = getData($studiengang_result)[0]; + + $stundengrenze_result = $this->_ci->OrganisationseinheitModel->getStundengrenze($studiengang->oe_kurzbz, $echter_dv); + if (isError($stundengrenze_result)) return $stundengrenze_result; + + $stundengrenze = getData($stundengrenze_result)[0]; + $maxstunden = $stundengrenze->stunden; + + $lehrauftrag_firma = $this->LehrauftragAufFirma($mitarbeiter_uid); + + if (!$echter_dv && !$lehrauftrag_firma) + { + $oe_result = $this->_ci->OrganisationseinheitModel->getChilds($stundengrenze->oe_kurzbz); + $oe_array = hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array(''); + + $stunden_summe_result = $this->getSumSemesterstunden($mitarbeiter_uid, $studiensemester_kurzbz, $oe_array); + + $stunden_summe = hasData($stunden_summe_result) ? getData($stunden_summe_result)[0]->summe : 0; + + if ($stunden_summe >= $maxstunden && (!$this->_ci->permissionlib->isBerechtigt('admin'))) + { + $stunden_limit_result = $this->getStundenInstitut($mitarbeiter_uid, $studiensemester_kurzbz, $oe_array); + + $error = "ACHTUNG: Die maximal erlaubte Semesterstundenanzahl des Lektors von $maxstunden Stunden ($stundengrenze->oe_kurzbz) wurde ueberschritten!\n + Daten wurden NICHT gespeichert!\n\n"; + + if (hasData($stunden_limit_result)) + { + $stunden_limit_array = getData($stunden_limit_result); + + foreach ($stunden_limit_array as $stunden_limit) + { + $error .= $stunden_limit->summe . ' Stunden' . $stunden_limit->bezeichnung; + } + } + return error($error); + } + else + $maxstunden =- $stunden_summe; + } + return $maxstunden; + } + + private function LehrauftragAufFirma($mitarbeiter_uid) + { + $this->_ci->MitarbeiterModel->addJoin('tbl_benutzer', 'tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid'); + $this->_ci->MitarbeiterModel->addJoin('tbl_person', 'person_id'); + $this->_ci->MitarbeiterModel->addJoin('tbl_adresse', 'person_id', 'LEFT'); + $this->_ci->MitarbeiterModel->addOrder('zustelladresse', 'DESC'); + $this->_ci->MitarbeiterModel->addOrder('firma_id'); + $this->_ci->MitarbeiterModel->addLimit(1); + $firma_result = $this->_ci->MitarbeiterModel->loadWhere(array('mitarbeiter_uid' => $mitarbeiter_uid)); + $firma = getData($firma_result)[0]->firma_id; + return !is_null($firma); + } + + private function getSumSemesterstunden($mitarbeiter_uid, $studiensemester_kurzbz, $oe_array = array()) + { + $this->_ci->LehreinheitmitarbeiterModel->addSelect('SUM(tbl_lehreinheitmitarbeiter.semesterstunden) as summe'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $this->_ci->LehreinheitmitarbeiterModel->db->where('mitarbeiter_uid', $mitarbeiter_uid); + $this->_ci->LehreinheitmitarbeiterModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz); + $this->_ci->LehreinheitmitarbeiterModel->db->where('bismelden', true); + $this->_ci->LehreinheitmitarbeiterModel->db->where('lower(mitarbeiter_uid) NOT LIKE', '_dummy%'); + $this->_ci->LehreinheitmitarbeiterModel->db->where_in('tbl_studiengang.oe_kurzbz', $oe_array); + return $this->_ci->LehreinheitmitarbeiterModel->load(); + } + + private function getStundenInstitut($mitarbeiter_uid, $studiensemester_kurzbz, $oe_array = array()) + { + $this->_ci->LehreinheitmitarbeiterModel->addSelect('SUM(tbl_lehreinheitmitarbeiter.semesterstunden) as summe, tbl_studiengang.bezeichnung'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehreinheit', 'lehreinheit_id'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); + $this->_ci->LehreinheitmitarbeiterModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $this->_ci->LehreinheitmitarbeiterModel->db->where('mitarbeiter_uid', $mitarbeiter_uid); + $this->_ci->LehreinheitmitarbeiterModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz); + $this->_ci->LehreinheitmitarbeiterModel->db->where('bismelden', true); + $this->_ci->LehreinheitmitarbeiterModel->db->where_in('tbl_studiengang.oe_kurzbz', $oe_array); + + if(defined('FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE') + && is_array(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE) + && count(FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE) > 0) + { + $this->_ci->LehreinheitmitarbeiterModel->db->where_not_in('tbl_studiengang.oe_kurzbz', FAS_LV_LEKTORINNENZUTEILUNG_STUNDEN_IGNORE_OE); + } + + $this->_ci->LehreinheitmitarbeiterModel->addGroupBy('tbl_studiengang.bezeichnung'); + return $this->_ci->LehreinheitmitarbeiterModel->load(); + } +} diff --git a/application/models/accounting/Vertrag_model.php b/application/models/accounting/Vertrag_model.php index abc2114a6..c17c676c7 100644 --- a/application/models/accounting/Vertrag_model.php +++ b/application/models/accounting/Vertrag_model.php @@ -384,6 +384,60 @@ class Vertrag_model extends DB_Model } } + public function getVertrag($mitarbeiter_uid, $lehreinheit_id) + { + $this->addSelect('tbl_lehreinheitmitarbeiter.*, tbl_vertrag.*, status.bezeichnung as vertragsstatus, status.vertragsstatus_kurzbz'); + $this->addJoin('lehre.tbl_lehreinheitmitarbeiter', 'vertrag_id'); + $this->addJoin('lehre.tbl_vertragstyp', 'vertragstyp_kurzbz', 'LEFT'); + $this->addJoin(' + ( + SELECT DISTINCT ON(vertrag_id) vertrag_id, + bezeichnung, + tbl_vertragsstatus.vertragsstatus_kurzbz + FROM lehre.tbl_vertrag_vertragsstatus + JOIN lehre.tbl_vertragsstatus USING(vertragsstatus_kurzbz) + ORDER BY vertrag_id, datum DESC + ) as status', 'status.vertrag_id = lehre.tbl_vertrag.vertrag_id', 'LEFT'); + + return $this->loadWhere(array('mitarbeiter_uid' => $mitarbeiter_uid, 'lehreinheit_id' => $lehreinheit_id)); + } + + public function cancelVertrag($vertrag_id, $mitarbeiter_uid) + { + $vertrag = $this->load($vertrag_id); + + if (!hasData($vertrag)) + return error("Contract not found"); + + $vertrag = getData($vertrag)[0]; + + $this->_updateVertragRelevant($vertrag->vertrag_id); + + return $this->VertragvertragsstatusModel->insert(array( + 'vertrag_id' => $vertrag->vertrag_id, + 'vertragsstatus_kurzbz' => 'storno', + 'uid' => $mitarbeiter_uid, + 'datum' => 'NOW()', + 'insertamum' => 'NOW()', + 'insertvon' => getAuthUID() + )); + } + + public function deleteVertrag($vertrag_id) + { + $vertrag = $this->load($vertrag_id); + + if (!hasData($vertrag)) + return error("Contract not found"); + + $vertrag = getData($vertrag)[0]; + + $this->_updateVertragRelevant($vertrag->vertrag_id); + + $this->VertragvertragsstatusModel->delete(array('vertrag_id' => $vertrag->vertrag_id)); + return $this->delete(array('vertrag_id' => $vertrag->vertrag_id)); + } + // ----------------------------------------------------------------------------------------------------------------- // Private methods @@ -415,4 +469,20 @@ class Vertrag_model extends DB_Model return $bezeichnung; } + + private function _updateVertragRelevant($vertrag_id) + { + $this->LehreinheitmitarbeiterModel->update( + array("vertrag_id" => $vertrag_id), + array( + 'vertrag_id' => null + ) + ); + $this->ProjektbetreuerModel->update( + array("vertrag_id" => $vertrag_id), + array( + 'vertrag_id' => null + ) + ); + } } diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index d4bc7a22f..ba9e82c64 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -1,4 +1,6 @@ load->model('education/lehreinheitgruppe_model', 'LehreinheitgruppeModel'); $this->load->model('education/lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); $this->load->model('organisation/studiengang_model', 'StudiengangModel'); + $this->load->model('ressource/stundenplandev_model', 'StundenplandevModel'); + $this->load->model('ressource/stundenplan_model', 'StundenplanModel'); + $this->load->model('system/Log_model', 'LogModel'); } /** @@ -303,4 +308,437 @@ EOSQL; return $this->execQuery($query, $params); } + + + public function getOes($lehreinheit_id) + { + $this->addSelect('tbl_lehrveranstaltung.studiengang_kz, + tbl_lehrveranstaltung.lehrveranstaltung_id'); + $this->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_lehreinheit.lehrveranstaltung_id'); + $result = $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + + if (isError($result)) return $result; + + if (hasData($result)) + { + $lehrveranstaltung = getData($result)[0]; + $oe_result = $this->LehrveranstaltungModel->getAllOe($lehrveranstaltung->lehrveranstaltung_id, $lehrveranstaltung->studiengang_kz); + return success(hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array('')); + } + } + + public function getLehrfachOe($lehreinheit_id) + { + $this->addSelect('lehrfach.oe_kurzbz'); + $this->addJoin('lehre.tbl_lehrveranstaltung lehrfach', 'lehrfach.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id', 'LEFT'); + return $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + } + + + public function getByLvidStudiensemester($lv_id, $studiensemester_kurzbz) + { + $qry = "WITH lehreinheiten AS ( + SELECT * + FROM lehre.tbl_lehreinheit + WHERE lehrveranstaltung_id = ? + AND studiensemester_kurzbz = ? + ), + gruppen AS ( + SELECT + COALESCE( + string_agg( + tbl_lehreinheitgruppe.gruppe_kurzbz, ' ' + ) FILTER (WHERE NOT direktinskription), + string_agg( + COALESCE( + upper(tbl_studiengang.typ::varchar(1) ||tbl_studiengang.kurzbz) || + '-'|| + COALESCE(tbl_lehreinheitgruppe.semester::varchar, '') || + COALESCE(tbl_lehreinheitgruppe.verband::varchar, '')|| + COALESCE(tbl_lehreinheitgruppe.gruppe, '')), ', ' + ) + ) AS gruppe, + lehreinheit_id + FROM + lehre.tbl_lehreinheitgruppe + LEFT JOIN public.tbl_studiengang USING(studiengang_kz) + LEFT JOIN public.tbl_gruppe USING(gruppe_kurzbz) + GROUP BY lehreinheit_id + ), + mitarbeiter AS ( + SELECT kurzbz, semesterstunden, planstunden, lehreinheit_id + FROM lehre.tbl_lehreinheitmitarbeiter + JOIN public.tbl_mitarbeiter USING(mitarbeiter_uid) + ), + fachbereich AS ( + SELECT + tbl_organisationseinheit.bezeichnung, + tbl_organisationseinheit.organisationseinheittyp_kurzbz, + lehreinheit_id + FROM + public.tbl_organisationseinheit, + lehre.tbl_lehrveranstaltung as lehrfach, + lehre.tbl_lehreinheit + WHERE tbl_organisationseinheit.oe_kurzbz = lehrfach.oe_kurzbz + AND lehrfach.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id + ), + tag_data_agg AS ( + SELECT + lehreinheit_id, + COALESCE(json_agg(tag ORDER BY id), '[]'::json) AS tags + FROM ( + SELECT DISTINCT ON (public.tbl_notiz.notiz_id) + tbl_notiz.notiz_id AS id, + typ_kurzbz, + array_to_json(tbl_notiz_typ.bezeichnung_mehrsprachig)->>0 AS beschreibung, + text AS notiz, + style, + erledigt AS done, + lehreinheit_id + FROM public.tbl_notizzuordnung + JOIN public.tbl_notiz ON tbl_notizzuordnung.notiz_id = tbl_notiz.notiz_id + JOIN public.tbl_notiz_typ ON tbl_notiz.typ = tbl_notiz_typ.typ_kurzbz + WHERE lehreinheit_id IN (SELECT lehreinheit_id FROM lehreinheiten) + ) AS tag + GROUP BY lehreinheit_id + ) + SELECT lehreinheiten.*, + lehreinheiten.lehrform_kurzbz as lv_lehrform_kurzbz, + tbl_lehrveranstaltung.kurzbz as lv_kurzbz, + tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, + COALESCE(tag_data_agg.tags, '[]'::json) AS tags, + ( + SELECT string_agg(gr.gruppe, ' ') + FROM gruppen gr + WHERE gr.lehreinheit_id = lehreinheiten.lehreinheit_id + ) AS gruppen, + ( + SELECT string_agg(ma.kurzbz, ' ') + FROM mitarbeiter ma + WHERE ma.lehreinheit_id = lehreinheiten.lehreinheit_id + ) AS lektoren, + ( + SELECT string_agg(fachbereich.bezeichnung, ' ') + FROM fachbereich + WHERE fachbereich.lehreinheit_id = lehreinheiten.lehreinheit_id + ) AS fachbereich + FROM lehreinheiten + LEFT JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = lehreinheiten.lehrfach_id + LEFT JOIN tag_data_agg ON tag_data_agg.lehreinheit_id = lehreinheiten.lehreinheit_id"; + + return $this->execReadOnlyQuery($qry, array($lv_id, $studiensemester_kurzbz)); + } + + private function getLVTmp($stg_kz = null) + { + $qry = "SELECT DISTINCT ON(lehrveranstaltung_id) *, + '' as studienplan_id, '' as studienplan_beeichnung, + CONCAT(vw_lehreinheit.stg_typ, vw_lehreinheit.stg_kurzbz) as studiengang + FROM campus.vw_lehreinheit + WHERE mitarbeiter_uid = ? + AND studiensemester_kurzbz = ?"; + + if (!is_null($stg_kz)) { + $qry .= " AND lv_studiengang_kz = ?"; + } + + return $qry; + } + + public function getLvsByEmployee($mitarbeiter_uid, $studiensemester_kurzbz, $stg_kz = null) + { + $qry = "WITH lvs AS (" . $this->getLVTmp($stg_kz) . ") + SELECT lvs.* + FROM lvs + "; + + $params = array($mitarbeiter_uid, $studiensemester_kurzbz); + if (!is_null($stg_kz)) + { + $params[] = $stg_kz; + } + return $this->execReadOnlyQuery($qry, $params); + } + + + + public function getLEByLV($lv_id, $studiensemester_kurzbz, $mitarbeiter_uid = null, $fachbereich_kurzbz = null) + { + $qry = " + WITH gruppen AS ( + SELECT + COALESCE( + string_agg( + tbl_lehreinheitgruppe.gruppe_kurzbz, ', ' + ) FILTER (WHERE NOT direktinskription), + string_agg( + COALESCE( + upper(tbl_studiengang.typ::varchar(1) ||tbl_studiengang.kurzbz) || + '-'|| + COALESCE(tbl_lehreinheitgruppe.semester::varchar, '') || + COALESCE(tbl_lehreinheitgruppe.verband::varchar, '')|| + COALESCE(tbl_lehreinheitgruppe.gruppe, '')), ', ' + ) + ) AS gruppen, + lehreinheit_id + FROM + lehre.tbl_lehreinheitgruppe + LEFT JOIN public.tbl_studiengang USING(studiengang_kz) + LEFT JOIN public.tbl_gruppe USING(gruppe_kurzbz) + GROUP BY lehreinheit_id + ), + lektoren AS ( + SELECT string_agg(kurzbz, ' ') as lektoren, + string_agg(semesterstunden::text, ' ') as semesterstunden, + string_agg(planstunden::text, ' ') as planstunden, + lehreinheit_id + FROM lehre.tbl_lehreinheitmitarbeiter + JOIN public.tbl_mitarbeiter USING(mitarbeiter_uid) + GROUP BY lehreinheit_id + ), + fachbereich AS ( + SELECT + string_agg(CONCAT(tbl_organisationseinheit.bezeichnung, ' (', tbl_organisationseinheit.organisationseinheittyp_kurzbz, ')'),' ') as fachbereich, + lehreinheit_id + FROM + public.tbl_organisationseinheit, + lehre.tbl_lehrveranstaltung as lehrfach, + lehre.tbl_lehreinheit + WHERE + tbl_organisationseinheit.oe_kurzbz = lehrfach.oe_kurzbz + AND lehrfach.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id + GROUP BY lehreinheit_id + ) + SELECT tbl_lehreinheit.*, + tbl_lehrveranstaltung.*, + tbl_lehrveranstaltung.kurzbz as lv_kurzbz, + tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, + lektoren.lektoren, + lektoren.semesterstunden, + lektoren.planstunden, + fachbereich.fachbereich + FROM lehre.tbl_lehreinheit + LEFT JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id + LEFT JOIN gruppen ON tbl_lehreinheit.lehreinheit_id = gruppen.lehreinheit_id + LEFT JOIN lektoren ON tbl_lehreinheit.lehreinheit_id = lektoren.lehreinheit_id + LEFT JOIN fachbereich ON tbl_lehreinheit.lehreinheit_id = fachbereich.lehreinheit_id + WHERE tbl_lehreinheit.lehrveranstaltung_id = ? + AND studiensemester_kurzbz = ? + "; + + $params = array($lv_id, $studiensemester_kurzbz); + if ($mitarbeiter_uid !== null) + { + $qry .= " AND tbl_lehreinheit.lehreinheit_id IN ( SELECT lehreinheit_id FROM lehre.tbl_lehreinheitmitarbeiter WHERE mitarbeiter_uid = ?) "; + $params[] = $mitarbeiter_uid; + } + + if($fachbereich_kurzbz !== null) + { + $qry .= " AND EXISTS ( SELECT 1 FROM lehre.tbl_lehrveranstaltung JOIN public.tbl_fachbereich USING(oe_kurzbz) WHERE fachbereich_kurzbz= ? AND lehrveranstaltung_id=tbl_lehreinheit.lehrfach_id)"; + $params[] = $fachbereich_kurzbz; + } + $qry .= " ORDER BY lehreinheit_id;"; + + return $this->execReadOnlyQuery($qry, $params); + } + + public function deleteLehreinheit($lehreinheit_id) + { + $lehreinheit = $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + + if (isError($lehreinheit)) return $lehreinheit; + + if (!hasData($lehreinheit)) + return error("Lehreinheit not found!"); + + $errorReasons = []; + $addError = function ($reason = null) use (&$errorReasons) + { + if ($reason !== null) + { + $errorReasons[] = $reason; + } + }; + + $stundenplandev_result = $this->StundenplandevModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + $stundenplan_result = $this->StundenplanModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + + if (hasData($stundenplan_result) || hasData($stundenplandev_result)) + $addError('Dieser LV-Teil ist bereits im LV-Plan verplant und kann daher nicht geloescht werden!'); + + Events::trigger( + 'lehreinheit_delete_check', + $addError, + $lehreinheit_id + ); + + if (!empty($errorReasons)) return error($errorReasons); + + $this->db->trans_begin(); + + Events::trigger( + 'lehreinheit_delete', + $addError, + $lehreinheit_id + ); + + $undosql = ''; + + $lehreinheit_gruppe_result = $this->LehreinheitgruppeModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + if (hasData($lehreinheit_gruppe_result)) + { + foreach (getData($lehreinheit_gruppe_result) as $row) + { + $values = [ + $this->db->escape($row->lehreinheitgruppe_id), + $this->db->escape($row->lehreinheit_id), + $this->db->escape($row->studiengang_kz), + $this->db->escape($row->semester), + $this->db->escape($row->verband), + $this->db->escape($row->gruppe), + $this->db->escape($row->gruppe_kurzbz), + $this->db->escape($row->updateamum), + $this->db->escape($row->updatevon), + $this->db->escape($row->insertamum), + $this->db->escape($row->insertvon) + ]; + + $undosql .= "INSERT INTO lehre.tbl_lehreinheitgruppe ( + lehreinheitgruppe_id, + lehreinheit_id, + studiengang_kz, + semester, + verband, + gruppe, + gruppe_kurzbz, + updateamum, + updatevon, + insertamum, + insertvon + ) VALUES (" . implode(', ', $values) . ");\n"; + } + + $lehreinheit_gruppe_delete_result = $this->LehreinheitgruppeModel->delete(array('lehreinheit_id' => $lehreinheit_id)); + + if (isError($lehreinheit_gruppe_delete_result)) + $addError(getError($lehreinheit_gruppe_delete_result)); + } + + $lehreinheit_mitarbeiter_result = $this->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + if (hasData($lehreinheit_mitarbeiter_result)) + { + foreach (getData($lehreinheit_mitarbeiter_result) as $row) + { + $values = [ + $this->db->escape($row->lehreinheit_id), + $this->db->escape($row->mitarbeiter_uid), + $this->db->escape($row->lehrfunktion_kurzbz), + $this->db->escape($row->planstunden), + $this->db->escape($row->stundensatz), + $this->db->escape($row->faktor), + $this->db->escape($row->anmerkung), + $this->db->escape($row->bismelden), + $this->db->escape($row->updateamum), + $this->db->escape($row->updatevon), + $this->db->escape($row->insertamum), + $this->db->escape($row->insertvon), + $this->db->escape($row->semesterstunden) + ]; + + $undosql .= "INSERT INTO lehre.tbl_lehreinheitmitarbeiter ( + lehreinheit_id, + mitarbeiter_uid, + lehrfunktion_kurzbz, + planstunden, + stundensatz, + faktor, + anmerkung, + bismelden, + updateamum, + updatevon, + insertamum, + insertvon, + semesterstunden + ) VALUES (" . implode(', ', $values) . ");\n"; + } + + $lehreinheit_mitarbeiter_delete_result = $this->LehreinheitmitarbeiterModel->delete(array('lehreinheit_id' => $lehreinheit_id)); + if (isError($lehreinheit_mitarbeiter_delete_result)) + $addError(getError($lehreinheit_mitarbeiter_delete_result)); + } + + foreach (getData($lehreinheit) as $row) + { + $values = [ + $this->db->escape($row->lehreinheit_id), + $this->db->escape($row->lehrveranstaltung_id), + $this->db->escape($row->studiensemester_kurzbz), + $this->db->escape($row->lehrfach_id), + $this->db->escape($row->lehrform_kurzbz), + $this->db->escape($row->stundenblockung), + $this->db->escape($row->wochenrythmus), + $this->db->escape($row->start_kw), + $this->db->escape($row->raumtyp), + $this->db->escape($row->raumtypalternativ), + $this->db->escape($row->sprache), + $this->db->escape($row->lehre), + $this->db->escape($row->anmerkung), + $this->db->escape($row->unr), + $this->db->escape($row->lvnr), + $this->db->escape($row->updateamum), + $this->db->escape($row->updatevon), + $this->db->escape($row->insertamum), + $this->db->escape($row->insertvon), + ]; + + $undosql .= "INSERT INTO lehre.tbl_lehreinheit ( + lehreinheit_id, + lehrveranstaltung_id, + studiensemester_kurzbz, + lehrfach_id, + lehrform_kurzbz, + stundenblockung, + wochenrythmus, + start_kw, + raumtyp, + raumtypalternativ, + sprache, + lehre, + anmerkung, + unr, + lvnr, + updateamum, + updatevon, + insertamum, + insertvon + ) VALUES (" . implode(', ', $values) . ");\n"; + } + $lehreinheit_result = $this->delete($lehreinheit_id); + + $deleteSql = "DELETE FROM lehre.tbl_lehreinheitmitarbeiter WHERE lehreinheit_id = " . $this->db->escape($lehreinheit_id) ."; \n + DELETE FROM lehre.tbl_lehreinheitgruppe WHERE lehreinheit_id = " . $this->db->escape($lehreinheit_id) ."; \n + DELETE FROM lehre.tbl_lehreinheit WHERE lehreinheit_id = " . $this->db->escape($lehreinheit_id) .";"; + if (isError($lehreinheit_result)) + $addError($lehreinheit_result); + + $log_result = $this->LogModel->insert([ + 'sql' => $deleteSql, + 'sqlundo' => $undosql, + 'beschreibung' => 'Lehreinheit loeschen - ' . $lehreinheit_id, + 'mitarbeiter_uid' => getAuthUID(), + ]); + + if (isError($log_result)) + $addError($log_result); + + if (!empty($errorReasons)) + { + $this->db->trans_rollback(); + return error($errorReasons); + } + + $this->db->trans_commit(); + return success('Contract successfully updated.'); + } } diff --git a/application/models/education/Lehreinheitgruppe_model.php b/application/models/education/Lehreinheitgruppe_model.php index 2a6f9571a..5dd2fa66c 100644 --- a/application/models/education/Lehreinheitgruppe_model.php +++ b/application/models/education/Lehreinheitgruppe_model.php @@ -14,6 +14,7 @@ class Lehreinheitgruppe_model extends DB_Model $this->load->model('organisation/studiengang_model', 'StudiengangModel'); $this->load->model('organisation/gruppe_model', 'GruppeModel'); $this->load->model('person/benutzergruppe_model', 'BenutzergruppeModel'); + $this->load->model('ressource/stundenplandev_model', 'StundenplandevModel'); } /** @@ -23,7 +24,15 @@ class Lehreinheitgruppe_model extends DB_Model */ public function getDirectGroup($lehreinheit_id) { + $this->addSelect('tbl_lehreinheitgruppe.*'); + $this->addSelect('tbl_gruppe.*'); + $this->addSelect('uid'); + $this->addSelect('vorname'); + $this->addSelect('nachname'); $this->addJoin('public.tbl_gruppe', 'gruppe_kurzbz'); + $this->addJoin('public.tbl_benutzergruppe', 'gruppe_kurzbz', 'LEFT'); + $this->addJoin('public.tbl_benutzer', 'uid', 'LEFT'); + $this->addJoin('public.tbl_person', 'person_id', 'LEFT'); return $this->loadWhere( array( 'tbl_gruppe.direktinskription' => true, @@ -264,4 +273,203 @@ class Lehreinheitgruppe_model extends DB_Model } return $result; } + + public function addGroup($lehreinheit_id, $gid, $verband) + { + $lehreinheit = $this->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit)) + return error ('No Lehreinheit found!'); + + if ($verband === false) + { + $gruppen_result = $this->GruppeModel->loadWhere(array('gid' => $gid)); + + if (!hasData($gruppen_result)) + return error('No group found for gid ' . $gid); + + $gruppen_array = getData($gruppen_result)[0]; + + if (!isEmptyString($gruppen_array->gruppe_kurzbz)) + { + $this->db->where('trim(gruppe_kurzbz)', $gruppen_array->gruppe_kurzbz); + } + else + { + $this->db->group_start(); + $this->db->where("trim(gruppe_kurzbz) = ''"); + $this->db->or_where("gruppe_kurzbz IS NULL"); + $this->db->group_end(); + } + } + else if ($verband === true) + { + $gruppen_result = $this->_ci->LehrverbandModel->loadWhere(array('gid' => $gid)); + + if (!hasData($gruppen_result)) + return error('No group found for gid ' . $gid); + + $gruppen_array = getData($gruppen_result)[0]; + + if (!isEmptyString($gruppen_array->verband)) + { + $this->db->where('verband', $gruppen_array->verband); + } + else + { + $this->db->group_start(); + $this->db->where("trim(verband) = ''"); + $this->db->or_where("verband IS NULL"); + $this->db->group_end(); + } + + if (!isEmptyString($gruppen_array->gruppe)) + { + $this->db->where('gruppe', $gruppen_array->gruppe); + } + else + { + $this->db->group_start(); + $this->db->where("trim(gruppe) = ''"); + $this->db->or_where("gruppe IS NULL"); + $this->db->group_end(); + } + } + else + return error('Wrong type of verband'); + + $this->db->where('lehreinheit_id', $lehreinheit_id); + $this->db->where('studiengang_kz', $gruppen_array->studiengang_kz); + + if (!isEmptyString($gruppen_array->semester)) + { + $this->db->where('semester', $gruppen_array->semester); + } + else + { + $this->db->group_start(); + $this->db->where("semester = ''"); + $this->db->or_where("semester IS NULL"); + $this->db->group_end(); + } + + $exist_result = $this->load(); + + if (!hasData($exist_result)) + { + $new_group_result = $this->insert(array( + 'lehreinheit_id' => $lehreinheit_id, + 'studiengang_kz' => $gruppen_array->studiengang_kz, + 'gruppe_kurzbz' => isset($gruppen_array->gruppe_kurzbz) ? $gruppen_array->gruppe_kurzbz : null, + 'semester' => $gruppen_array->semester, + 'verband' => isset($gruppen_array->verband) && !isEmptyString($gruppen_array->verband) ? $gruppen_array->verband : null, + 'gruppe' => isset($gruppen_array->gruppe) && !isEmptyString($gruppen_array->gruppe) ? $gruppen_array->gruppe : null, + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => getAuthUID() + )); + + if (isError($new_group_result)) + return error('Error when adding Group'); + + return success('Group assigned successfully to Lehreinheit'); + } + else + return error('Group already assigned'); + } + + public function deleteGroup($lehreinheit_id, $lehreinheitgruppe_id) + { + $lehreinheit = $this->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit)) + return error ('No Lehreinheit found!'); + + $lehreinheitgruppe = $this->load($lehreinheitgruppe_id); + + if (!hasData($lehreinheitgruppe)) + return error ('No Lehreinheitgruppe found!'); + + $this->addSelect('stundenplandev_id'); + $this->addJoin('lehre.tbl_stundenplandev', + "tbl_stundenplandev.lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id + AND tbl_stundenplandev.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz + AND tbl_stundenplandev.semester = tbl_lehreinheitgruppe.semester + AND trim(COALESCE(tbl_stundenplandev.verband, '')) = trim(COALESCE(tbl_lehreinheitgruppe.verband, '')) + AND trim(COALESCE(tbl_stundenplandev.gruppe, '')) = trim(COALESCE(tbl_lehreinheitgruppe.gruppe, '')) + AND trim(COALESCE(tbl_stundenplandev.gruppe_kurzbz, '')) = trim(COALESCE(tbl_lehreinheitgruppe.gruppe_kurzbz, ''))" + ); + $stundenplan_result = $this->loadWhere(array('tbl_lehreinheitgruppe.lehreinheitgruppe_id' => $lehreinheitgruppe_id)); + + if (hasData($stundenplan_result)) + return error('Gruppe already verplant'); + + $delete_result = $this->delete($lehreinheitgruppe_id); + + if (isError($delete_result)) + return error('Error deleting Group'); + + return success('Group deleted'); + } + + public function getByLehreinheit($lehreinheit_id) + { + $lehreinheit = $this->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit)) + return error ('No Lehreinheit found!'); + + $this->addSelect('tbl_lehreinheitgruppe.*'); + $this->addSelect('tbl_gruppe.direktinskription'); + $this->addSelect('tbl_gruppe.gruppe_kurzbz'); + $this->addSelect("CASE + WHEN tbl_lehreinheitgruppe.gruppe_kurzbz IS NULL THEN + COALESCE ( + UPPER(tbl_studiengang.typ || tbl_studiengang.kurzbz) || + COALESCE(tbl_lehreinheitgruppe.semester::varchar, '') || + COALESCE(tbl_lehreinheitgruppe.verband::varchar, '') || + COALESCE(tbl_lehreinheitgruppe.gruppe, ''), + '') + ELSE tbl_lehreinheitgruppe.gruppe_kurzbz + END AS bezeichnung"); + $this->addSelect("CASE + WHEN tbl_lehreinheitgruppe.gruppe_kurzbz IS NULL THEN + ( + SELECT bezeichnung + FROM public.tbl_lehrverband + WHERE studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz + AND semester = tbl_lehreinheitgruppe.semester + AND verband = tbl_lehreinheitgruppe.verband + AND gruppe = tbl_lehreinheitgruppe.gruppe + LIMIT 1 + ) + ELSE tbl_gruppe.beschreibung + END AS beschreibung"); + $this->addSelect("CASE + WHEN tbl_lehreinheitgruppe.gruppe_kurzbz IS NULL THEN + ( + SELECT EXISTS ( + SELECT 1 + FROM lehre.tbl_stundenplandev + WHERE lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id + AND studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz + AND semester = tbl_lehreinheitgruppe.semester + AND TRIM(COALESCE(verband, '')) = TRIM(tbl_lehreinheitgruppe.verband) + AND TRIM(COALESCE(gruppe, '')) = TRIM(tbl_lehreinheitgruppe.gruppe) + AND (gruppe_kurzbz IS NULL OR gruppe_kurzbz = '') + ) + ) + ELSE + ( + SELECT EXISTS ( + SELECT 1 + FROM lehre.tbl_stundenplandev + WHERE lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id + AND gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz + ) + ) + END AS verplant"); + $this->addJoin('tbl_studiengang', 'studiengang_kz', 'LEFT'); + $this->addJoin('public.tbl_gruppe', 'gruppe_kurzbz', 'LEFT'); + return $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'tbl_gruppe.direktinskription' => false)); + } } diff --git a/application/models/education/Lehreinheitmitarbeiter_model.php b/application/models/education/Lehreinheitmitarbeiter_model.php index ae1ac55d2..efdb2e74d 100644 --- a/application/models/education/Lehreinheitmitarbeiter_model.php +++ b/application/models/education/Lehreinheitmitarbeiter_model.php @@ -10,6 +10,14 @@ class Lehreinheitmitarbeiter_model extends DB_Model parent::__construct(); $this->dbTable = 'lehre.tbl_lehreinheitmitarbeiter'; $this->pk = array('mitarbeiter_uid', 'lehreinheit_id'); + $this->hasSequence = false; + + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('ressource/stundenplandev_model', 'StundenplandevModel'); + $this->load->model('ressource/stundenplan_model', 'StundenplanModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); } /** @@ -75,4 +83,67 @@ class Lehreinheitmitarbeiter_model extends DB_Model ]); } + public function getLektorenByLe($lehreinheit_id) + { + $this->addSelect('vorname, nachname, tbl_lehreinheitmitarbeiter.*, stundenplan.verplant'); + $this->addJoin('tbl_benutzer', 'uid = mitarbeiter_uid'); + $this->addJoin('tbl_person', 'person_id'); + + $this->addJoin('( + SELECT 1 as verplant, lehreinheit_id, mitarbeiter_uid + FROM lehre.tbl_stundenplandev + GROUP BY lehreinheit_id, mitarbeiter_uid + + ) stundenplan', 'stundenplan.mitarbeiter_uid = tbl_lehreinheitmitarbeiter.mitarbeiter_uid AND stundenplan.lehreinheit_id = tbl_lehreinheitmitarbeiter.lehreinheit_id', 'LEFT'); + + return $this->loadWhere(array('tbl_lehreinheitmitarbeiter.lehreinheit_id' => $lehreinheit_id)); + } + + public function getByLeLektor($lehreinheit_id, $mitarbeiter_uid) + { + $this->addSelect('vorname, nachname, tbl_lehreinheitmitarbeiter.*'); + $this->addJoin('tbl_benutzer', 'uid = mitarbeiter_uid'); + $this->addJoin('tbl_person', 'person_id'); + return $this->loadWhere(array('tbl_lehreinheitmitarbeiter.lehreinheit_id' => $lehreinheit_id, 'tbl_lehreinheitmitarbeiter.mitarbeiter_uid' => $mitarbeiter_uid)); + } + + public function deleteLektorFromLe($lehreinheit_id, $mitarbeiter_uid) + { + if (defined('FAS_LV_LEKTORINNENZUTEILUNG_VERTRAGSDETAILS_ANZEIGEN') && FAS_LV_LEKTORINNENZUTEILUNG_VERTRAGSDETAILS_ANZEIGEN) + { + $vertrag_result = $this->VertragModel->getVertrag($mitarbeiter_uid, $lehreinheit_id); + + if (hasData($vertrag_result)) + return error("Loeschen nur nach Stornierung des Vertrags möglich"); + } + + $stundenplandev_result = $this->StundenplandevModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + $stundenplan_result = $this->StundenplanModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + + if (hasData($stundenplandev_result) || hasData($stundenplan_result)) + return error("Diese/r LektorIn kann nicht gelöscht werden da er schon verplant ist"); + + $result = $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + + if (hasData($result)) + { + $le_mitarbeiter_array = getData($result)[0]; + + if ($le_mitarbeiter_array->vertrag_id !== null) + { + $vertrag_result = $this->VertragModel->deleteVertrag($le_mitarbeiter_array->vertrag_id); + if (isError($vertrag_result)) + return $vertrag_result; + } + + $delete_result = $this->delete(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + + if (isError($delete_result)) + return $delete_result; + + return success($delete_result); + } + } + + } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 056fb45d7..955177273 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -988,4 +988,229 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($qry, $params); } + + public function getLvsByOrganization($oe_kurzbz) + { + $qry=" + SELECT + distinct on (lehrveranstaltung_id) + tbl_lehrveranstaltung.studiengang_kz as lv_studiengang_kz, tbl_lehrveranstaltung.semester as lv_semester, + tbl_lehrveranstaltung.kurzbz as lv_kurzbz, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, tbl_lehrveranstaltung.ects as lv_ects, + tbl_lehrveranstaltung.lehreverzeichnis as lv_lehreverzeichnis, tbl_lehrveranstaltung.planfaktor as lv_planfaktor, + tbl_lehrveranstaltung.planlektoren as lv_planlektoren, tbl_lehrveranstaltung.planpersonalkosten as lv_planpersonalkosten, + tbl_lehrveranstaltung.plankostenprolektor as lv_plankostenprolektor, tbl_lehrveranstaltung.orgform_kurzbz as lv_orgform_kurzbz, + tbl_lehrveranstaltung.lehrveranstaltung_id, + tbl_lehrveranstaltung.lehrform_kurzbz as lehrform_kurzbz, + tbl_lehrveranstaltung.lehrform_kurzbz as lv_lehrform_kurzbz, + tbl_lehrveranstaltung.bezeichnung_english as lv_bezeichnung_english, + tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.semester, tbl_lehrveranstaltung.anmerkung, tbl_lehrveranstaltung.sprache, tbl_lehrveranstaltung.semesterstunden, + tbl_lehrveranstaltung.lehre, tbl_lehrveranstaltung.aktiv, + '' as studienplan_id, '' as studienplan_bezeichnung, tbl_lehrveranstaltung.lehrtyp_kurzbz + FROM + lehre.tbl_lehrveranstaltung + WHERE + tbl_lehrveranstaltung.oe_kurzbz= ? + AND tbl_lehrveranstaltung.aktiv + "; + + return $this->execReadOnlyQuery($qry, array($oe_kurzbz)); + } + + public function getLvsByFachbereich($fachbereich, $studiensemester_kurbz, $mitarbeiter_uid = null) + { + $qry = ""; + if (!is_null($mitarbeiter_uid)) + { + $qry = $this->getLvsFromStudienplanByEmp(); + $params = array($fachbereich, $studiensemester_kurbz); + } + + $qry .= "SELECT + distinct on(lehrveranstaltung_id) + lv_studiengang_kz, lv_semester, lv_kurzbz, lv_bezeichnung, lv_ects, + lv_lehreverzeichnis, lv_planfaktor, lv_planlektoren, lv_planpersonalkosten, + lv_plankostenprolektor, lv_orgform_kurzbz, lehrveranstaltung_id, + lehrform_kurzbz, lv_lehrform_kurzbz, lv_bezeichnung_english, studiengang_kz, semester, anmerkung, sprache, semesterstunden, + lehre, aktiv, + '' as studienplan_id, '' as studienplan_bezeichnung, + (SELECT lehrtyp_kurzbz FROM lehre.tbl_lehrveranstaltung WHERE lehrveranstaltung_id=vw_lehreinheit.lehrveranstaltung_id) as lehrtyp_kurzbz + FROM + campus.vw_lehreinheit + WHERE studiensemester_kurzbz = ? + AND fachbereich_kurzbz = ?"; + + $params[] = array($studiensemester_kurbz, $fachbereich); + + if (!is_null($mitarbeiter_uid)) + { + $qry .= " AND mitarbeiter_uid = ?"; + $params[] = $mitarbeiter_uid; + } + else + { + $qry.=" AND lehrveranstaltung_id NOT IN (SELECT lehrveranstaltung_id + FROM + lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_studienplan_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN lehre.tbl_studienplan USING(studienplan_id) + JOIN lehre.tbl_studienordnung USING(studienordnung_id) + JOIN lehre.tbl_studienplan_semester USING(studienplan_id) + WHERE + tbl_lehrveranstaltung.oe_kurzbz=(Select oe_kurzbz from public.tbl_fachbereich where fachbereich_kurzbz= ?) + AND tbl_studienplan_semester.studiensemester_kurzbz= ?"; + + $params[] = array($fachbereich, $studiensemester_kurbz); + } + + return $this->execReadOnlyQuery($qry, $params); + } + + private function getLvsFromStudienplanByEmp() + { + return " + SELECT + distinct on (lehrveranstaltung_id) + tbl_lehrveranstaltung.studiengang_kz as lv_studiengang_kz, + tbl_lehrveranstaltung.semester as lv_semester, + tbl_lehrveranstaltung.kurzbz as lv_kurzbz, + tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, + tbl_lehrveranstaltung.ects as lv_ects, + tbl_lehrveranstaltung.lehreverzeichnis as lv_lehreverzeichnis, + tbl_lehrveranstaltung.planfaktor as lv_planfaktor, + tbl_lehrveranstaltung.planlektoren as lv_planlektoren, + tbl_lehrveranstaltung.planpersonalkosten as lv_planpersonalkosten, + tbl_lehrveranstaltung.plankostenprolektor as lv_plankostenprolektor, + tbl_lehrveranstaltung.orgform_kurzbz as lv_orgform_kurzbz, + tbl_lehrveranstaltung.lehrveranstaltung_id, + tbl_lehrveranstaltung.lehrform_kurzbz as lehrform_kurzbz, + tbl_lehrveranstaltung.lehrform_kurzbz as lv_lehrform_kurzbz, + tbl_lehrveranstaltung.bezeichnung_english as lv_bezeichnung_english, + tbl_lehrveranstaltung.studiengang_kz, + tbl_studienplan_lehrveranstaltung.semester, + tbl_lehrveranstaltung.anmerkung, + tbl_lehrveranstaltung.sprache, + tbl_lehrveranstaltung.semesterstunden, + tbl_lehrveranstaltung.lehre, + tbl_lehrveranstaltung.aktiv, + tbl_studienplan.studienplan_id::text, + tbl_studienplan.bezeichnung as studienplan_bezeichnung, + tbl_lehrveranstaltung.lehrtyp_kurzbz + FROM + lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_studienplan_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN lehre.tbl_studienplan USING(studienplan_id) + JOIN lehre.tbl_studienordnung USING(studienordnung_id) + JOIN lehre.tbl_studienplan_semester USING(studienplan_id) + WHERE + tbl_lehrveranstaltung.oe_kurzbz=(Select oe_kurzbz from public.tbl_fachbereich where fachbereich_kurzbz= ?) + AND tbl_studienplan_semester.studiensemester_kurzbz = ? + AND tbl_lehrveranstaltung.aktiv + UNION + "; + } + + public function getLvsByStudiengang($studienplan_ids, $placeholders, $only_ids, $studiengang_kz, $studiensemester_kurzbz, $semester = null, $verband = null) + { + $qry = ""; + $params = array(); + + if (!empty($studienplan_ids)) + { + $qry = $this->getLvsFromStudienplanByStudienplanID($placeholders); + $params = $studienplan_ids; + } + + $qry .= " + SELECT DISTINCT on(lehrveranstaltung_id) lehrveranstaltung_id, + kurzbz as lv_kurzbz, + bezeichnung as lv_bezeichnung, + bezeichnung_english as lv_bezeichnung_english, + studiengang_kz, + semester, + tbl_lehrveranstaltung.sprache, + ects as lv_ects, + semesterstunden, + tbl_lehrveranstaltung.anmerkung, + tbl_lehrveranstaltung.lehre, + lehreverzeichnis as lv_lehreverzeichnis, + aktiv, + planfaktor as lv_planfaktor, + planlektoren as lv_planlektoren, + planpersonalkosten as lv_planpersonalkosten, + plankostenprolektor as lv_plankostenprolektor, + tbl_lehrveranstaltung.lehrform_kurzbz as lv_lehrform_kurzbz, + tbl_lehrveranstaltung.orgform_kurzbz, + ''::text as studienplan_id, + '' as studienplan_bezeichnung, + '' as studienplan_lehrveranstaltung_id_parent, + tbl_lehrveranstaltung.lehrtyp_kurzbz + FROM lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_lehreinheit USING (lehrveranstaltung_id) + WHERE studiengang_kz = ? + AND studiensemester_kurzbz = ? + "; + + $params[] = $studiengang_kz; + $params[] = $studiensemester_kurzbz; + if (!is_null($semester)) + { + $qry .= ' AND semester = ?'; + $params[] = $semester; + } + if (!is_null($verband)) + { + $qry .= ' AND (orgform_kurzbz = ? OR orgform_kurzbz IS NULL)'; + $params[] = $verband; + } + + if (!empty($only_ids)) + { + + $qry .= ' AND NOT EXISTS (SELECT 1 FROM lehre.tbl_studienplan_lehrveranstaltung where studienplan_id IN ? + AND lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND tbl_lehrveranstaltung.aktiv)'; + + $params[] = $only_ids; + } + + return $this->execReadOnlyQuery($qry, $params); + } + private function getLvsFromStudienplanByStudienplanID($placeholders) + { + return " + SELECT + lehrveranstaltung_id, kurzbz as lv_kurzbz, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, bezeichnung_english as lv_bezeichnung_english, studiengang_kz, + tbl_studienplan_lehrveranstaltung.semester, tbl_lehrveranstaltung.sprache, + ects as lv_ects, semesterstunden, anmerkung, lehre, lehreverzeichnis as lv_lehreverzeichnis, tbl_lehrveranstaltung.aktiv, + planfaktor as lv_planfaktor, planlektoren as lv_planlektoren, planpersonalkosten as lv_planpersonalkosten, + plankostenprolektor as lv_plankostenprolektor, lehrform_kurzbz as lv_lehrform_kurzbz, tbl_lehrveranstaltung.orgform_kurzbz, + tbl_studienplan_lehrveranstaltung.studienplan_id::text as studienplan_id, tbl_studienplan.bezeichnung as studienplan_bezeichnung, tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent::text, + tbl_lehrveranstaltung.lehrtyp_kurzbz + FROM + lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_studienplan_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN lehre.tbl_studienplan USING(studienplan_id) + WHERE + tbl_lehrveranstaltung.aktiv AND ((studienplan_id, tbl_studienplan_lehrveranstaltung.semester) IN ( " . implode(',', $placeholders) . ")) + UNION + "; + } + + public function getAllOe($lv_id, $stg_kz = null) + { + $qry = "SELECT DISTINCT oe_kurzbz + FROM lehre.tbl_studienplan_lehrveranstaltung + JOIN lehre.tbl_studienplan USING(studienplan_id) + JOIN lehre.tbl_studienordnung USING(studienordnung_id) + JOIN public.tbl_studiengang USING(studiengang_kz) + WHERE lehrveranstaltung_id = ? "; + + $params = array($lv_id); + if (!is_null($stg_kz)) + { + $qry .= ' OR studiengang_kz = ?'; + $params[] = $stg_kz; + } + + return $this->execReadOnlyQuery($qry, $params); + } } diff --git a/application/models/organisation/Organisationseinheit_model.php b/application/models/organisation/Organisationseinheit_model.php index 1b1a826aa..b07a90c87 100644 --- a/application/models/organisation/Organisationseinheit_model.php +++ b/application/models/organisation/Organisationseinheit_model.php @@ -217,4 +217,34 @@ class Organisationseinheit_model extends DB_Model oe_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%' "); } + + /** + * Ermittelt die Stundenobergrenze fuer Lektoren + * Dabei wird im OE Baum nach oben nach Stundengrenzen gesucht und die niedrigste Stundengrenze ermittelt + * @param $oe_kurzbz Organisationseinheit + * @param $fixangestellt boolean legt fest ob die Grenze + * fuer Freie oder Fixangestellte Lektoren ermittelt werden soll + + */ + public function getStundengrenze($oe_kurzbz, $fixangestellt = true) + { + $fixfrei = $fixangestellt ? 'fix' : 'frei'; + + $qry = " + WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as + ( + SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit + WHERE oe_kurzbz= ? + UNION ALL + SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes + WHERE o.oe_kurzbz=oes.oe_parent_kurzbz + ) + SELECT oe_kurzbz, warn_semesterstunden_{$fixfrei} AS stunden + FROM oes + JOIN public.tbl_organisationseinheit USING (oe_kurzbz) + ORDER BY warn_semesterstunden_{$fixfrei} ASC + LIMIT 1"; + + return $this->execReadOnlyQuery($qry, array($oe_kurzbz)); + } } diff --git a/application/models/organisation/Studienplan_model.php b/application/models/organisation/Studienplan_model.php index e35ba52fb..5a9097d9a 100644 --- a/application/models/organisation/Studienplan_model.php +++ b/application/models/organisation/Studienplan_model.php @@ -134,4 +134,25 @@ class Studienplan_model extends DB_Model 'prestudent_id' => $prestudent_id ]); } + + public function loadStudienplanLehrveranstaltung($lv_id) + { + $qry = "SELECT studienplan_lehrveranstaltung_id, + semester, + pflicht, + studienplan_id, + koordinator, + studienplan_lehrveranstaltung_id_parent, + lehrveranstaltung_id, + insertamum, + insertvon, + updateamum, + updatevon, + sort, + curriculum, + export + FROM lehre.tbl_studienplan_lehrveranstaltung WHERE studienplan_lehrveranstaltung_id = ? "; + return $this->execReadOnlyQuery($qry, array($lv_id)); + } + } diff --git a/application/models/person/Notiz_model.php b/application/models/person/Notiz_model.php index 2e99d1cdd..e13c6ccb9 100644 --- a/application/models/person/Notiz_model.php +++ b/application/models/person/Notiz_model.php @@ -151,36 +151,36 @@ class Notiz_model extends DB_Model * bestellung_id, lehreinheit_id, anrechnung_id, uid) * @param $id the corresponding id, part of public.tbl_notizzuordnung */ - public function getNotizWithDocEntries($id, $type) + public function getNotizWithDocEntries($id, $type, $withoutTags = true) { - $qry = " - SELECT - n.*, count(dms_id) as countDoc, z.notizzuordnung_id, - (CASE - WHEN n.updateamum >= n.insertamum THEN n.updateamum - ELSE n.insertamum - END) AS lastUpdate, - regexp_replace(n.text, '<[^>]*>', '', 'g') as text_stripped, - TO_CHAR(n.start::timestamp, 'DD.MM.YYYY') AS start_format, - TO_CHAR(n.ende::timestamp, 'DD.MM.YYYY') AS ende_format, - z.notiz_id, z.person_id as id, ? as type_id - - FROM - public.tbl_notiz n - JOIN - public.tbl_notizzuordnung z USING (notiz_id) - LEFT JOIN - public.tbl_notiz_dokument dok USING (notiz_id) - LEFT JOIN - campus.tbl_dms_version USING (dms_id) - WHERE - z.$type = ? - GROUP BY - notiz_id, z.notizzuordnung_id - "; + $this->addSelect("tbl_notiz.*, + count(dms_id) as countDoc, + z.notizzuordnung_id, + (CASE + WHEN tbl_notiz.updateamum >= tbl_notiz.insertamum THEN tbl_notiz.updateamum + ELSE tbl_notiz.insertamum + END) AS lastUpdate, + regexp_replace(tbl_notiz.text, '<[^>]*>', '', 'g') as text_stripped, + TO_CHAR(tbl_notiz.start::timestamp, 'DD.MM.YYYY') AS start_format, + TO_CHAR(tbl_notiz.ende::timestamp, 'DD.MM.YYYY') AS ende_format, + z.notiz_id, + z.person_id as id, + {$type} as type_id + "); - return $this->execQuery($qry, array($type, $id)); + $this->addJoin('public.tbl_notizzuordnung z', 'notiz_id'); + $this->addJoin('public.tbl_notiz_dokument dok', 'notiz_id', 'LEFT'); + $this->addJoin('campus.tbl_dms_version', 'dms_id', 'LEFT'); + $this->db->where("z.{$type}", $id); + + if ($withoutTags) + $this->db->where('tbl_notiz.typ IS NULL'); + + $this->addGroupBy('notiz_id'); + $this->addGroupBy('z.notizzuordnung_id'); + + return $this->load(); } diff --git a/application/models/ressource/Mitarbeiter_model.php b/application/models/ressource/Mitarbeiter_model.php index 836f5d65a..337997b8e 100644 --- a/application/models/ressource/Mitarbeiter_model.php +++ b/application/models/ressource/Mitarbeiter_model.php @@ -278,4 +278,18 @@ class Mitarbeiter_model extends DB_Model return $this->execQuery($qry, $parametersArray); } + + public function isLehrauftragFirma($mitarbeiter_uid) + { + $this->addSelect('firma_id'); + $this->addJoin('public.tbl_benutzer', 'uid = mitarbeiter_uid'); + $this->addJoin('public.tbl_person', 'person_id'); + $this->addJoin('public.tbl_adresse', 'person_id', 'LEFT'); + $this->addOrder('zustelladresse', 'DESC'); + $this->addOrder('firma_id'); + $this->addLimit(1); + $firma_result = $this->loadWhere(array('mitarbeiter_uid' => $mitarbeiter_uid)); + $firma = getData($firma_result)[0]->firma_id; + return !is_null($firma); + } } diff --git a/application/models/ressource/Stundenplandev_model.php b/application/models/ressource/Stundenplandev_model.php index 800540d60..82b3779ab 100644 --- a/application/models/ressource/Stundenplandev_model.php +++ b/application/models/ressource/Stundenplandev_model.php @@ -10,6 +10,9 @@ class Stundenplandev_model extends DB_Model parent::__construct(); $this->dbTable = 'lehre.tbl_stundenplandev'; $this->pk = 'stundenplandev_id'; + + $this->load->model('education/lehreinheit_model', 'LehreinheitModel'); + $this->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel'); } @@ -157,4 +160,84 @@ class Stundenplandev_model extends DB_Model return $this->execQuery($qry, $params); } + public function deleteGroupPlanning($lehreinheit_id, $lehreinheitgruppe_id) + { + $lehreinheit = $this->LehreinheitModel->load($lehreinheit_id); + + if (!hasData($lehreinheit)) + return error ('No Lehreinheit found!'); + + $lehreinheitgruppe = $this->LehreinheitgruppeModel->load($lehreinheitgruppe_id); + + if (!hasData($lehreinheitgruppe)) + return error ('No Lehreinheitgruppe found!'); + + $this->addJoin('lehre.tbl_stundenplan_betriebsmittel', 'stundenplandev_id'); + $this->addJoin('lehre.tbl_lehreinheitgruppe', 'lehreinheit_id'); + $this->db->where('tbl_lehreinheitgruppe.lehreinheitgruppe_id', $lehreinheitgruppe_id); + + $this->db->group_start(); + $this->db->group_start(); + $this->db->where('tbl_lehreinheitgruppe.gruppe_kurzbz IS NOT NULL', null, false); + $this->db->where('tbl_lehreinheitgruppe.gruppe_kurzbz = tbl_stundenplandev.gruppe_kurzbz', null, false); + $this->db->group_end(); + $this->db->or_group_start(); + $this->db->where('tbl_lehreinheitgruppe.gruppe_kurzbz IS NULL', null, false); + $this->db->where('tbl_lehreinheitgruppe.studiengang_kz = tbl_stundenplandev.studiengang_kz', null, false); + $this->db->where('tbl_lehreinheitgruppe.semester = tbl_stundenplandev.semester', null, false); + $this->db->where('tbl_lehreinheitgruppe.verband = tbl_stundenplandev.verband', null, false); + $this->db->where('tbl_lehreinheitgruppe.gruppe = tbl_stundenplandev.gruppe', null, false); + $this->db->group_end(); + $this->db->group_end(); + + $betriebsmittel_result = $this->load(); + $betriebsmittel_array = hasData($betriebsmittel_result) ? getData($betriebsmittel_result) : array(); + if (sizeof($betriebsmittel_array) > 0) + { + return error ('Gruppe kann nicht entfernt werden da bereits Ressourcen zugeordnet wurden'); + } + + $this->addSelect('stundenplandev_id'); + $this->addJoin('lehre.tbl_lehreinheitgruppe', + "tbl_stundenplandev.lehreinheit_id = tbl_lehreinheitgruppe.lehreinheit_id + AND tbl_stundenplandev.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz + AND tbl_stundenplandev.semester = tbl_lehreinheitgruppe.semester + AND trim(COALESCE(tbl_stundenplandev.verband, '')) = trim(COALESCE(tbl_lehreinheitgruppe.verband, '')) + AND trim(COALESCE(tbl_stundenplandev.gruppe, '')) = trim(COALESCE(tbl_lehreinheitgruppe.gruppe, '')) + AND trim(COALESCE(tbl_stundenplandev.gruppe_kurzbz, '')) = trim(COALESCE(tbl_lehreinheitgruppe.gruppe_kurzbz, ''))" + ); + $stundenplan_result = $this->loadWhere(array('tbl_lehreinheitgruppe.lehreinheitgruppe_id' => $lehreinheitgruppe_id)); + + if (hasData($stundenplan_result)) + { + $stundenplan_ids = array_column(getData($stundenplan_result), 'stundenplandev_id'); + $this->db->where_in('stundenplandev_id', $stundenplan_ids); + $delete_result = $this->db->delete('lehre.tbl_stundenplandev'); + + if ($delete_result) + return success('Group deleted successfully from Stundenplandev'); + else + return error('Error deleting Group from Stundenplandev'); + } + } + + public function deleteLektorPlanning($lehreinheit_id, $mitarbeiter_uid) + { + $this->addDistinct('mitarbeiter_uid'); + $this->addSelect('mitarbeiter_uid'); + $stundenplan_result = $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); + $stundenplan_array = hasData($stundenplan_result) ? (getData($stundenplan_result)) : array(); + + if (sizeof($stundenplan_array) <= 1) + return error('Diese/r LektorIn kann nicht aus dem LVPlan entfernt werden da dies der/die letzte verplante LektorIn ist'); + + $this->addJoin('lehre.tbl_stundenplan_betriebsmittel', 'stundenplandev_id'); + $betriebsmittel_result = $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'tbl_stundenplandev.mitarbeiter_uid' => $mitarbeiter_uid)); + $betriebsmittel_array = hasData($betriebsmittel_result) ? getData($betriebsmittel_result) : array(); + + if (sizeof($betriebsmittel_array) > 0) + return error('Gruppe kann nicht entfernt werden da bereits Ressourcen zugeordnet wurden'); + + return $this->delete(array('lehreinheit_id' => $lehreinheit_id, 'mitarbeiter_uid' => $mitarbeiter_uid)); + } } diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index 10f5a6aa1..f34ad07ed 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -42,4 +42,20 @@ class Stundensatz_model extends DB_Model return $this->execQuery($qry, $params); } + + public function getDefaultStundensatz($mitarbeiter_uid, $beginn, $ende = null, $typ = null) + { + $stundensatz_result = $this->getStundensatzByDatum($mitarbeiter_uid, $beginn, $ende, $typ); + $default_stundensatz = hasData($stundensatz_result) ? getData($stundensatz_result)[0]->stundensatz : null; + if (defined('FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ') && !FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ) + { + $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel'); + $echterdv_result = $this->DienstverhaeltnisModel->existsDienstverhaeltnis($mitarbeiter_uid, $beginn, $ende, 'echterdv'); + if (hasData($echterdv_result)) + { + $default_stundensatz = null; + } + } + return $default_stundensatz; + } } \ No newline at end of file diff --git a/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php index f81a2d518..b055ee954 100644 --- a/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php +++ b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php @@ -253,4 +253,25 @@ EOSQL; } return $dvs; } + + public function existsDienstverhaeltnis($mitarbeiter_uid, $start, $ende = null, $vertragsart_kurzbz = null) + { + $this->addOrder('von', 'DESC'); + $this->db->where('mitarbeiter_uid', $mitarbeiter_uid); + if (!is_null($vertragsart_kurzbz)) + $this->db->where('vertragsart_kurzbz', $this->escape($vertragsart_kurzbz)); + + $this->db->where('von <=', $ende); + + if (!is_null($ende)) + { + $this->db->group_start(); + $this->db->where('bis >=', $start); + $this->db->or_where('bis IS NULL', null, false); + $this->db->group_end(); + } + + $this->addLimit(1); + return $this->load(); + } } diff --git a/application/views/LVVerwaltung.php b/application/views/LVVerwaltung.php new file mode 100644 index 000000000..4cebae839 --- /dev/null +++ b/application/views/LVVerwaltung.php @@ -0,0 +1,39 @@ + 'LVVerwaltung', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'vue3' => true, + 'primevue3' => true, + 'tabulator6' => true, + 'tinymce5' => true, + 'tags' => true, + + 'customCSSs' => [ + 'public/css/components/vue-datepicker.css', + 'public/css/components/primevue.css', + 'public/css/Studentenverwaltung.css', + 'public/css/Lvverwaltung.css' + + ], + 'customJSModules' => [ + 'public/js/apps/LVVerwaltung.js' + ] + ); + + $this->load->view('templates/FHC-Header', $includesArray); + +?> +
+ + + +
+load->view('templates/FHC-Footer', $includesArray); ?> + diff --git a/public/css/Lvverwaltung.css b/public/css/Lvverwaltung.css new file mode 100644 index 000000000..1ca3f0be1 --- /dev/null +++ b/public/css/Lvverwaltung.css @@ -0,0 +1,27 @@ +textarea[name="anmerkung"] { + position: absolute; + max-height: 300px; +} + +.lv_table_icon::before +{ + font-family: 'Font Awesome 6 Free'; + font-weight: 900; + margin-left: 5px; + display: inline-block; +} + +.lv_table_icon.icon-modul::before +{ + content: '\f468'; +} + +.lv_table_icon.icon-lv::before +{ + content: '\f466'; +} + +.lv_table_icon.icon-::before +{ + content: '\f073'; +} \ No newline at end of file diff --git a/public/js/api/factory/notiz.js b/public/js/api/factory/notiz.js index 074d4b6a5..ce14269d6 100644 --- a/public/js/api/factory/notiz.js +++ b/public/js/api/factory/notiz.js @@ -16,7 +16,10 @@ */ import person from "./notiz/person.js"; +import lehreinheit from "./notiz/lehreinheit.js"; + export default { - person + person, + lehreinheit }; diff --git a/public/js/api/factory/notiz/lehreinheit.js b/public/js/api/factory/notiz/lehreinheit.js new file mode 100644 index 000000000..d93bb50f9 --- /dev/null +++ b/public/js/api/factory/notiz/lehreinheit.js @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2025 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizLehreinheit/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; diff --git a/public/js/api/lehrveranstaltung.js b/public/js/api/lehrveranstaltung.js new file mode 100644 index 000000000..0499572ba --- /dev/null +++ b/public/js/api/lehrveranstaltung.js @@ -0,0 +1,28 @@ +export default { + + getByLV(lehrveranstaltung_id) + { + return { + method: 'get', + url: '/api/frontend/v1/Lehrveranstaltung/loadByLV/' + encodeURIComponent(lehrveranstaltung_id) + }; + }, + getByStg(studiengang_kz, semester) + { + return ("/api/frontend/v1/Lehrveranstaltung/loadByStudiengang/" + encodeURIComponent(studiengang_kz) + "/" + encodeURIComponent(semester)); + }, + + getByEmpStg(mitarbeiter_uid, stg) + { + return ("/api/frontend/v1/Lehrveranstaltung/loadByEmployee/" + encodeURIComponent(mitarbeiter_uid) + "/" + encodeURIComponent(stg)); + }, + + getTable(url) + { + return { + method: 'get', + url: url + }; + }, + +} \ No newline at end of file diff --git a/public/js/api/lehrveranstaltung/details.js b/public/js/api/lehrveranstaltung/details.js new file mode 100644 index 000000000..db251330a --- /dev/null +++ b/public/js/api/lehrveranstaltung/details.js @@ -0,0 +1,30 @@ +export default { + getStudiensemester() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getStudiensemester/' + }; + }, + getSprache() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getSprache/' + }; + }, + getLehrform() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getLehrform/' + }; + }, + getRaumtyp() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getRaumtyp/' + }; + }, +} diff --git a/public/js/api/lehrveranstaltung/direktgruppe.js b/public/js/api/lehrveranstaltung/direktgruppe.js new file mode 100644 index 000000000..9cd72fcc7 --- /dev/null +++ b/public/js/api/lehrveranstaltung/direktgruppe.js @@ -0,0 +1,26 @@ +export default { + add(newData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/DirektGruppe/add/', + params: newData + }; + }, + delete(deleteData) + { + + return { + method: 'post', + url: '/api/frontend/v1/lv/DirektGruppe/delete/', + params: deleteData + }; + }, + getByLehreinheit(lehreinheit_id) + { + return { + method: 'get', + url: '/api/frontend/v1/lv/DirektGruppe/getByLehreinheit/' + encodeURIComponent(lehreinheit_id) + }; + }, +} diff --git a/public/js/api/lehrveranstaltung/gruppe.js b/public/js/api/lehrveranstaltung/gruppe.js new file mode 100644 index 000000000..12c55509c --- /dev/null +++ b/public/js/api/lehrveranstaltung/gruppe.js @@ -0,0 +1,56 @@ +export default { + + delete(deleteData) + { + + return { + method: 'post', + url: '/api/frontend/v1/lv/gruppe/delete/', + params: deleteData + }; + }, + + add(newData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/gruppe/add/', + params: newData + }; + }, + getByLehreinheit(lehreinheit_id) + { + return { + method: 'get', + url: '/api/frontend/v1/lv/gruppe/getByLehreinheit/' + encodeURIComponent(lehreinheit_id) + }; + }, + + deleteFromLVPlan(deleteData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/gruppe/deleteLVPlan/', + params: deleteData + }; + }, + + +/*------------- details -------- */ + getAll() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/gruppe/getAll/' + }; + }, + + getBenutzer() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/gruppe/getBenutzer/' + }; + } + +} diff --git a/public/js/api/lehrveranstaltung/lehreinheit.js b/public/js/api/lehrveranstaltung/lehreinheit.js new file mode 100644 index 000000000..d8f12e27a --- /dev/null +++ b/public/js/api/lehrveranstaltung/lehreinheit.js @@ -0,0 +1,41 @@ +export default { + copy(data) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lehreinheit/copy/', + params: data + }; + }, + delete(data) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lehreinheit/delete/', + params: data + }; + }, + add(newData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lehreinheit/add/', + params: newData + }; + }, + get(lehreinheit) + { + return { + method: 'get', + url: '/api/frontend/v1/lv/lehreinheit/get/' + encodeURIComponent(lehreinheit) + }; + }, + update(updatedData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lehreinheit/update/', + params: updatedData + }; + }, +} diff --git a/public/js/api/lehrveranstaltung/lektor.js b/public/js/api/lehrveranstaltung/lektor.js new file mode 100644 index 000000000..e8c2fb673 --- /dev/null +++ b/public/js/api/lehrveranstaltung/lektor.js @@ -0,0 +1,78 @@ +export default { + + getLehrfunktionen() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/lektor/getLehrfunktionen/' + }; + }, + + + getLektoren() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/lektor/getLektoren/' + }; + }, + + + getByLehreinheit(lehreinheit_id) + { + return { + method: 'get', + url: '/api/frontend/v1/lv/lektor/getLektorenByLE/' + encodeURIComponent(lehreinheit_id) + }; + }, + + + add(newData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lektor/add/', + params: newData + }; + }, + + update(updatedData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lektor/update/', + params: updatedData + }; + }, + + + deletePerson(deleteData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lektor/deletePerson/', + params: deleteData + }; + }, + deleteFromLVPlan(deleteData) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lektor/deleteLVPlan/', + params: deleteData + }; + }, + getLektorDaten(lehreinheit_id, mitarbeiter_uid) + { + return { + method: 'get', + url: '/api/frontend/v1/lv/lektor/getLektorDaten/' + encodeURIComponent(lehreinheit_id) + '/' + encodeURIComponent(mitarbeiter_uid) + }; + }, + + + + + + +} diff --git a/public/js/api/lehrveranstaltung/setup.js b/public/js/api/lehrveranstaltung/setup.js new file mode 100644 index 000000000..78f78b05b --- /dev/null +++ b/public/js/api/lehrveranstaltung/setup.js @@ -0,0 +1,9 @@ +export default { + getTabs() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getTabs/' + }; + }, +} diff --git a/public/js/api/lehrveranstaltung/studiengangtree.js b/public/js/api/lehrveranstaltung/studiengangtree.js new file mode 100644 index 000000000..fb63db729 --- /dev/null +++ b/public/js/api/lehrveranstaltung/studiengangtree.js @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2025 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 . + */ + +export default { + get(path) { + let url = 'api/frontend/v1/lv/StgTree'; + if (path) + url += '/' + path; + return { + method: 'get', + url + }; + }, + favorites: { + get() { + return { + method: 'get', + url: 'api/frontend/v1/lv/favorites' + }; + }, + set(favorites) { + return { + method: 'post', + url: 'api/frontend/v1/lv/favorites/set', + params: { favorites } + }; + } + } +}; \ No newline at end of file diff --git a/public/js/api/lehrveranstaltung/tag.js b/public/js/api/lehrveranstaltung/tag.js new file mode 100644 index 000000000..3d5a5f2ea --- /dev/null +++ b/public/js/api/lehrveranstaltung/tag.js @@ -0,0 +1,54 @@ +export default { + + getTag(data) + { + return { + method: 'get', + url: 'api/frontend/v1/lv/Tags/getTag', + params: data + }; + }, + + getTags(data) + { + return { + method: 'get', + url: 'api/frontend/v1/lv/Tags/getTags' + }; + }, + + addTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/lv/Tags/addTag', + params: data + }; + }, + + updateTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/lv/Tags/updateTag', + params: data + }; + }, + doneTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/lv/Tags/doneTag', + params: data + }; + }, + + deleteTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/lv/Tags/deleteTag', + params: data + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/lehrveranstaltung/vertrag.js b/public/js/api/lehrveranstaltung/vertrag.js new file mode 100644 index 000000000..601f4b7e3 --- /dev/null +++ b/public/js/api/lehrveranstaltung/vertrag.js @@ -0,0 +1,22 @@ +export default { + + getByLeEmp(lehreinheit_id, mitarbeiter_uid) + { + return { + method: 'get', + url: '/api/frontend/v1/lv/lektor/getLektorDaten/' + encodeURIComponent(lehreinheit_id) + '/' + encodeURIComponent(mitarbeiter_uid), + }; + }, + + cancelByLeEmp(needUpdate) + { + return { + method: 'post', + url: '/api/frontend/v1/lv/lektor/cancelVertrag/', + params: needUpdate + }; + }, + + + +} diff --git a/public/js/apps/LVVerwaltung.js b/public/js/apps/LVVerwaltung.js new file mode 100644 index 000000000..c582f817e --- /dev/null +++ b/public/js/apps/LVVerwaltung.js @@ -0,0 +1,46 @@ +import LVVerwaltung from "../components/LVVerwaltung/LVVerwaltung.js"; +import Phrasen from "../plugins/Phrasen.js"; + +const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router; + +const router = VueRouter.createRouter({ + history: VueRouter.createWebHistory(`/${ciPath}/LVVerwaltung`), + routes: [ + { + name: 'index', + path: `/`, + component: LVVerwaltung + }, + { + name: `byEmp`, + path: `/emp/:emp/:stg?`, + component: LVVerwaltung + }, + /*{ + name: `byFachbereich`, + path: `/fachbereich/:fachbereich/:emp?`, + component: LVVerwaltung + },*/ + { + name: `byStg`, + path: `/stg/:stg/:semester?`, + component: LVVerwaltung + }, + { + path: '/:pathMatch(.*)*', + redirect: '/' + } + ] +}); + +const app = Vue.createApp(); + +app + .use(router) + .use(primevue.config.default, { + zIndex: { + overlay: 1100 + } + }) + .use(Phrasen) + .mount('#main'); diff --git a/public/js/components/LVVerwaltung/Details/Direktinskription.js b/public/js/components/LVVerwaltung/Details/Direktinskription.js new file mode 100644 index 000000000..c7b8e5894 --- /dev/null +++ b/public/js/components/LVVerwaltung/Details/Direktinskription.js @@ -0,0 +1,155 @@ +import {CoreFilterCmpt} from "../../filter/Filter.js"; +import FormForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; +import ApiDirektGruppe from "../../../api/lehrveranstaltung/direktgruppe.js"; +export default{ + name: "LVDirektGruppen", + components: { + CoreFilterCmpt, + FormForm, + FormInput + }, + props: { + lehreinheit_id: Number + }, + inject: { + dropdowns: { + from: 'dropdowns' + }, + }, + computed: { + tabulatorOptions() { + return { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call(ApiDirektGruppe.getByLehreinheit(this.lehreinheit_id)), + ajaxResponse: (url, params, response) => { return response.data || [] }, + columns:[ + {title: this.$p.t('person', 'uid'), field:"uid"}, + {title: this.$p.t('person', 'vorname'), field:"vorname"}, + {title: this.$p.t('person', 'nachname'), field:"nachname"}, + {title: this.$p.t('lehre', 'gruppe'), field:"gruppe_kurzbz"}, + { + title: this.$p.t('global', 'actions'), field: 'actions', + minWidth: 150, + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + let button = document.createElement('button'); + container.className = "d-flex gap-1"; + + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', (event) => { + event.stopPropagation(); + this.deleteDirektGroup(cell.getData().gruppe_kurzbz, cell.getData().uid) + }); + container.append(button); + return container; + }, + frozen: true + }, + ], + layout: 'fitDataFill', + selectable: true, + persistenceID: 'lvverwaltung_direkt_gruppen_2025_05_27_v1', + height: 'auto', + } + } + }, + data() { + return{ + lastSelected: null, + gruppen: [], + tabulatorEvents: [], + showAutocomplete: false, + selectedUser: null, + filteredUsers: [], + abortController: null, + searchTimeout: null, + } + }, + watch: { + lehreinheit_id(n) { + this.$refs.table.reloadTable(); + } + }, + methods:{ + reload() { + this.$refs.table.reloadTable(); + }, + + deleteDirektGroup(gruppe_kurzbz, uid) + { + let deleteData = { + 'gruppe_kurzbz': gruppe_kurzbz, + 'uid': uid, + 'lehreinheit_id': this.lehreinheit_id + } + + this.$api.call(ApiDirektGruppe.delete(deleteData)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(()=> { + this.reload(); + }) + }, + searchUser(event) + { + const query = event.query.toLowerCase().trim(); + this.filteredUsers = this.dropdowns.benutzer_array.filter(user => { + + const fullName = `${user.vorname.toLowerCase()} ${user.nachname.toLowerCase()}`; + const reverseFullName = `${user.nachname.toLowerCase()} ${user.vorname.toLowerCase()}`; + return fullName.includes(query) || reverseFullName.includes(query) || user.uid.toLowerCase().includes(query) || user.studiengang.toLowerCase().includes(query); + }).map(user => ({ + label: user.studiengang + ? `${user.nachname} ${user.vorname} ${user.uid} ${user.studiengang} ${user.semester}` + : `${user.nachname} ${user.vorname} ${user.uid}`, + uid: user.uid + })); + }, + addUser() + { + let newData = { + 'uid': this.selectedUser.uid, + 'lehreinheit_id': this.lehreinheit_id + } + return this.$api.call(ApiDirektGruppe.add(newData)) + .then(result => { + this.reload() + this.selectedUser = '' + }) + .catch(this.$fhcAlert.handleSystemError); + }, + }, + template: ` + + + + + ` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Details/Form.js b/public/js/components/LVVerwaltung/Details/Form.js new file mode 100644 index 000000000..eed65f7ad --- /dev/null +++ b/public/js/components/LVVerwaltung/Details/Form.js @@ -0,0 +1,209 @@ +import CoreForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; + +export default { + name: "LVDetailsForm", + components: { + FormInput, + CoreForm + }, + props: { + data: { + type: Object, + required: true + } + }, + inject: { + dropdowns: { + from: 'dropdowns' + }, + showLVID: { + from: 'permissionLehrveranstaltung', + default: false + }, + showGewichtung: { + from: 'configShowGewichtung', + default: true + } + }, + computed: { + formattedAnmerkung: { + get() { + return (this.data.anmerkung || '').replace(/\\n/g, '\n'); + }, + set(value) { + this.data.anmerkung = (value || '').replace(/\n/g, '\\n'); + } + } + }, + template: ` +
+
+ + + +
+
+ + + + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + + + +
+ +
+ + + +
+
+` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Details/Gruppen.js b/public/js/components/LVVerwaltung/Details/Gruppen.js new file mode 100644 index 000000000..62dae172f --- /dev/null +++ b/public/js/components/LVVerwaltung/Details/Gruppen.js @@ -0,0 +1,195 @@ +import {CoreFilterCmpt} from "../../filter/Filter.js"; +import FormForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; +import ApiGruppe from "../../../api/lehrveranstaltung/gruppe.js"; +export default{ + name: "LVGruppen", + components: { + CoreFilterCmpt, + FormForm, + FormInput + }, + props: { + lehreinheit_id: Number + }, + inject: { + dropdowns: { + from: 'dropdowns' + }, + showLVPlanGruppenDel: { + from: 'permissionGruppenEntfernen', + default: false + }, + }, + computed: { + tabulatorOptions() { + return { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call(ApiGruppe.getByLehreinheit(this.lehreinheit_id)), + ajaxResponse: (url, params, response) => response.data, + columns:[ + {title: this.$p.t('global', 'bezeichnung'), field:"bezeichnung"}, + {title: this.$p.t('global', 'beschreibung'), field:"beschreibung"}, + {title: this.$p.t('lehre', 'studiengang'), field:"studiengang"}, + {title: "ID", field:"id", visible:false}, + { + title: this.$p.t('lehre', 'verplant'), + field:"verplant", + formatter:"tickCross", + hozAlign:"center", + formatterParams: { + tickElement: '', + crossElement: '' + } + }, + { + title: this.$p.t('global', 'actions'), field: 'actions', + minWidth: 150, + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + let button = document.createElement('button'); + container.className = "d-flex gap-1"; + + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', (event) => { + event.stopPropagation(); + this.deleteGroup(cell.getData().lehreinheitgruppe_id) + }); + container.append(button); + + if (this.showLVPlanGruppenDel) + { + button = document.createElement('button'); + container.className = "d-flex gap-2"; + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('lehre', 'auslvplanentfernen'); + button.disabled = !cell.getData().verplant; + button.addEventListener('click', (event) => { + event.stopPropagation(); + this.deleteLVPlan(cell.getData().lehreinheitgruppe_id) + }); + container.append(button); + } + return container; + }, + frozen: true + }, + ], + layout: 'fitDataFill', + selectable: true, + persistenceID: 'lvverwaltung_gruppen_2025_05_27_v1', + height: 'auto', + } + } + }, + data() { + return{ + tabulatorEvents: [], + showAutocomplete: false, + filteredGroups: [], + selectedGroup: null + } + }, + watch: { + lehreinheit_id() { + this.$refs.table.reloadTable(); + } + }, + methods:{ + searchGroup(event) + { + const query = event.query.toLowerCase().trim(); + this.filteredGroups = this.dropdowns.gruppen_array.filter(gruppe => { + return gruppe.gruppe_kurzbz.toLowerCase().includes(query); + }).map(gruppe => ({ + label: gruppe.bezeichnung + ? `${gruppe.gruppe_kurzbz.trim()} (${gruppe.bezeichnung})` + : gruppe.gruppe_kurzbz.trim(), + gid: gruppe.gid, + gruppe_kurzbz: gruppe.gruppe_kurzbz.trim(), + lehrverband: gruppe.lehrverband, + })); + }, + reload() { + this.$refs.table.reloadTable(); + }, + addGroup() + { + let newData = { + 'gid': this.selectedGroup.gid, + 'lehreinheit_id': this.lehreinheit_id, + 'lehrverband': this.selectedGroup.lehrverband, + 'gruppe_kurzbz' : this.selectedGroup.gruppe_kurzbz + } + + return this.$api.call(ApiGruppe.add(newData)) + .then(result => { + this.reload() + this.selectedGroup = '' + }) + .catch(this.$fhcAlert.handleSystemError); + }, + deleteLVPlan(lehreinheitgruppe_id) + { + let deleteData = { + 'lehreinheitgruppe_id': lehreinheitgruppe_id, + 'lehreinheit_id': this.lehreinheit_id + } + + this.$api.call(ApiGruppe.deleteFromLVPlan(deleteData)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(()=> { + this.reload(); + }) + }, + deleteGroup(lehreinheitgruppe_id) + { + let deleteData = { + 'lehreinheitgruppe_id': lehreinheitgruppe_id, + 'lehreinheit_id': this.lehreinheit_id + } + + this.$api.call(ApiGruppe.delete(deleteData)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(()=> { + this.reload(); + }) + }, + }, + template: ` + + + + + ` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js new file mode 100644 index 000000000..772af5a47 --- /dev/null +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -0,0 +1,282 @@ +import CoreSearchbar from "../searchbar/searchbar.js"; +import VerticalSplit from "../verticalsplit/verticalsplit.js"; +import StvVerband from "../Stv/Studentenverwaltung/Verband.js"; +import StvStudiensemester from "../Stv/Studentenverwaltung/Studiensemester.js"; +import LvTable from "./Setup/Table.js"; +import LvTabs from "./Setup/Tabs.js"; + +import ApiDetails from "../../api/lehrveranstaltung/details.js"; +import ApiLektor from "../../api/lehrveranstaltung/lektor.js"; +import ApiGruppe from "../../api/lehrveranstaltung/gruppe.js"; +import ApiStudiengangTree from "../../api/lehrveranstaltung/studiengangtree.js"; +import ApiSearchbar from "../../api/factory/searchbar.js"; + + +export default { + name: "LVVerwaltung", + components: { + CoreSearchbar, + VerticalSplit, + StvVerband, + StvStudiensemester, + LvTable, + LvTabs, + }, + props: { + defaultSemester: String, + lvRoot: String, + permissions: Object, + config: Object + }, + computed: { + type(){ + return this.$route.params.type + } + }, + provide() { + return { + currentSemester: Vue.computed(() => this.studiensemesterKurzbz), + dropdowns: this.dropdowns, + configShowVertragsdetails: this.config.showVertragsdetails, + configShowGewichtung: this.config.showGewichtung, + lehreinheitAnmerkungDefault: this.config.lehreinheitAnmerkungDefault, + lehreinheitRaumtypDefault: this.config.lehreinheitRaumtypDefault, + lehreinheitRaumtypAlternativeDefault: this.config.lehreinheitRaumtypAlternativeDefault, + + permissionLehrveranstaltung: this.permissions['lehre/lehrveranstaltung'], + permissionGruppenEntfernen: this.permissions['lv-plan/gruppenentfernen'], + permissionLektorEntfernen: this.permissions['lv-plan/lektorentfernen'], + } + }, + mounted() { + this.updateFilter(this.$route); + }, + watch: { + '$route'(to) { + this.updateFilter(to); + }, + }, + data() { + return { + selected: [], + studiensemesterKurzbz: this.defaultSemester, + stg: "", + filter: {}, + endpoint: ApiStudiengangTree, + dropdowns: { + studiensemester_array: [], + sprachen_array: [], + lehrform_array: [], + raumtyp_array: [], + lektor_array: [], + gruppen_array: [], + benutzer_array: [], + }, + selectedStudiengang: '', + searchbaroptions: { + cssclass: "position-relative", + calcheightonly: true, + types: [ + "mitarbeiter" + ], + actions: { + employee: { + defaultaction: { + type: "function", + action: (data) => { + this.onSelectEmployee(data.uid); + } + }, + childactions: [ + ] + }, + } + }, + } + }, + methods: { + updateFilter(route) + { + let filter = { ...route.params, ...route.query }; + if (!filter.activeFilter) + { + if (filter.emp) + { + filter.activeFilter = 'employee'; + } + else if (filter.stg) + { + filter.activeFilter = 'verband'; + } + } + this.filter = filter; + }, + handleRowClicked(data) + { + this.selected = data + }, + onSelectEmployee(emp) + { + let stg = this.stg === '' ? null : this.stg; + + this.$router.push({ + name: 'byEmp', + params: { emp, stg, activeFilter: 'employee'}, + }); + }, + + onSelectVerband({link}) + { + let stg = null; + let semester = null; + + if (typeof link === 'number') + stg = link; + else if (typeof link === 'string') + { + [stg, semester] = link.split('/'); + } + + this.stg = stg; + + if (this.filter && this.filter.emp) + { + this.$router.push({ + name: 'byEmp', + params: { emp: this.filter.emp, stg, activeFilter: 'employee' }, + }); + } + else + { + this.$router.push({ + name: 'byStg', + params: { stg, semester, activeFilter: 'verband' }, + }); + } + + this.selected = []; + }, + resetEmployeeFilter() + { + const newParams = { ...this.$route.params, activeFilter: 'verband' }; + if (newParams.stg === '') + this.$router.replace({ name: 'index' }); + else + { + delete newParams.emp; + newParams.semester = null; + this.$router.replace({ name: 'byStg', params: newParams }); + + } + }, + searchfunction(params) { + return this.$api.call(ApiSearchbar.search(params)); + }, + studiensemesterChanged(newValue) { + this.studiensemesterKurzbz = newValue; + this.$refs.lvTable.reload(); + this.selected = []; + }, + }, + created() { + if (this.$route.params.stg !== undefined) + { + this.selectedStudiengang = this.$route.params?.semester !== '' && this.$route.params?.semester + ? `${this.$route.params.stg}/${this.$route.params.semester}` + : this.$route.params.stg; + } + + this.$p.loadCategory(['lehre', 'person']) + + this.$api.call(ApiDetails.getStudiensemester()) + .then(result => { + this.dropdowns.studiensemester_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(ApiDetails.getSprache()) + .then(result => { + this.dropdowns.sprachen_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(ApiDetails.getLehrform()) + .then(result => { + this.dropdowns.lehrform_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(ApiDetails.getRaumtyp()) + .then(result => { + this.dropdowns.raumtyp_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(ApiLektor.getLehrfunktionen()) + .then(result => { + this.dropdowns.lehrfunktion_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(ApiLektor.getLektoren()) + .then(result => { + this.dropdowns.lektor_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(ApiGruppe.getAll()) + .then(result => { + this.dropdowns.gruppen_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(ApiGruppe.getBenutzer()) + .then(result => { + this.dropdowns.benutzer_array = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + + template: ` +
+ +
+
+ + +
+ + + + +
+
+
+
` +}; diff --git a/public/js/components/LVVerwaltung/Lektor/Daten.js b/public/js/components/LVVerwaltung/Lektor/Daten.js new file mode 100644 index 000000000..bb40f56fe --- /dev/null +++ b/public/js/components/LVVerwaltung/Lektor/Daten.js @@ -0,0 +1,270 @@ +import {CoreFilterCmpt} from "../../filter/Filter.js"; +import CoreForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; +import ApiLektor from "../../../api/lehrveranstaltung/lektor.js"; + +export default{ + name: "LVLektorDaten", + components: { + CoreFilterCmpt, + CoreForm, + FormInput + }, + props: { + lehreinheit_id: Number, + mitarbeiter_uid: String + }, + emits: [ + 'changedLektor', + 'changedCosts', + ], + inject: { + dropdowns: { + from: 'dropdowns' + } + }, + + data() { + return{ + original: null, + data: null, + changed: {}, + internal_mitarbeiter_uid: null, + filteredLektor: [], + } + }, + computed: { + changedLength() { + return Object.keys(this.changed).length; + }, + berechneteGesamtkosten() { + if (!this.data) return 0; + + const stunden = Number(this.data.semesterstunden) || 0; + const stundensatz = Number(this.data.stundensatz) || 0; + + return (stunden * stundensatz).toFixed(2); + } + }, + watch: { + lehreinheit_id: + { + deep: true, + handler(newVal, oldVal) { + this.data = null; + this.original = null; + this.internal_mitarbeiter_uid = null; + } + }, + mitarbeiter_uid: + { + deep: true, + handler(newVal, oldVal) { + this.internal_mitarbeiter_uid = newVal; + + if (newVal === null) + this.data = null; + else if (newVal !== undefined && this.lehreinheit_id !== undefined) + this.getLektorData(); + } + + }, + data: { + handler(newValue) { + if (newValue === null) + { + this.changed = {} + return + } + let changed = {}; + + let keys = Object.keys(this.original); + + for (let key of keys) + { + if (this.original[key] !== newValue[key]) + changed[key] = newValue[key]; + } + this.changed = changed; + }, + deep: true + }, + }, + methods: { + getLektorData() + { + if (!this.lehreinheit_id || !this.internal_mitarbeiter_uid) + return; + + return this.$api.call(ApiLektor.getLektorDaten(this.lehreinheit_id, this.internal_mitarbeiter_uid)) + .then(result => { + this.data = result.data; + this.original = { ...this.data }; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + updateDaten() + { + if (!this.changedLength) + return; + + if (this.changed.mitarbeiter_uid && this.changed.mitarbeiter_uid.uid) + { + this.changed.mitarbeiter_uid = this.changed.mitarbeiter_uid.uid; + } + this.$refs.form.clearValidation(); + + let updatedData = { + lehreinheit_id: this.lehreinheit_id, + mitarbeiter_uid: this.mitarbeiter_uid, + formData: this.changed + } + this.$refs.form.call(ApiLektor.update(updatedData)) + .then(result => { + let error = result.data?.error; + if (error) + this.$fhcAlert.alertWarning(error) + this.original = {...this.data}; + + if (this.changed.mitarbeiter_uid) + { + this.$emit('changedLektor', this.changed.mitarbeiter_uid); + } + if (this.changed.semesterstunden || this.changed.stundensatz) + { + this.$emit('changedCosts'); + } + this.changed = {}; + + }) + .catch(this.$fhcAlert.handleSystemError); + }, + searchLektor(event) + { + const query = event.query.toLowerCase().trim(); + this.filteredLektor = this.dropdowns.lektor_array.filter(lektor => { + const fullName = `${lektor.vorname.toLowerCase()} ${lektor.nachname.toLowerCase()}`; + const reverseFullName = `${lektor.nachname.toLowerCase()} ${lektor.vorname.toLowerCase()}`; + return fullName.includes(query) || reverseFullName.includes(query) || lektor.uid.toLowerCase().includes(query); + }).map(lektor => ({ + label: `${lektor.nachname} ${lektor.vorname} (${lektor.uid})`, + uid: lektor.uid + })); + }, + + }, + created() { + this.getLektorData() + }, + template: ` + +
+ +
+
+ {{$p.t('lehre', 'daten')}} + + +
+
+ ` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Lektor/Table.js b/public/js/components/LVVerwaltung/Lektor/Table.js new file mode 100644 index 000000000..373a8955c --- /dev/null +++ b/public/js/components/LVVerwaltung/Lektor/Table.js @@ -0,0 +1,223 @@ +import {CoreFilterCmpt} from "../../filter/Filter.js"; +import FormForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; +import ApiLektor from "../../../api/lehrveranstaltung/lektor.js"; + + +export default{ + name: "LVLektorTable", + components: { + CoreFilterCmpt, + FormForm, + FormInput + }, + props: { + lehreinheit_id: Number, + selected: String + }, + inject: { + dropdowns: { + from: 'dropdowns' + }, + showLVPlanLektorDel: { + from: 'permissionLektorEntfernen', + default: false + }, + }, + emits: ['update:selected'], + + data() { + return { + tabulatorEvents: [ + { + event: 'rowSelectionChanged', + handler: this.lektorSelected + } + ], + showAutocomplete: false, + filteredLektor: [], + selectedLektor: '' + } + }, + computed: { + tabulatorOptions() { + return { + + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call(ApiLektor.getByLehreinheit(this.lehreinheit_id)), + ajaxResponse: (url, params, response) => { return response.data || [] }, + columns:[ + {title: this.$p.t('person', 'nachname'), field:"nachname"}, + {title: this.$p.t('person', 'vorname'), field:"vorname"}, + {title: this.$p.t('person', 'uid'), field:"mitarbeiter_uid"}, + {title: this.$p.t('lehre', 'lehreinheit_id'), field:"lehreinheit_id"}, + { + title: this.$p.t('lehre', 'verplant'), + field:"verplant", + formatter:"tickCross", + hozAlign:"center", + formatterParams: { + tickElement: '', + crossElement: '' + } + }, + { + title: this.$p.t('global', 'actions'), field: 'actions', + minWidth: 150, + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + let button = document.createElement('button'); + + container.className = "d-flex gap-2"; + + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', (event) => { + event.stopPropagation(); + this.deletePerson(cell.getData().mitarbeiter_uid, cell.getData().lehreinheit_id); + }); + + container.append(button); + if (this.showLVPlanLektorDel) + { + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.disabled = !cell.getData().verplant; + button.title = this.$p.t('ui', 'auslvplanentfernen'); + button.addEventListener('click', (event) => { + event.stopPropagation(); + this.deleteLVPlan(cell.getData().mitarbeiter_uid, cell.getData().lehreinheit_id) + }); + container.append(button); + } + + return container; + }, + frozen: true + }, + ], + layout: 'fitDataFill', + height: 'auto', + selectable: true, + selectableRangeMode: 'click', + selectableRows:1, + persistenceID: 'lehrveranstaltungen_lektor_table_2025_05_27_v1', + }}, + }, + mounted(){ + }, + watch: { + lehreinheit_id() { + this.$refs.table.tabulator.setData('api/frontend/v1/lv/lektor/getLektorenByLE/' + encodeURIComponent(this.lehreinheit_id)); + }, + }, + methods:{ + lektorSelected(data) + { + if (data.length > 0) + { + let mitarbeiter_uid = data[0].mitarbeiter_uid; + this.$emit('update:selected', mitarbeiter_uid); + } + else + { + this.$emit('update:selected', null); + } + }, + reload() { + this.$refs.table.reloadTable(); + }, + + deleteLVPlan(uid, lehreinheit_id) + { + let deleteData = { + 'mitarbeiter_uid': uid, + 'lehreinheit_id': lehreinheit_id, + } + + this.$api.call(ApiLektor.deleteFromLVPlan(deleteData)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(()=> { + this.reload(); + }) + }, + deletePerson(uid, lehreinheit_id) + { + let deleteData = { + 'mitarbeiter_uid': uid, + 'lehreinheit_id': lehreinheit_id, + } + + this.$api.call(ApiLektor.deletePerson(deleteData)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + this.reload(); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(()=> { + + }) + }, + searchLektor(event) + { + const query = event.query.toLowerCase().trim(); + this.filteredLektor = this.dropdowns.lektor_array.filter(lektor => { + const fullName = `${lektor.vorname.toLowerCase()} ${lektor.nachname.toLowerCase()}`; + const reverseFullName = `${lektor.nachname.toLowerCase()} ${lektor.vorname.toLowerCase()}`; + return fullName.includes(query) || reverseFullName.includes(query) || lektor.uid.toLowerCase().includes(query); + }).map(lektor => ({ + label: `${lektor.nachname} ${lektor.vorname} (${lektor.uid})`, + uid: lektor.uid + })); + }, + addLektor() + { + let newData = { + 'mitarbeiter_uid': this.selectedLektor.uid, + 'lehreinheit_id': this.lehreinheit_id + } + + this.$api.call(ApiLektor.add(newData)) + .then(result => { + this.reload() + this.selectedLektor = '' + }) + .catch(this.$fhcAlert.handleSystemError); + }, + + }, + template: ` + + + + +` +}; + + diff --git a/public/js/components/LVVerwaltung/Lektor/Vertrag.js b/public/js/components/LVVerwaltung/Lektor/Vertrag.js new file mode 100644 index 000000000..f36fad8e0 --- /dev/null +++ b/public/js/components/LVVerwaltung/Lektor/Vertrag.js @@ -0,0 +1,161 @@ +import {CoreFilterCmpt} from "../../filter/Filter.js"; +import CoreForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; +import ApiVertrag from "../../../api/lehrveranstaltung/vertrag.js"; + +export default{ + name: "LVLektorVertrag", + components: { + CoreFilterCmpt, + CoreForm, + FormInput + }, + emits: [ + 'canceledVertrag' + ], + props: { + lehreinheit_id: Number, + mitarbeiter_uid: String + }, + + inject: { + dropdowns: { + from: 'dropdowns' + }, + showVertragsdetails: { + from: 'configShowVertragsdetails', + default: false + } + }, + + data() { + return{ + data: null, + internal_mitarbeiter_uid: null, + } + }, + watch: { + lehreinheit_id: + { + deep: true, + handler(newVal, oldVal) { + this.data = null; + this.internal_mitarbeiter_uid = null; + } + + }, + mitarbeiter_uid: + { + deep: true, + handler(newVal, oldVal) { + this.internal_mitarbeiter_uid = newVal; + + if (newVal === null) + this.data = null; + else if (newVal !== undefined && this.lehreinheit_id !== undefined) + this.getLektorVertrag(); + } + }, + }, + computed: { + vertragsstatus() { + if (!this.data || !this.data.vertrag) return; + + const betragVertrag = Number(this.data.vertrag.betrag) || 0; + const stundenVertrag = Number(this.data.vertrag.vertragsstunden) || 0; + + const semStunden = Number(this.data.semesterstunden) || 0; + const stundensatz = Number(this.data.stundensatz) || 0; + + const kostenAktuell = semStunden * stundensatz; + + return (stundenVertrag !== semStunden || betragVertrag !== kostenAktuell) ? 'Geändert' : (this.data.vertrag.vertragsstatus || ''); + }, + }, + methods: { + getLektorVertrag () + { + if (this.showVertragsdetails === false) + return; + + if (!this.lehreinheit_id || !this.internal_mitarbeiter_uid) + return; + + this.$api.call(ApiVertrag.getByLeEmp(this.lehreinheit_id, this.internal_mitarbeiter_uid)) + .then(result => { + this.data = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + + cancelVertrag() + { + let needUpdate = { + vertrag_id: this.data.vertrag.vertrag_id, + mitarbeiter_uid: this.mitarbeiter_uid, + lehreinheit_id: this.lehreinheit_id + } + this.$api.call(ApiVertrag.cancelByLeEmp(needUpdate)) + .then(result => { + this.data.vertrag = null; + this.$emit('canceledVertrag'); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + }, + // language=HTML + template: ` + +
+ {{$p.t('lehre', 'vertragsdetails')}} + {{ data === null ? ' – Noch kein Vertrag' : '' }} + + +
+
+ ` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Setup/Table.js b/public/js/components/LVVerwaltung/Setup/Table.js new file mode 100644 index 000000000..9b0ae71f3 --- /dev/null +++ b/public/js/components/LVVerwaltung/Setup/Table.js @@ -0,0 +1,683 @@ +import {CoreFilterCmpt} from "../../filter/Filter.js"; +import BsModal from "../../Bootstrap/Modal.js"; +import DetailsForm from "../Details/Form.js"; +import CoreTag from '../../Tag/Tag.js'; +import { tagHeaderFilter } from '../../../../js/tabulator/filters/extendedHeaderFilter.js'; +import { extendedHeaderFilter } from "../../../../js/tabulator/filters/extendedHeaderFilter.js"; + +import ApiLv from "../../../api/lehrveranstaltung.js"; +import ApiTag from "../../../api/lehrveranstaltung/tag.js"; +import ApiLehreinheit from "../../../api/lehrveranstaltung/lehreinheit.js"; + +export default { + name: "LVVerwaltungTable", + components: { + CoreFilterCmpt, + BsModal, + DetailsForm, + CoreTag + + }, + props: { + selected: Object, + filter: { + type: Object, + default: () => ({}) + } + }, + inject: { + currentSemester: { + from: 'currentSemester' + }, + lehreinheitAnmerkungDefault: { + from: 'lehreinheitAnmerkungDefault', + default: '' + }, + lehreinheitRaumtypDefault: { + from: 'lehreinheitRaumtypDefault', + default: '' + }, + lehreinheitRaumtypAlternativeDefault: { + from: 'lehreinheitRaumtypAlternativeDefault', + default: '' + } + }, + emits: [ + 'update:selected', + 'row-clicked' + ], + watch: { + filter: { + handler() { + if (this.$refs.table && this.$refs.table.tabulator) + { + this.expanded = []; + this.reload(); + } + }, + deep: true, + + } + }, + data() { + return { + fieldTitleMap: { + lv_kurzbz: ['lehre', 'kurzbz'], + tags: ['ui', 'tags'], + lehrveranstaltung_id: ['lehre', 'lehrveranstaltung_id'], + lv_bezeichnung: ['ui', 'bezeichnung'], + lv_bezeichnung_english: ['lehre', 'bezeichnungeng'], + lv_studiengang_kz: ['lehre', 'studiengangskennzahlLehre'], + studiengang: ['lehre', 'studiengang'], + semester: ['lehre', 'semester'], + sprache: ['global', 'sprache'], + lv_ects: ['lehre', 'ects'], + semesterstunden: ['lehre', 'semesterstunden'], + anmerkung: ['global', 'anmerkung'], + lehre: ['lehre', 'lehre'], + lehreverzeichnis: ['ui', 'lehreverzeichnis'], + aktiv: ['person', 'aktiv'], + planfaktor: ['ui', 'planfaktor'], + planlektoren: ['ui', 'planlektoren'], + planpersonalkosten: ['ui', 'planpersonalkosten'], + plankostenprolektor: ['ui', 'plankostenprolektor'], + orgform_kurzbz: ['lehre', 'organisationsform'], + studienplan_id: ['ui', 'studienplan_id'], + studienplan_bezeichnung: ['ui', 'studienplan_bezeichnung'], + lehrtyp_kurzbz: ['ui', 'lehrtyp_kurzbz'], + lehrform_kurzbz: ['lehre', 'lehrform'], + le_planstunden: ['lehre', 'leplanstunden'], + lehreinheit_id: ['lehre', 'lehreinheit_id'], + stundenblockung: ['lehre', 'stundenblockung'], + wochenrythmus: ['lehre', 'wochenrhytmus'], + startkw: ['lehre', 'startkw'], + raumtyp: ['lehre', 'raumtyp'], + raumtypalternativ: ['lehre', 'raumtypalternativ'], + gruppen: ['lehre', 'gruppen'], + lektoren: ['lehre', 'lehrende'], + }, + + expanded: [], + selectedColumnValues: [], + tagEndpoint: ApiTag, + iconPath: FHC_JS_DATA_STORAGE_OBJECT.app_root + '/skin/images/lehrtyp_', + tabulatorEvents: [ + { + event: 'rowSelectionChanged', + handler: this.rowSelectionChanged + }, + + { + event: 'dataProcessed', + handler: (data) => { + this.reexpandRows() + this.$emit('update:selected', {}) + } + }, + { + event: 'dataTreeRowExpanded', + handler: (data) => { + this.getExpandedRows() + } + },{ + event: 'dataTreeRowCollapsed', + handler: (data) => { + this.getExpandedRows() + } + } + + ], + formData: {}, + lv_info: false, + lv_info_default: { + stundenblockung: 2, + wochenrythmus: 1, + studiensemester_kurzbz: this.currentSemester, + lehrform_kurzbz: 'UE', + anmerkung: this.lehreinheitAnmerkungDefault.replace("'","\'"), + raumtyp: this.lehreinheitRaumtypDefault, + raumtypalternativ: this.lehreinheitRaumtypAlternativeDefault, + lehrfach_id: '' + + } + } + }, + computed: { + tabulatorOptions() { + return { + index: 'uniqueindex', + ajaxURL: 'dummy', + ajaxRequestFunc: async (url, config, params) => { + let realUrl = this.buildApiUrl(); + if (realUrl) + return this.$api.call(ApiLv.getTable(this.buildApiUrl())); + }, + ajaxResponse: (url, params, response) => { return response?.data || [] }, + dataTree: true, + initialSort:[ + {column: 'lv_bezeichnung', dir: 'desc'}, + ], + dataTreeElementColumn: "lv_kurzbz", + dataTreeFilter: true, + dataTreeStartExpanded: false, + dataTreeCollapseElement: '', + dataTreeExpandElement: '', + columnDefaults: { + tooltip: true, + headerFilter: "input", + headerFilterFunc: extendedHeaderFilter + }, + layout: 'fitDataStretch', + layoutColumnsOnNewData: false, + height: '100%', + selectableRowsRangeMode: 'click', + selectableRows: true, + rowContextMenu: (component, e) => { + + return [ + { + label: "LV-Teil kopieren", + menu: [ + { + label: "Alles", + action: (e, row) => + { + this.copyLehreinheit(row, "alle"); + }, + }, + { + label: "Nur LV-Teil", + action: (e, row) => + { + this.copyLehreinheit(row, "lvteil"); + }, + }, + { + label: "Nur mit Gruppen", + action: (e, row) => + { + this.copyLehreinheit(row, "halb"); + }, + }, + { + label: "Nur mit Lehrenden", + action: (e, row) => + { + this.copyLehreinheit(row, "lektoren"); + }, + }, + ], + }, + { + label: "Entfernen", + action: (e, row) => { + this.deleteLehreinheit(row) + }, + }, + ]; + }, + + persistenceID: 'lehrveranstaltungen_2025_05_27_v1', + columns: [ + { + title: this.$p.t('lehre', 'kurzbz'), + field: "lv_kurzbz", + headerFilterFuncParams: {field: 'lv_kurzbz'}, + headerFilter: true, + formatter: (cell, formatterParams) => { + const rowData = cell.getRow().getData(); + const iconKey = (rowData.lehrtyp_kurzbz || '').toLowerCase(); + + const span = document.createElement('span'); + span.classList.add('lv_table_icon', `icon-${iconKey}`); + span.title = iconKey || 'LV-Teil'; + return span; + }, + + cellClick: (e, cell) => { + cell.getRow().treeToggle(); + } + }, + { + title: 'Tags', + field: 'tags', + tooltip: false, + headerFilter: "input", + headerFilterFunc: tagHeaderFilter, + headerFilterFuncParams: {field: 'tags'}, + formatter: (cell) => { + let tags = cell.getValue(); + if (!tags) return; + + let container = document.createElement('div'); + container.className = "d-flex gap-1"; + + let parsedTags = JSON.parse(tags); + let maxVisibleTags = 2; + + const rowData = cell.getRow().getData(); + if (rowData._tagExpanded === undefined) { + rowData._tagExpanded = false; + } + + const renderTags = () => { + container.innerHTML = ''; + parsedTags = parsedTags.filter(item => item !== null); + const tagsToShow = rowData._tagExpanded ? parsedTags : parsedTags.slice(0, maxVisibleTags); + + tagsToShow.forEach(tag => { + if (!tag) return; + let tagElement = document.createElement('span'); + tagElement.innerText = tag.beschreibung; + tagElement.title = tag.notiz; + tagElement.className = "tag " + tag.style; + if (tag.done) tagElement.className += " tag_done"; + + tagElement.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + this.$refs.tagComponent.editTag(tag.id); + }); + + container.appendChild(tagElement); + }); + + if (parsedTags.length > maxVisibleTags) { + let toggle = document.createElement('button'); + toggle.innerText = (rowData._tagExpanded ? '- ' : '+ ') + (parsedTags.length - maxVisibleTags); + toggle.className = "display_all"; + toggle.title = rowData._tagExpanded ? "Tags ausblenden" : "Tags einblenden"; + + toggle.addEventListener('click', () => { + rowData._tagExpanded = !rowData._tagExpanded; + renderTags(); + }); + + container.appendChild(toggle); + } + }; + + renderTags(); + return container; + }, + width: 150, + }, + { + title: this.$p.t('lehre', 'lehrveranstaltung_id'), + field: "lehrveranstaltung_id", + headerFilterFuncParams: {field: 'lehrveranstaltung_id'}, + headerFilter: true + }, + {title: this.$p.t('ui', 'bezeichnung'), field: "lv_bezeichnung", headerFilter: true, headerFilterFuncParams: {field: 'lv_bezeichnung'}}, + {title: this.$p.t('lehre', 'bezeichnungeng'), field: "lv_bezeichnung_english", headerFilter: true, headerFilterFuncParams: {field: 'lv_bezeichnung_english'}}, + { + title: this.$p.t('lehre', 'studiengangskennzahlLehre'), + field: "lv_studiengang_kz", + headerFilter: true, + headerFilterFuncParams: {field: 'lv_studiengang_kz'} + }, + {title: this.$p.t('lehre', 'studiengang'), field: "studiengang", headerFilter: true, headerFilterFuncParams: {field: 'studiengang'}}, + {title: this.$p.t('lehre', 'semester'), field: "semester", headerFilter: true, headerFilterFuncParams: {field: 'semester'}}, + {title: this.$p.t('global', 'sprache'), field: "sprache", headerFilter: true, headerFilterFuncParams: {field: 'sprache'}}, + {title: this.$p.t('lehre', 'ects'), field: "lv_ects", headerFilter: true, headerFilterFuncParams: {field: 'lv_ects'}}, + {title: this.$p.t('lehre', 'semesterstunden'), field: "semesterstunden", headerFilter: true, headerFilterFuncParams: {field: 'semesterstunden'}}, + {title: this.$p.t('global', 'anmerkung'), field: "anmerkung", headerFilter: true, headerFilterFuncParams: {field: 'anmerkung'}}, + {title: this.$p.t('lehre', 'lehre'), field: "lehre", headerFilter: true, headerFilterFuncParams: {field: 'lehre'}}, + {title: "Lehreverzeichnis", field: "lehreverzeichnis", headerFilter: true, headerFilterFuncParams: {field: 'lehreverzeichnis'}}, + {title: this.$p.t('person', 'aktiv'), field: "aktiv", headerFilter: true, headerFilterFuncParams: {field: 'aktiv'}}, + {title: "Planfaktor", field: "planfaktor", headerFilter: true, headerFilterFuncParams: {field: 'planfaktor'}}, + {title: "Planlektoren", field: "planlektoren", headerFilter: true, headerFilterFuncParams: {field: 'planlektoren'}}, + {title: "planpersonalkosten", field: "planpersonalkosten", headerFilter: true, headerFilterFuncParams: {field: 'planpersonalkosten'}}, + {title: "plankostenprolektor", field: "plankostenprolektor", headerFilter: true, headerFilterFuncParams: {field: 'plankostenprolektor'}}, + {title: this.$p.t('ui', 'organisationsform'), field: "orgform_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'orgform_kurzbz'}}, + {title: this.$p.t('ui', 'studienplan_id'), field: "studienplan_id", headerFilter: true, headerFilterFuncParams: {field: 'studienplan_id'}}, + {title: "studienplan_bezeichnung", field: "studienplan_bezeichnung", headerFilter: true, headerFilterFuncParams: {field: 'studienplan_bezeichnung'}}, + {title: "lehrtyp_kurzbz", field: "lehrtyp_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'lehrtyp_kurzbz'}}, + {title: this.$p.t('lehre', 'lehrform'), field: "lehrform_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'lehrform_kurzbz'}}, + {title: this.$p.t('lehre', 'leplanstunden'), field: "le_planstunden", headerFilter: true, headerFilterFuncParams: {field: 'le_planstunden'}}, + {title: this.$p.t('lehre', 'lehreinheit_id'), field: "lehreinheit_id", headerFilter: true, headerFilterFuncParams: {field: 'lehreinheit_id'}}, + {title: this.$p.t('lehre', 'stundenblockung'), field: "stundenblockung", headerFilter: true, headerFilterFuncParams: {field: 'stundenblockung'}}, + {title: this.$p.t('lehre', 'wochenrhytmus'), field: "wochenrythmus", headerFilter: true, headerFilterFuncParams: {field: 'wochenrythmus'}}, + {title: this.$p.t('lehre', 'startkw'), field: "startkw", headerFilter: true, headerFilterFuncParams: {field: 'startkw'}}, + {title: this.$p.t('lehre', 'raumtyp'), field: "raumtyp", headerFilter: true, headerFilterFuncParams: {field: 'raumtyp'}}, + {title: this.$p.t('lehre', 'raumtypalternativ'), field: "raumtypalternativ", headerFilter: true, headerFilterFuncParams: {field: 'raumtypalternativ'}}, + {title: this.$p.t('lehre', 'gruppen'), field: "gruppen", headerFilter: true, headerFilterFuncParams: {field: 'gruppen'}}, + {title: this.$p.t('lehre', 'lehrende'), field: "lektoren", headerFilter: true, headerFilterFuncParams: {field: 'lektoren'}}, + ], + } + + } + }, + + mounted() { + if (this.shouldAutoLoad()) + { + this.reload(); + } + }, + methods: { + shouldAutoLoad() { + return this.filter && this.filter.activeFilter; + }, + async reload() + { + + if (this.shouldAutoLoad) + { + this.$refs.table.reloadTable(); + } + }, + rowSelectionChanged(data) { + this.selectedRows = this.$refs.table.tabulator.getSelectedRows(); + this.selectedColumnValues = this.selectedRows.filter(row => row.getData().lehreinheit_id !== undefined).map(row => row.getData().lehreinheit_id); + + if (data[0]?.lehreinheit_id !== undefined && this.selectedColumnValues.length === 1) + { + this.$emit('update:selected', [data[0]]); + this.lv_info = false + } + else if (data[0]?.lehrveranstaltung_id) + { + this.$emit('update:selected', {}); + this.getLVInfos(data[0]); + } + }, + getLVInfos(data) + { + this.$api.call(ApiLv.getByLV(data.lehrveranstaltung_id)) + .then(result => { + + if (result.data?.lehrfach_id === undefined + && Array.isArray(result.data?.lehrfaecher)) + { + const match = result.data.lehrfaecher?.find( + lf => lf.lehrfach?.startsWith(result.data.lvbezeichnung) + ); + if (match) + { + result.data.lehrfach_id = match.lehrveranstaltung_id; + } + } + this.lv_info = {...this.lv_info_default, ...result.data}; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + buildApiUrl() + { + if (this.filter.activeFilter === 'employee' && this.filter.emp) + { + return this.$api.getUri(ApiLv.getByEmpStg( + this.filter.emp, + this.filter.stg + )); + } + + if (this.filter.activeFilter === 'verband' && this.filter.stg) + { + return this.$api.getUri(ApiLv.getByStg( + this.filter.stg, + this.filter.semester + )); + } + }, + resetEmployeeFilter() + { + const newFilter = { ...this.filter }; + delete newFilter.emp; + newFilter.activeFilter = 'verband'; + }, + buildParams() + { + const params = {}; + for (const [key, value] of Object.entries(this.filter)) { + if (value !== undefined && value !== null) { + params[key] = value; + } + } + return params; + }, + showLehreinheitModal() { + this.resetModal(); + this.$refs.lehreinheitModal.show(); + }, + addNewLehreinheit() + { + return this.$api.call(ApiLehreinheit.add(this.lv_info)) + .then(result => { + this.$refs.lehreinheitModal.hide() + this.reload() + }) + .catch(this.$fhcAlert.handleSystemError); + }, + resetModal() + { + this.lv_info_default = { + stundenblockung: 2, + wochenrythmus: 1, + studiensemester_kurzbz: this.currentSemester, + lehrform_kurzbz: 'UE', + anmerkung: this.lehreinheitAnmerkungDefault.replace("'","\'"), + raumtyp: this.lehreinheitRaumtypDefault, + raumtypalternativ: this.lehreinheitRaumtypAlternativeDefault, + lehrfach_id: '' + } + }, + addedTag(addedTag) + { + const table = this.$refs.table.tabulator; + + this.selectedRows.forEach(row => + { + if (Array.isArray(addedTag.response)) + { + addedTag.response.forEach(tag => { + + const all = this.getAllRows(table.getRows()); + const targetRow = all.find(row => row.getData().lehreinheit_id === tag.lehreinheit_id); + if (targetRow) + { + const rowData = targetRow.getData(); + let tags = []; + try { + tags = JSON.parse(rowData.tags || '[]'); + } catch (e) {} + + const tagExists = tags.some((t) => t.id === tag.id); + if (!tagExists) + { + addedTag.id = tag.id; + tags.push({ ...addedTag }); + targetRow.update({ tags: JSON.stringify(tags) }); + targetRow.reformat(); + } + } + }); + } + }); + }, + deletedTag(deletedTag) { + const table = this.$refs.table.tabulator; + const all = this.getAllRows(table.getRows()); + + const targetRow = all.find(row => { + const rowData = row.getData(); + + let tags = []; + try { + tags = JSON.parse(rowData.tags || '[]'); + } catch (e) {} + + return tags.some(tag => tag.id === deletedTag); + }); + + if (targetRow) { + const rowData = targetRow.getData(); + let tags = []; + + try { + tags = JSON.parse(rowData.tags || '[]'); + } catch (e) {} + + const filteredTags = tags.filter(t => t.id !== deletedTag); + const updatedTags = JSON.stringify(filteredTags); + + if (updatedTags !== rowData.tags) { + targetRow.update({ + tags: updatedTags + }); + + targetRow.reformat(); + } + } + }, + + updatedTag(updatedTag) { + const table = this.$refs.table.tabulator; + const all = this.getAllRows(table.getRows()); + + const targetRow = all.find(row => { + const rowData = row.getData(); + let tags = []; + + try { + tags = JSON.parse(rowData.tags || '[]'); + } catch (e) {} + + return tags.some(t => t?.id === updatedTag.id); + }); + + if (targetRow) + { + const rowData = targetRow.getData(); + let tags = []; + try { + tags = JSON.parse(rowData.tags || '[]'); + } catch (e) {} + + let changed = false; + + const tagIndex = tags.findIndex(tag => tag?.id === updatedTag.id); + if (tagIndex !== -1) { + tags[tagIndex] = { ...updatedTag }; + changed = true; + } + + if (changed) + { + targetRow.update({ + tags: JSON.stringify(tags), + }); + targetRow.reformat(); + } + } + }, + async copyLehreinheit(row, art) + { + let data = { + lehreinheit_id: row.getData().lehreinheit_id, + art: art + } + + return this.$api.call(ApiLehreinheit.copy(data)) + .then(result => { + this.reload() + }) + .catch(this.$fhcAlert.handleSystemError) + }, + + async getExpandedRows() { + this.expanded = []; + let rows = this.$refs.table.tabulator.getRows(); + let allRows = this.getAllRows(rows); + allRows.forEach(row => { + if (row.getTreeChildren().length > 0 && row.isTreeExpanded()) + { + this.expanded.push(row.getData().uniqueindex); + } + }); + }, + reexpandRows() { + const all = this.getAllRows(this.$refs.table.tabulator.getRows()); + + const matchingRows = all.filter(row => + this.expanded.includes(row.getData().uniqueindex) + ); + + matchingRows.forEach((row, index) => { + row._row.modules.dataTree.open = true; + + if (index === matchingRows.length - 1) + { + row.treeExpand(); + } + }); + }, + deleteLehreinheit(row) + { + let deleteData = { + lehreinheit_id: row.getData().lehreinheit_id, + } + return this.$api.call(ApiLehreinheit.delete(deleteData)) + .then(result => { + this.reload() + }) + .catch(this.$fhcAlert.handleSystemError); + }, + getAllRows(rows) + { + let result = []; + rows.forEach(row => + { + result.push(row); + let children = row.getTreeChildren(); + if(children && children.length > 0) + { + result = result.concat(this.getAllRows(children)); + } + }); + return result; + }, + }, + template: ` + + + + + + + + + + + + + +` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Setup/Tabs.js b/public/js/components/LVVerwaltung/Setup/Tabs.js new file mode 100644 index 000000000..af14fbf32 --- /dev/null +++ b/public/js/components/LVVerwaltung/Setup/Tabs.js @@ -0,0 +1,62 @@ +import FhcTabs from "../../Tabs.js"; +import Setup from "../../../api/lehrveranstaltung/setup.js"; + +export default { + name: "LVVerwaltungTabs", + components: { + FhcTabs + }, + data() { + return { + configLVTabs: {}, + }; + }, + props: { + lv: Object + }, + computed: { + config() { + if (!this.lv || !this.lv.length) + return {}; + + return this.configLVTabs; + } + }, + methods: { + reload() { + if (this.$refs.tabs?.$refs?.current?.reload) + { + this.$refs.tabs.$refs.current.reload(); + } + } + }, + created() { + this.$api.call(Setup.getTabs()) + .then(result => { + this.configLVTabs = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + }, + template: ` +
+
+ Bitte eine Lehreinheit auswählen! +
+
+ +
+
+ Loading... +
+
+ ` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Tabs/Details.js b/public/js/components/LVVerwaltung/Tabs/Details.js new file mode 100644 index 000000000..ce0102177 --- /dev/null +++ b/public/js/components/LVVerwaltung/Tabs/Details.js @@ -0,0 +1,133 @@ +import CoreForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; +import GruppenTable from '../Details/Gruppen.js'; +import GruppenDirektTable from '../Details/Direktinskription.js'; +import DetailsForm from '../Details/Form.js' +import ApiLehreinheit from "../../../api/lehrveranstaltung/lehreinheit.js"; + +export default { + name: "LVTabDetails", + components: { + CoreForm, + FormInput, + GruppenTable, + GruppenDirektTable, + DetailsForm + }, + props: { + modelValue: Object, + config: { + type: Object, + default: {} + }, + }, + inject: { + dropdowns: { + from: 'dropdowns' + } + }, + watch: { + modelValue(newValue) + { + this.updateLE(newValue) + }, + data: { + handler(newValue) { + if (newValue === null) + { + this.changed = {} + return + } + let changed = {}; + + let keys = Object.keys(this.original); + + for (let key of keys) { + if (this.original[key] !== newValue[key]) + { + changed[key] = newValue[key]; + } + } + this.changed = changed; + }, + deep: true + } + }, + data() { + return { + original: null, + data: null, + changed: {} + } + }, + computed: { + changedLength() { + return Object.keys(this.changed).length; + } + }, + + methods: { + updateLE(le) { + if (le?.lehreinheit_id === undefined) + { + this.data = null; + return; + } + return this.$api.call(ApiLehreinheit.get(le.lehreinheit_id)) + .then(result => { + this.data = result.data; + this.original = {...(this.original || {}), ...this.data}; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + save() { + if (!this.changedLength) + return; + this.$refs.form.clearValidation(); + + let updatedData = { + lehreinheit_id: this.modelValue.lehreinheit_id, + formData: this.changed + } + return this.$refs.form.call(ApiLehreinheit.update(updatedData)) + .then(result => { + this.original = {...this.data}; + this.changed = {}; + this.$refs.form.setFeedback(true, result.data); + }) + .catch(this.$fhcAlert.handleSystemError); + + }, + reload(){ + this.updateLE(this.modelValue); + } + }, + created() { + this.updateLE(this.modelValue); + }, + template: ` + +
+ +
+
+ {{this.$p.t('lehre', 'lehreinheit')}} + +
+
+
+
+
+ {{this.$p.t('lehre', 'gruppen')}} + +
+
+ {{this.$p.t('lehre', 'assignedPersons')}} + +
+
+ +
` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Tabs/Lektor.js b/public/js/components/LVVerwaltung/Tabs/Lektor.js new file mode 100644 index 000000000..99e1edb9e --- /dev/null +++ b/public/js/components/LVVerwaltung/Tabs/Lektor.js @@ -0,0 +1,70 @@ +import CoreForm from '../../Form/Form.js'; +import FormInput from '../../Form/Input.js'; +import LektorTable from '../Lektor/Table.js' +import LektorDaten from '../Lektor/Daten.js' +import LektorVertrag from '../Lektor/Vertrag.js' +export default { + name: "LVTabLektor", + components: { + CoreForm, + FormInput, + LektorTable, + LektorDaten, + LektorVertrag + }, + props: { + modelValue: Object, + config: { + type: Object, + default: {} + }, + }, + data() { + return { + mitarbeiter_uid: null + } + }, + methods: { + changedLektor(uid) { + const lektorTable = this.$refs.lektor_table; + const tabulator = lektorTable.$refs.table.tabulator; + + const selectUID = () => { + let row = tabulator.getRows().find(r => r.getData().mitarbeiter_uid === uid); + if (row) + { + row.select(); + } + tabulator.off('dataProcessed', selectUID); + }; + tabulator.on('dataProcessed', selectUID); + lektorTable.reload(); + }, + changedCosts() { + this.$refs.lektor_vertrag?.getLektorVertrag(); + }, + canceledVertrag() { + this.$refs.lektor_daten?.getLektorData(); + } + }, + template: ` +
+
+
+ {{ $p.t('lehre', 'lektorInnen')}} + +
+
+ +
+
+
+
+
+
+ +
+
+
+ ` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Tabs/Notiz.js b/public/js/components/LVVerwaltung/Tabs/Notiz.js new file mode 100644 index 000000000..6bccf5c52 --- /dev/null +++ b/public/js/components/LVVerwaltung/Tabs/Notiz.js @@ -0,0 +1,33 @@ +import CoreNotiz from "../../Notiz/Notiz.js"; +import ApiNotizLehreinheit from '../../../api/factory/notiz/lehreinheit.js'; +export default { + name: "LVTabNotiz", + components: { + CoreNotiz + }, + props: { + modelValue: Object + }, + data() { + return { + endpoint: ApiNotizLehreinheit + }; + }, + template: ` +
+ + +
+ ` +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung.js b/public/js/components/Stv/Studentenverwaltung.js index 248cfd55c..cc224480f 100644 --- a/public/js/components/Stv/Studentenverwaltung.js +++ b/public/js/components/Stv/Studentenverwaltung.js @@ -24,6 +24,7 @@ import StvStudiensemester from "./Studentenverwaltung/Studiensemester.js"; import ApiSearchbar from "../../api/factory/searchbar.js"; import ApiStv from "../../api/factory/stv.js"; +import ApiStvVerband from '../../api/factory/stv/verband.js'; export default { @@ -70,6 +71,7 @@ export default { }, data() { return { + endpoint: ApiStvVerband, selected: [], searchbaroptions: { cssclass: "position-relative", @@ -220,7 +222,7 @@ export default {
- +
diff --git a/public/js/components/Stv/Studentenverwaltung/Verband.js b/public/js/components/Stv/Studentenverwaltung/Verband.js index 8ae2b6b40..c60242511 100644 --- a/public/js/components/Stv/Studentenverwaltung/Verband.js +++ b/public/js/components/Stv/Studentenverwaltung/Verband.js @@ -5,8 +5,6 @@ import PvTree from "../../../../../index.ci.php/public/js/components/primevue/tr import PvTreetable from "../../../../../index.ci.php/public/js/components/primevue/treetable/treetable.esm.min.js"; import PvColumn from "../../../../../index.ci.php/public/js/components/primevue/column/column.esm.min.js"; -import ApiStvVerband from '../../../api/factory/stv/verband.js'; - export default { components: { PvTree, @@ -16,11 +14,22 @@ export default { emits: [ 'selectVerband' ], + props: { + endpoint: { + type: Object, + required: true, + }, + preselectedKey: { + type: String, + default: null + } + }, data() { return { loading: true, nodes: [], selectedKey: [], + expandedKeys: {}, filters: {}, // TODO(chris): filter only 1st level? favnodes: [], favorites: {on: false, list: []} @@ -44,7 +53,7 @@ export default { return res.pop(); return null; }, - onExpandTreeNode(node) { + async onExpandTreeNode(node) { if (!node.children) { if (node.data.link) { let activeEl = null; @@ -55,8 +64,8 @@ export default { }); this.loading = true; - this.$api - .call(ApiStvVerband.get(node.data.link)) + return this.$api + .call(this.endpoint.get(node.data.link)) .then(result => result.data) .then(result => { const subNodes = result.map(this.mapResultToTreeData); @@ -68,7 +77,7 @@ export default { let treeitem = this.$refs.tree.$el.querySelector('[data-tree-item-key="' + node.key + '"]'); treeitem = treeitem.closest('[role="row"]'); - + this.$nextTick(() => { if (activeEl == document.activeElement) treeitem.dispatchEvent(new KeyboardEvent('keydown', { @@ -108,7 +117,7 @@ export default { } this.favorites.on = !this.favorites.on; this.$api - .call(ApiStvVerband.favorites.set( + .call(this.endpoint.favorites.set( JSON.stringify(this.favorites) )); this.loading = false; @@ -135,7 +144,7 @@ export default { for (let parent in sortedInParents) promises.push( this.$api - .call(ApiStvVerband.get(parent == '_' ? '' : parent)) + .call(this.endpoint.get(parent == '_' ? '' : parent)) .then(res => res.data) .then(res => res.filter(node => sortedInParents[parent].includes(node.link + ''))) ); @@ -160,9 +169,9 @@ export default { this.favnodes.push((await this.loadNodes([key.data.link])).pop()); this.favorites.list.push(key.data.link + ''); } - + this.$api - .call(ApiStvVerband.favorites.set( + .call(this.endpoint.favorites.set( JSON.stringify(this.favorites) )); }, @@ -181,19 +190,54 @@ export default { let items = e.target.querySelectorAll('[data-link-fav-add][tabindex="-1"]'); items.forEach(el => el.tabIndex = 0); } + }, + async setPreselection() + { + if (!this.preselectedKey) + return; + + let rawKey = this.preselectedKey + + if (!rawKey || typeof rawKey !== 'string') + return; + + const parts = this.preselectedKey.split('/'); + let currentKey = parts[0]; + let currentNode = this.findNodeByKey(currentKey); + + if (!currentNode) + return; + + for (let i = 1; i < parts.length; i++) + { + this.expandedKeys[currentNode.key] = true; + + await this.onExpandTreeNode(currentNode); + + currentKey += '-' + parts[i]; + currentNode = this.findNodeByKey(currentKey); + + if (!currentNode) + { + return; + } + } + + this.selectedKey = { [currentNode.key]: true }; } }, mounted() { this.$api - .call(ApiStvVerband.get()) + .call(this.endpoint.get()) .then(result => { this.nodes = result.data.map(this.mapResultToTreeData); + this.setPreselection(); this.loading = false; }) .catch(this.$fhcAlert.handleSystemError); this.$api - .call(ApiStvVerband.favorites.get()) + .call(this.endpoint.favorites.get()) .then(result => { if (result.data) { let f = JSON.parse(result.data); @@ -218,6 +262,7 @@ export default { :value="filteredNodes" @node-expand="onExpandTreeNode" selection-mode="single" + v-model:expanded-keys="expandedKeys" v-model:selection-keys="selectedKey" @node-select="onSelectTreeNode" scrollable diff --git a/public/js/components/Tag/Tag.js b/public/js/components/Tag/Tag.js index c7552a5a9..a3243ed47 100644 --- a/public/js/components/Tag/Tag.js +++ b/public/js/components/Tag/Tag.js @@ -57,7 +57,7 @@ export default { init() { if (!this.endpoint) return; - this.endpoint.getTags() + this.$api.call(this.endpoint.getTags()) .then(response => response.data) .then(response => { this.tags = response @@ -71,7 +71,7 @@ export default { 'id': tag_id }; - this.endpoint.getTag(getData) + this.$api.call(this.endpoint.getTag(getData)) .then(result => result.data) .then(result => this.openModal(result)) }, @@ -118,7 +118,7 @@ export default { { postData.id = this.selectedTagId; this.tagData.id = this.selectedTagId; - this.endpoint.updateTag(postData); + this.$api.call(this.endpoint.updateTag(postData)); this.$emit("updated", this.tagData); this.$refs.tagModal.hide(); } @@ -130,7 +130,7 @@ export default { return; } - this.endpoint.addTag(postData) + this.$api.call(this.endpoint.addTag(postData)) .then(response => response.data) .then(response => { if (typeof response === 'number') { @@ -156,7 +156,7 @@ export default { id: this.selectedTagId, done: !this.tagData.done } - this.endpoint.doneTag(postData) + this.$api.call(this.endpoint.doneTag(postData)) this.$emit("updated", this.tagData); this.$refs.tagModal.hide(); }, @@ -165,7 +165,7 @@ export default { let postData = { id: this.selectedTagId } - this.endpoint.deleteTag(postData) + this.$api.call(this.endpoint.deleteTag(postData)) this.$emit("deleted", this.selectedTagId) this.$refs.tagModal.hide(); }, diff --git a/public/js/tabulator/filters/extendedHeaderFilter.js b/public/js/tabulator/filters/extendedHeaderFilter.js index e15f8d9ac..5dfcce205 100644 --- a/public/js/tabulator/filters/extendedHeaderFilter.js +++ b/public/js/tabulator/filters/extendedHeaderFilter.js @@ -39,7 +39,7 @@ function parseFilterExpression(expression) return collections; } -export function extendedHeaderFilter(headerValue, rowValue) +export function extendedHeaderFilter(headerValue, rowValue, rowData, filterParams) { if (typeof headerValue === 'boolean') { @@ -48,52 +48,79 @@ export function extendedHeaderFilter(headerValue, rowValue) const collections = parseFilterExpression(headerValue); - try { + function matchValue(value) + { + try { + return collections.some(collection => { - return collections.some(collection => { + let positives = collection.positives.length === 0 || collection.positives.every(condition => { - let positives = collection.positives.length === 0 || collection.positives.every(condition => { + if (condition.type === 'comparison') + { + let value = parseFloat(rowValue); + if (isNaN(value)) return false; - if (condition.type === 'comparison') - { - let value = parseFloat(rowValue); - if (isNaN(value)) return false; - - switch (condition.operator) { - case '<': - return value < condition.number; - case '>': - return value > condition.number; - case '<=': - return value <= condition.number; - case '>=': - return value >= condition.number; - case '=': - return value === condition.number; - case '!=': - return value !== condition.number; - default: - return false; + switch (condition.operator) { + case '<': + return value < condition.number; + case '>': + return value > condition.number; + case '<=': + return value <= condition.number; + case '>=': + return value >= condition.number; + case '=': + return value === condition.number; + case '!=': + return value !== condition.number; + default: + return false; + } } - } - else if (condition.type === 'regex') - { - return condition.regex.test(rowValue); - } - return false; + else if (condition.type === 'regex') + { + return condition.regex.test(rowValue); + } + return false; + }); + + let negatives = collection.negatives.every(condition => { + return !condition.regex.test(rowValue); + }); + + return positives && negatives; }); + } catch (e) { - let negatives = collection.negatives.every(condition => { - return !condition.regex.test(rowValue); - }); - - return positives && negatives; - }); - } catch (e) { - + } } + + if (matchValue(rowValue)) + return true; + + if (rowData && filterParams) + { + const childrenField = filterParams?.children || '_children'; + const field = filterParams?.field; + + const children = rowData[childrenField]; + if (Array.isArray(children)) + { + for (let child of children) + { + let childValue = child[field]; + if (extendedHeaderFilter(headerValue, childValue, child, filterParams)) + { + return true; + } + } + } + } + + return false; } -export function tagHeaderFilter(headerValue, rowValue) { +export function tagHeaderFilter(headerValue, rowValue, rowData, filterParams) +{ let data; @@ -120,6 +147,5 @@ export function tagHeaderFilter(headerValue, rowValue) { combinedText = String(data); } - return extendedHeaderFilter(headerValue, combinedText) -} - + return extendedHeaderFilter(headerValue, combinedText, rowData, filterParams) +} \ No newline at end of file diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index 0e2b4e7c6..fbdc1f4ae 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -74,6 +74,7 @@ require_once('dbupdate_3.4/55968_index_anrechnung.php'); require_once('dbupdate_3.4/25999_locale_update.php'); require_once('dbupdate_3.4/55289_pep_fine_tuning.php'); require_once('dbupdate_3.4/55614_perm_verwaltetoe.php'); +require_once('dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php'); // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; diff --git a/system/dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php b/system/dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php new file mode 100644 index 000000000..55fb55b80 --- /dev/null +++ b/system/dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php @@ -0,0 +1,16 @@ +db_query("SELECT 1 FROM public.tbl_variablenname WHERE name = 'lv_favorites';")) +{ + if ($db->db_num_rows($result) == 0) + { + $qry = "INSERT INTO public.tbl_variablenname(name, defaultwert) VALUES('lv_favorites', null);"; + + if (!$db->db_query($qry)) + echo 'public.tbl_variablenname '.$db->db_last_error().'
'; + else + echo 'public.tbl_variablenname: Added name "lv_favorites"
'; + } +} diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 0203b3c2f..c158e3971 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -41873,8 +41873,729 @@ and represent the current state of research on the topic. The prescribed citatio 'insertvon' => 'system' ) ) - ) + ), // PROJEKTARBEITSBEURTEILUNG SS2025 ENDE --------------------------------------------------------------------------- + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'gewicht', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gewicht', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Weight', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'newlehreinheit', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Neuer LV-Teil', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'New teaching unit', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'bezeichnungeng', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bezeichnung Englisch', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title english', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'detailanmerkung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Info an LV-Planung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Info to LV Planning', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'unr', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'UNR', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'UNR', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'las', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehrauftragsstunden (LAS)', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Teaching hours (LAS)', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'lehre', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehre', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Teaching', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'raumtyp', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Raumtyp', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Room', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'lehrende', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehrende', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'lecturers', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'raumtypalternativ', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Raumtyp Alternativ', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Room Alternative', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'startkw', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Start KW', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Start CW', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'stundenblockung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Stunden Block', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Hours Block', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'wochenrhythmus', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Wochenrhythmus', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Weekly rhythm', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'lehrfunktion', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehrfunktion', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Teaching function', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'anmerkung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Info an DepL/KFL', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Info to DepL/KFL', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'planstunden', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'LV-Plan Stunden', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Course-Plan Hours', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'leplanstunden', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Planstunden', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Plan Hours', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'default', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Default', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Default', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'stundensatz', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Stundensatz', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Hourly Rate', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'bismelden', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'BIS-Melden', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Report BIS', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'gesamtkosten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gesamtkosten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Total costs', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'daten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Daten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Data', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'lehreinheit_id', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehreinheit ID', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Teaching Unit ID', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'verplant', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Verplant', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Planned', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'addLektor', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'LektorIn hinzufügen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Add lector', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'gruppen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gruppen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Groups', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'addGroup', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gruppe hinzufügen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Add group', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'assignPerson', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Person zuordnen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Assign person', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'assignedPersons', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Direkt zugeordnete Personen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Directly assigned persons', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'geaendert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Geändert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Changed', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'vertragurfassung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Vertragsdetails lt. Urfassung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Contract details as per original version', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'vertragsdetails', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Vertragsdetails', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Contract details', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'semesterstunden', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Semesterstunden', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Semester hours', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'vertragsstatus', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Vertragsstatus', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Contract status', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'auslvplanentfernen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Stunden aus LV-Plan entfernen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Remove hours from course plan', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'lehrfach', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehrfach', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Course', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + ); From 239eace246349288b1146c1c684243e59e5721af Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 27 Jun 2025 23:14:56 +0200 Subject: [PATCH 11/93] registration links to Bewerbungstool: changed in infocenter and fas, studentenverwaltung so that user email is not verified --- application/views/system/infocenter/stammdaten.php | 2 +- .../js/components/Stv/Studentenverwaltung/Details/Details.js | 4 ++-- rdf/student.rdf.php | 2 +- vilesci/personen/personendetails.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/views/system/infocenter/stammdaten.php b/application/views/system/infocenter/stammdaten.php index f143c9c03..4806d979a 100644 --- a/application/views/system/infocenter/stammdaten.php +++ b/application/views/system/infocenter/stammdaten.php @@ -188,7 +188,7 @@ zugangscode)): ?> diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Details.js index ae4f92b20..3ca656697 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Details.js @@ -153,7 +153,7 @@ export default { @@ -459,4 +459,4 @@ export default { ` -}; \ No newline at end of file +}; diff --git a/rdf/student.rdf.php b/rdf/student.rdf.php index 40cf28e01..f16f8a7b0 100644 --- a/rdf/student.rdf.php +++ b/rdf/student.rdf.php @@ -349,7 +349,7 @@ function draw_content($row) uid)?$row->uid.'@'.DOMAIN:'').']]> zugangscode.']]> - zugangscode.'&emailAdresse='.$mail_privat.']]> + zugangscode.'&emailAdresse='.$mail_privat.'&keepEmailUnverified=true]]> bpk.']]> diff --git a/vilesci/personen/personendetails.php b/vilesci/personen/personendetails.php index a20e34c5d..684b21712 100644 --- a/vilesci/personen/personendetails.php +++ b/vilesci/personen/personendetails.php @@ -153,7 +153,7 @@ echo "Name: $person->titelpre $person->nachname $ echo "Geburtsdatum: ".$datum_obj->formatDatum($person->gebdatum,'d.m.Y').""; echo "Geschlecht: ".$person->geschlecht.""; echo "Anmerkung: ".$db->convert_html_chars($person->anmerkungen).""; -echo "Zugangscode:".(in_array('bewerbung', (explode(';', ACTIVE_ADDONS)))?"".$db->convert_html_chars($person->zugangscode)."":$db->convert_html_chars($person->zugangscode)).""; +echo "Zugangscode:".(in_array('bewerbung', (explode(';', ACTIVE_ADDONS)))?"".$db->convert_html_chars($person->zugangscode)."":$db->convert_html_chars($person->zugangscode)).""; echo ''; echo '
Statusinformation - FH Ausweis
'; From 31f0be35c876a39eb7d2bcfaae57039e9932dfa7 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Wed, 2 Jul 2025 12:53:54 +0200 Subject: [PATCH 12/93] selbe person auch wenn nicht abbrecher --- application/models/person/Person_model.php | 116 +++++++++------------ 1 file changed, 52 insertions(+), 64 deletions(-) diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php index 997048972..3947378cf 100644 --- a/application/models/person/Person_model.php +++ b/application/models/person/Person_model.php @@ -307,72 +307,60 @@ class Person_model extends DB_Model public function checkDuplicate($person_id) { - $qry = "SELECT person_id - FROM public.tbl_prestudent p - JOIN - ( - SELECT DISTINCT ON(prestudent_id) * - FROM public.tbl_prestudentstatus - WHERE prestudent_id IN - ( - SELECT prestudent_id - FROM public.tbl_prestudent - WHERE person_id IN - ( - SELECT p2.person_id - FROM public.tbl_person p - JOIN public.tbl_person p2 - ON lower(p.vorname) = lower(p2.vorname) - AND lower(p.nachname) = lower(p2.nachname) - AND p.gebdatum = p2.gebdatum - AND p.person_id = ? - ) - ) - ORDER BY prestudent_id, datum DESC, insertamum DESC - ) ps USING(prestudent_id) - JOIN public.tbl_status USING(status_kurzbz) + $qry = " + WITH person AS ( + SELECT * + FROM public.tbl_person + WHERE person_id = ? + ), + allePersonen AS ( + SELECT p.person_id + FROM public.tbl_person p + JOIN person + ON lower(p.vorname) = lower(person.vorname) + AND lower(p.nachname) = lower(person.nachname) + AND p.gebdatum = person.gebdatum + ), + lastStatus AS ( + SELECT DISTINCT ON (tbl_prestudentstatus.prestudent_id) + tbl_prestudentstatus.prestudent_id, + tbl_prestudentstatus.status_kurzbz, + tbl_prestudent.studiengang_kz, + tbl_prestudent.person_id + FROM public.tbl_prestudentstatus + JOIN public.tbl_prestudent USING (prestudent_id) + WHERE tbl_prestudent.person_id IN (SELECT person_id FROM allePersonen) + ORDER BY tbl_prestudentstatus.prestudent_id, tbl_prestudentstatus.datum DESC, tbl_prestudentstatus.insertamum DESC + ), + interessenten AS ( + SELECT * + FROM lastStatus WHERE status_kurzbz = 'Interessent' - AND studiengang_kz IN - ( - SELECT studiengang_kz - FROM public.tbl_prestudent p - JOIN - ( - SELECT DISTINCT ON(prestudent_id) * - FROM public.tbl_prestudentstatus - WHERE prestudent_id IN - ( - SELECT prestudent_id - FROM public.tbl_prestudent - WHERE person_id IN - ( - SELECT p2.person_id - FROM public.tbl_person p - JOIN public.tbl_person p2 - ON lower(p.vorname) = lower(p2.vorname) - AND lower(p.nachname) = lower(p2.nachname) - AND p.gebdatum = p2.gebdatum - AND p.person_id = ? - ) - ) - ORDER BY prestudent_id, datum DESC, insertamum DESC - ) ps USING(prestudent_id) - JOIN public.tbl_status USING(status_kurzbz) - WHERE status_kurzbz = 'Abbrecher' - ) - - UNION - + ), + keineInteressenten AS ( + SELECT * + FROM lastStatus + WHERE status_kurzbz != 'Interessent' + ), + doppeltePerson AS ( SELECT p2.person_id - FROM tbl_person p1 - JOIN tbl_prestudent ps ON p1.person_id = ps.person_id - INNER JOIN ( - SELECT vorname, nachname, gebdatum, person.person_id - FROM tbl_person person - JOIN tbl_prestudent sps ON person.person_id = sps.person_id - ) p2 - ON (lower(p1.vorname) = lower(p2.vorname) AND lower(p1.nachname) = lower(p2.nachname) AND p1.gebdatum = p2.gebdatum) - WHERE p1.person_id != p2.person_id AND (p1.person_id = ?)"; + FROM public.tbl_person p1 + JOIN public.tbl_prestudent ps1 ON ps1.person_id = p1.person_id + JOIN public.tbl_person p2 + ON lower(p1.vorname) = lower(p2.vorname) + AND lower(p1.nachname) = lower(p2.nachname) + AND p1.gebdatum = p2.gebdatum + WHERE p1.person_id = ? + AND p1.person_id <> p2.person_id + ) + SELECT DISTINCT(interessenten.person_id) + FROM interessenten + JOIN keineInteressenten + ON interessenten.studiengang_kz = keineInteressenten.studiengang_kz + WHERE interessenten.person_id = ? + UNION + SELECT DISTINCT person_id + FROM doppeltePerson"; return $this->execQuery($qry, array($person_id, $person_id, $person_id)); } From 5b2b715a169f83e0e29a186577e39bcae984da20 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Mon, 7 Jul 2025 08:59:36 +0200 Subject: [PATCH 13/93] userstory 61241: bugs behoben --- .../api/frontend/v1/Lehrveranstaltung.php | 16 +- .../controllers/api/frontend/v1/lv/Gruppe.php | 11 +- .../api/frontend/v1/lv/Lehreinheit.php | 7 +- .../models/education/Lehreinheit_model.php | 290 ++++++++---------- .../education/Lehreinheitgruppe_model.php | 4 +- .../education/Lehrveranstaltung_model.php | 17 +- public/css/Lvverwaltung.css | 5 +- .../components/LVVerwaltung/LVVerwaltung.js | 2 +- .../js/components/LVVerwaltung/Setup/Table.js | 139 ++++++--- .../js/components/LVVerwaltung/Tabs/Notiz.js | 2 +- system/phrasesupdate.php | 42 +++ 11 files changed, 300 insertions(+), 235 deletions(-) diff --git a/application/controllers/api/frontend/v1/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/Lehrveranstaltung.php index 1b2e2bc35..098d44712 100644 --- a/application/controllers/api/frontend/v1/Lehrveranstaltung.php +++ b/application/controllers/api/frontend/v1/Lehrveranstaltung.php @@ -39,6 +39,12 @@ class Lehrveranstaltung extends FHCAPI_Controller $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); + + $this->loadPhrases( + array( + 'ui' + ) + ); } public function loadByEmployee($mitarbeiter_uid = null, $stg_kz = null) { @@ -54,7 +60,7 @@ class Lehrveranstaltung extends FHCAPI_Controller foreach ($lehrveranstaltungen_data as $lehrveranstaltung) { - $lehreinheiten = $this->_ci->LehreinheitModel->getLEByLV($lehrveranstaltung->lehrveranstaltung_id, $studiensemester_kurzbz, $mitarbeiter_uid); + $lehreinheiten = $this->_ci->LehreinheitModel->getByLvidStudiensemester($lehrveranstaltung->lehrveranstaltung_id, $studiensemester_kurzbz, $mitarbeiter_uid); $lehreinheiten_data = $this->getDataOrTerminateWithError($lehreinheiten); if (!isset($lehrveranstaltung->_children)) @@ -69,8 +75,8 @@ class Lehrveranstaltung extends FHCAPI_Controller public function loadByStudiengang($studiengang_kz = null, $semester = null) { - if (is_null($studiengang_kz) || !ctype_digit((string)$studiengang_kz)) - $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + if (is_null($studiengang_kz) || !preg_match("/^-?[1-9][0-9]*$/", (string)$studiengang_kz)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); $verband = null; if (!is_null($semester) && !is_numeric($semester)) @@ -164,7 +170,7 @@ class Lehrveranstaltung extends FHCAPI_Controller if (is_null($lehrveranstaltung_id) || !ctype_digit((string)$lehrveranstaltung_id)) $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); - $this->_ci->LehrveranstaltungModel->addSelect('lehrveranstaltung_id, lehrform_kurzbz, lehre, bezeichnung as lvbezeichnung'); + $this->_ci->LehrveranstaltungModel->addSelect('lehrveranstaltung_id, lehrform_kurzbz, lehre, bezeichnung as lvbezeichnung, sprache'); $lehrveranstaltung_result = $this->_ci->LehrveranstaltungModel->loadWhere(array('lehrveranstaltung_id' => $lehrveranstaltung_id)); $lehrveranstaltung_result = $this->getDataOrTerminateWithError($lehrveranstaltung_result); $lehrveranstaltung = $lehrveranstaltung_result[0]; @@ -202,7 +208,7 @@ class Lehrveranstaltung extends FHCAPI_Controller foreach ($lehrveranstaltungen_data as $lehrveranstaltung) { - $lehreinheiten = $this->LehreinheitModel->getLEByLV($lehrveranstaltung->lehrveranstaltung_id, $studiensemester_kurzbz); + $lehreinheiten = $this->LehreinheitModel->getByLvidStudiensemester($lehrveranstaltung->lehrveranstaltung_id, $studiensemester_kurzbz); $lehreinheiten_data = $this->getDataOrTerminateWithError($lehreinheiten); if (!isset($lehrveranstaltung->_children)) diff --git a/application/controllers/api/frontend/v1/lv/Gruppe.php b/application/controllers/api/frontend/v1/lv/Gruppe.php index 01c11f98f..09f253a59 100644 --- a/application/controllers/api/frontend/v1/lv/Gruppe.php +++ b/application/controllers/api/frontend/v1/lv/Gruppe.php @@ -19,6 +19,13 @@ class Gruppe extends FHCAPI_Controller $this->_ci = &get_instance(); $this->_setAuthUID(); + $this->_ci->load->library('PhrasesLib'); + $this->loadPhrases( + array( + 'ui' + ) + ); + $this->_ci->load->model('organisation/Gruppe_model', 'GruppeModel'); $this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); $this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel'); @@ -57,10 +64,6 @@ class Gruppe extends FHCAPI_Controller if (is_null($lehreinheit_id) || !ctype_digit((string)$lehreinheit_id) || is_null($gid) || !ctype_digit((string)$gid) || is_null($lehrverband)) $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); - $gruppe_result = $this->_ci->GruppeModel->loadWhere(array('gid' => $gid)); - if (!hasData($gruppe_result) || isError($gruppe_result)) - $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); - $this->checkPermission($lehreinheit_id); $result = $this->_ci->LehreinheitgruppeModel->addGroup($lehreinheit_id, $gid, !($lehrverband === 'false')); diff --git a/application/controllers/api/frontend/v1/lv/Lehreinheit.php b/application/controllers/api/frontend/v1/lv/Lehreinheit.php index 84ee66d5d..0c42c0082 100644 --- a/application/controllers/api/frontend/v1/lv/Lehreinheit.php +++ b/application/controllers/api/frontend/v1/lv/Lehreinheit.php @@ -164,7 +164,6 @@ class Lehreinheit extends FHCAPI_Controller $this->terminateWithValidationErrors($this->form_validation->error_array()); } - $updateData = array(); foreach ($updatableFields as $field) { @@ -183,6 +182,12 @@ class Lehreinheit extends FHCAPI_Controller $updateData ); + if (!isset($updateData['unr'])) + { + $unr = getData($result); + $this->_ci->LehreinheitModel->update($unr, array('unr' => $unr)); + } + $this->terminateWithSuccess($result); } diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index ba9e82c64..ce414bad2 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -335,7 +335,7 @@ EOSQL; } - public function getByLvidStudiensemester($lv_id, $studiensemester_kurzbz) + public function getByLvidStudiensemester($lv_id, $studiensemester_kurzbz, $mitarbeiter_uid = null, $fachbereich_kurzbz = null) { $qry = "WITH lehreinheiten AS ( SELECT * @@ -343,98 +343,64 @@ EOSQL; WHERE lehrveranstaltung_id = ? AND studiensemester_kurzbz = ? ), - gruppen AS ( - SELECT - COALESCE( - string_agg( - tbl_lehreinheitgruppe.gruppe_kurzbz, ' ' - ) FILTER (WHERE NOT direktinskription), - string_agg( - COALESCE( - upper(tbl_studiengang.typ::varchar(1) ||tbl_studiengang.kurzbz) || - '-'|| - COALESCE(tbl_lehreinheitgruppe.semester::varchar, '') || - COALESCE(tbl_lehreinheitgruppe.verband::varchar, '')|| - COALESCE(tbl_lehreinheitgruppe.gruppe, '')), ', ' - ) - ) AS gruppe, - lehreinheit_id - FROM - lehre.tbl_lehreinheitgruppe - LEFT JOIN public.tbl_studiengang USING(studiengang_kz) - LEFT JOIN public.tbl_gruppe USING(gruppe_kurzbz) - GROUP BY lehreinheit_id - ), - mitarbeiter AS ( - SELECT kurzbz, semesterstunden, planstunden, lehreinheit_id - FROM lehre.tbl_lehreinheitmitarbeiter - JOIN public.tbl_mitarbeiter USING(mitarbeiter_uid) - ), - fachbereich AS ( - SELECT - tbl_organisationseinheit.bezeichnung, - tbl_organisationseinheit.organisationseinheittyp_kurzbz, - lehreinheit_id - FROM - public.tbl_organisationseinheit, - lehre.tbl_lehrveranstaltung as lehrfach, - lehre.tbl_lehreinheit - WHERE tbl_organisationseinheit.oe_kurzbz = lehrfach.oe_kurzbz - AND lehrfach.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id - ), - tag_data_agg AS ( - SELECT - lehreinheit_id, - COALESCE(json_agg(tag ORDER BY id), '[]'::json) AS tags - FROM ( - SELECT DISTINCT ON (public.tbl_notiz.notiz_id) - tbl_notiz.notiz_id AS id, - typ_kurzbz, - array_to_json(tbl_notiz_typ.bezeichnung_mehrsprachig)->>0 AS beschreibung, - text AS notiz, - style, - erledigt AS done, - lehreinheit_id - FROM public.tbl_notizzuordnung - JOIN public.tbl_notiz ON tbl_notizzuordnung.notiz_id = tbl_notiz.notiz_id - JOIN public.tbl_notiz_typ ON tbl_notiz.typ = tbl_notiz_typ.typ_kurzbz - WHERE lehreinheit_id IN (SELECT lehreinheit_id FROM lehreinheiten) - ) AS tag - GROUP BY lehreinheit_id - ) + ". $this->_getGruppenCTE() . ", + ". $this->_getLektorenCTE() . ", + ". $this->_getFachbereichCTE() . ", + ". $this->_getTagsCTE() . " + SELECT lehreinheiten.*, lehreinheiten.lehrform_kurzbz as lv_lehrform_kurzbz, tbl_lehrveranstaltung.kurzbz as lv_kurzbz, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, COALESCE(tag_data_agg.tags, '[]'::json) AS tags, - ( - SELECT string_agg(gr.gruppe, ' ') - FROM gruppen gr - WHERE gr.lehreinheit_id = lehreinheiten.lehreinheit_id - ) AS gruppen, - ( - SELECT string_agg(ma.kurzbz, ' ') - FROM mitarbeiter ma - WHERE ma.lehreinheit_id = lehreinheiten.lehreinheit_id - ) AS lektoren, - ( - SELECT string_agg(fachbereich.bezeichnung, ' ') - FROM fachbereich - WHERE fachbereich.lehreinheit_id = lehreinheiten.lehreinheit_id - ) AS fachbereich + gruppen.gruppen, + mitarbeiter.lektoren, + mitarbeiter.le_planstunden, + mitarbeiter.semesterstunden, + fachbereich.bezeichnung as fachbereich, + UPPER(CONCAT(tbl_studiengang.typ,tbl_studiengang.kurzbz)) as studiengang, + semester FROM lehreinheiten LEFT JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = lehreinheiten.lehrfach_id - LEFT JOIN tag_data_agg ON tag_data_agg.lehreinheit_id = lehreinheiten.lehreinheit_id"; + LEFT JOIN public.tbl_studiengang USING(studiengang_kz) + LEFT JOIN tag_data_agg ON tag_data_agg.lehreinheit_id = lehreinheiten.lehreinheit_id + LEFT JOIN mitarbeiter ON lehreinheiten.lehreinheit_id = mitarbeiter.lehreinheit_id + LEFT JOIN fachbereich ON lehreinheiten.lehreinheit_id = fachbereich.lehreinheit_id + LEFT JOIN gruppen ON lehreinheiten.lehreinheit_id = gruppen.lehreinheit_id + WHERE true + "; - return $this->execReadOnlyQuery($qry, array($lv_id, $studiensemester_kurzbz)); + $params = array($lv_id, $studiensemester_kurzbz); + + if ($mitarbeiter_uid !== null) + { + $qry .= " AND lehreinheiten.lehreinheit_id IN ( SELECT lehreinheit_id FROM lehre.tbl_lehreinheitmitarbeiter WHERE mitarbeiter_uid = ?) "; + $params[] = $mitarbeiter_uid; + } + + if($fachbereich_kurzbz !== null) + { + $qry .= " AND EXISTS ( SELECT 1 FROM lehre.tbl_lehrveranstaltung JOIN public.tbl_fachbereich USING(oe_kurzbz) WHERE fachbereich_kurzbz= ? AND lehrveranstaltung_id=lehreinheiten.lehrfach_id)"; + $params[] = $fachbereich_kurzbz; + } + $qry .= " ORDER BY lehrveranstaltung_id;"; + + return $this->execReadOnlyQuery($qry, $params); } private function getLVTmp($stg_kz = null) { $qry = "SELECT DISTINCT ON(lehrveranstaltung_id) *, - '' as studienplan_id, '' as studienplan_beeichnung, - CONCAT(vw_lehreinheit.stg_typ, vw_lehreinheit.stg_kurzbz) as studiengang - FROM campus.vw_lehreinheit + '' as stundenblockung, + '' as lehreinheit_id, + '' as wochenrythmus, + '' as raumtyp, + '' as raumtypalternativ, + '' as gruppen, + '' as studienplan_id, + '' as studienplan_beeichnung, + UPPER(CONCAT(vw_lehreinheit.stg_typ, vw_lehreinheit.stg_kurzbz)) as studiengang + FROM campus.vw_lehreinheit WHERE mitarbeiter_uid = ? AND studiensemester_kurzbz = ?"; @@ -460,89 +426,6 @@ EOSQL; return $this->execReadOnlyQuery($qry, $params); } - - - public function getLEByLV($lv_id, $studiensemester_kurzbz, $mitarbeiter_uid = null, $fachbereich_kurzbz = null) - { - $qry = " - WITH gruppen AS ( - SELECT - COALESCE( - string_agg( - tbl_lehreinheitgruppe.gruppe_kurzbz, ', ' - ) FILTER (WHERE NOT direktinskription), - string_agg( - COALESCE( - upper(tbl_studiengang.typ::varchar(1) ||tbl_studiengang.kurzbz) || - '-'|| - COALESCE(tbl_lehreinheitgruppe.semester::varchar, '') || - COALESCE(tbl_lehreinheitgruppe.verband::varchar, '')|| - COALESCE(tbl_lehreinheitgruppe.gruppe, '')), ', ' - ) - ) AS gruppen, - lehreinheit_id - FROM - lehre.tbl_lehreinheitgruppe - LEFT JOIN public.tbl_studiengang USING(studiengang_kz) - LEFT JOIN public.tbl_gruppe USING(gruppe_kurzbz) - GROUP BY lehreinheit_id - ), - lektoren AS ( - SELECT string_agg(kurzbz, ' ') as lektoren, - string_agg(semesterstunden::text, ' ') as semesterstunden, - string_agg(planstunden::text, ' ') as planstunden, - lehreinheit_id - FROM lehre.tbl_lehreinheitmitarbeiter - JOIN public.tbl_mitarbeiter USING(mitarbeiter_uid) - GROUP BY lehreinheit_id - ), - fachbereich AS ( - SELECT - string_agg(CONCAT(tbl_organisationseinheit.bezeichnung, ' (', tbl_organisationseinheit.organisationseinheittyp_kurzbz, ')'),' ') as fachbereich, - lehreinheit_id - FROM - public.tbl_organisationseinheit, - lehre.tbl_lehrveranstaltung as lehrfach, - lehre.tbl_lehreinheit - WHERE - tbl_organisationseinheit.oe_kurzbz = lehrfach.oe_kurzbz - AND lehrfach.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id - GROUP BY lehreinheit_id - ) - SELECT tbl_lehreinheit.*, - tbl_lehrveranstaltung.*, - tbl_lehrveranstaltung.kurzbz as lv_kurzbz, - tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, - lektoren.lektoren, - lektoren.semesterstunden, - lektoren.planstunden, - fachbereich.fachbereich - FROM lehre.tbl_lehreinheit - LEFT JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id - LEFT JOIN gruppen ON tbl_lehreinheit.lehreinheit_id = gruppen.lehreinheit_id - LEFT JOIN lektoren ON tbl_lehreinheit.lehreinheit_id = lektoren.lehreinheit_id - LEFT JOIN fachbereich ON tbl_lehreinheit.lehreinheit_id = fachbereich.lehreinheit_id - WHERE tbl_lehreinheit.lehrveranstaltung_id = ? - AND studiensemester_kurzbz = ? - "; - - $params = array($lv_id, $studiensemester_kurzbz); - if ($mitarbeiter_uid !== null) - { - $qry .= " AND tbl_lehreinheit.lehreinheit_id IN ( SELECT lehreinheit_id FROM lehre.tbl_lehreinheitmitarbeiter WHERE mitarbeiter_uid = ?) "; - $params[] = $mitarbeiter_uid; - } - - if($fachbereich_kurzbz !== null) - { - $qry .= " AND EXISTS ( SELECT 1 FROM lehre.tbl_lehrveranstaltung JOIN public.tbl_fachbereich USING(oe_kurzbz) WHERE fachbereich_kurzbz= ? AND lehrveranstaltung_id=tbl_lehreinheit.lehrfach_id)"; - $params[] = $fachbereich_kurzbz; - } - $qry .= " ORDER BY lehreinheit_id;"; - - return $this->execReadOnlyQuery($qry, $params); - } - public function deleteLehreinheit($lehreinheit_id) { $lehreinheit = $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); @@ -741,4 +624,85 @@ EOSQL; $this->db->trans_commit(); return success('Contract successfully updated.'); } + + private function _getGruppenCTE() + { + return "gruppen AS ( + SELECT + lehreinheit_id, + STRING_AGG( + CASE + WHEN (tbl_lehreinheitgruppe.gruppe_kurzbz IS NULL OR tbl_lehreinheitgruppe.gruppe_kurzbz = '') + THEN + UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) || + COALESCE(TRIM(tbl_lehreinheitgruppe.semester::text), '') || + COALESCE(TRIM(tbl_lehreinheitgruppe.verband), '') || + COALESCE(TRIM(tbl_lehreinheitgruppe.gruppe), '') + ELSE + CASE + WHEN NOT tbl_gruppe.direktinskription THEN tbl_lehreinheitgruppe.gruppe_kurzbz + ELSE NULL + END + END, + ' ' + ) AS gruppen + FROM lehre.tbl_lehreinheitgruppe + LEFT JOIN public.tbl_studiengang USING (studiengang_kz) + LEFT JOIN public.tbl_gruppe USING (gruppe_kurzbz) + JOIN lehreinheiten USING(lehreinheit_id) + GROUP BY lehreinheit_id + )"; + } + private function _getLektorenCTE() + { + return "mitarbeiter AS ( + SELECT + tbl_lehreinheitmitarbeiter.lehreinheit_id, + STRING_AGG(m.kurzbz, ' ') AS lektoren, + STRING_AGG(tbl_lehreinheitmitarbeiter.semesterstunden::text, ' ') AS semesterstunden, + STRING_AGG(tbl_lehreinheitmitarbeiter.planstunden::text, ' ') AS le_planstunden + FROM lehre.tbl_lehreinheitmitarbeiter + JOIN public.tbl_mitarbeiter m USING (mitarbeiter_uid) + JOIN lehreinheiten USING(lehreinheit_id) + GROUP BY tbl_lehreinheitmitarbeiter.lehreinheit_id + )"; + } + + private function _getFachbereichCTE() + { + return "fachbereich AS ( + SELECT + CONCAT(tbl_organisationseinheit.bezeichnung, ' (', tbl_organisationseinheit.organisationseinheittyp_kurzbz, ')') as bezeichnung, + lehreinheiten.lehreinheit_id + FROM public.tbl_organisationseinheit + JOIN lehre.tbl_lehrveranstaltung AS lehrfach ON tbl_organisationseinheit.oe_kurzbz = lehrfach.oe_kurzbz + JOIN lehre.tbl_lehreinheit ON lehrfach.lehrveranstaltung_id = tbl_lehreinheit.lehrfach_id + JOIN lehreinheiten ON tbl_lehreinheit.lehreinheit_id = lehreinheiten.lehreinheit_id + )"; + } + + private function _getTagsCTE() + { + return "tag_data_agg AS ( + SELECT + lehreinheit_id, + COALESCE(json_agg(tag ORDER BY id), '[]'::json) AS tags + FROM ( + SELECT DISTINCT ON (public.tbl_notiz.notiz_id) + tbl_notiz.notiz_id AS id, + typ_kurzbz, + array_to_json(tbl_notiz_typ.bezeichnung_mehrsprachig)->>0 AS beschreibung, + text AS notiz, + style, + erledigt AS done, + lehreinheit_id + FROM public.tbl_notizzuordnung + JOIN public.tbl_notiz ON tbl_notizzuordnung.notiz_id = tbl_notiz.notiz_id + JOIN public.tbl_notiz_typ ON tbl_notiz.typ = tbl_notiz_typ.typ_kurzbz + WHERE lehreinheit_id IN (SELECT lehreinheit_id FROM lehreinheiten) + ) AS tag + GROUP BY lehreinheit_id + )"; + } + } diff --git a/application/models/education/Lehreinheitgruppe_model.php b/application/models/education/Lehreinheitgruppe_model.php index 5dd2fa66c..8fc8e09f3 100644 --- a/application/models/education/Lehreinheitgruppe_model.php +++ b/application/models/education/Lehreinheitgruppe_model.php @@ -304,7 +304,7 @@ class Lehreinheitgruppe_model extends DB_Model } else if ($verband === true) { - $gruppen_result = $this->_ci->LehrverbandModel->loadWhere(array('gid' => $gid)); + $gruppen_result = $this->LehrverbandModel->loadWhere(array('gid' => $gid)); if (!hasData($gruppen_result)) return error('No group found for gid ' . $gid); @@ -470,6 +470,6 @@ class Lehreinheitgruppe_model extends DB_Model END AS verplant"); $this->addJoin('tbl_studiengang', 'studiengang_kz', 'LEFT'); $this->addJoin('public.tbl_gruppe', 'gruppe_kurzbz', 'LEFT'); - return $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id, 'tbl_gruppe.direktinskription' => false)); + return $this->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); } } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 955177273..121de9233 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -1122,9 +1122,9 @@ class Lehrveranstaltung_model extends DB_Model $qry .= " SELECT DISTINCT on(lehrveranstaltung_id) lehrveranstaltung_id, - kurzbz as lv_kurzbz, - bezeichnung as lv_bezeichnung, - bezeichnung_english as lv_bezeichnung_english, + tbl_lehrveranstaltung.kurzbz as lv_kurzbz, + tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, + tbl_lehrveranstaltung.bezeichnung_english as lv_bezeichnung_english, studiengang_kz, semester, tbl_lehrveranstaltung.sprache, @@ -1133,7 +1133,7 @@ class Lehrveranstaltung_model extends DB_Model tbl_lehrveranstaltung.anmerkung, tbl_lehrveranstaltung.lehre, lehreverzeichnis as lv_lehreverzeichnis, - aktiv, + tbl_lehrveranstaltung.aktiv, planfaktor as lv_planfaktor, planlektoren as lv_planlektoren, planpersonalkosten as lv_planpersonalkosten, @@ -1143,9 +1143,11 @@ class Lehrveranstaltung_model extends DB_Model ''::text as studienplan_id, '' as studienplan_bezeichnung, '' as studienplan_lehrveranstaltung_id_parent, - tbl_lehrveranstaltung.lehrtyp_kurzbz + tbl_lehrveranstaltung.lehrtyp_kurzbz, + UPPER(CONCAT(tbl_studiengang.typ,tbl_studiengang.kurzbz)) as studiengang FROM lehre.tbl_lehrveranstaltung JOIN lehre.tbl_lehreinheit USING (lehrveranstaltung_id) + JOIN public.tbl_studiengang USING(studiengang_kz) WHERE studiengang_kz = ? AND studiensemester_kurzbz = ? "; @@ -1178,17 +1180,18 @@ class Lehrveranstaltung_model extends DB_Model { return " SELECT - lehrveranstaltung_id, kurzbz as lv_kurzbz, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, bezeichnung_english as lv_bezeichnung_english, studiengang_kz, + lehrveranstaltung_id, tbl_lehrveranstaltung.kurzbz as lv_kurzbz, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, bezeichnung_english as lv_bezeichnung_english, studiengang_kz, tbl_studienplan_lehrveranstaltung.semester, tbl_lehrveranstaltung.sprache, ects as lv_ects, semesterstunden, anmerkung, lehre, lehreverzeichnis as lv_lehreverzeichnis, tbl_lehrveranstaltung.aktiv, planfaktor as lv_planfaktor, planlektoren as lv_planlektoren, planpersonalkosten as lv_planpersonalkosten, plankostenprolektor as lv_plankostenprolektor, lehrform_kurzbz as lv_lehrform_kurzbz, tbl_lehrveranstaltung.orgform_kurzbz, tbl_studienplan_lehrveranstaltung.studienplan_id::text as studienplan_id, tbl_studienplan.bezeichnung as studienplan_bezeichnung, tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent::text, - tbl_lehrveranstaltung.lehrtyp_kurzbz + tbl_lehrveranstaltung.lehrtyp_kurzbz, UPPER(CONCAT(tbl_studiengang.typ,tbl_studiengang.kurzbz)) as studiengang FROM lehre.tbl_lehrveranstaltung JOIN lehre.tbl_studienplan_lehrveranstaltung USING(lehrveranstaltung_id) JOIN lehre.tbl_studienplan USING(studienplan_id) + JOIN tbl_studiengang USING(studiengang_kz) WHERE tbl_lehrveranstaltung.aktiv AND ((studienplan_id, tbl_studienplan_lehrveranstaltung.semester) IN ( " . implode(',', $placeholders) . ")) UNION diff --git a/public/css/Lvverwaltung.css b/public/css/Lvverwaltung.css index 1ca3f0be1..38d74def4 100644 --- a/public/css/Lvverwaltung.css +++ b/public/css/Lvverwaltung.css @@ -14,14 +14,17 @@ textarea[name="anmerkung"] { .lv_table_icon.icon-modul::before { content: '\f468'; + color: #4e4ed2; } .lv_table_icon.icon-lv::before { content: '\f466'; + color: black; } .lv_table_icon.icon-::before { content: '\f073'; -} \ No newline at end of file + color: #f3c541; +} diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js index 772af5a47..c7c34802d 100644 --- a/public/js/components/LVVerwaltung/LVVerwaltung.js +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -186,7 +186,7 @@ export default { : this.$route.params.stg; } - this.$p.loadCategory(['lehre', 'person']) + this.$p.loadCategory(['lehre', 'person', 'global']) this.$api.call(ApiDetails.getStudiensemester()) .then(result => { diff --git a/public/js/components/LVVerwaltung/Setup/Table.js b/public/js/components/LVVerwaltung/Setup/Table.js index 9b0ae71f3..b4674ccff 100644 --- a/public/js/components/LVVerwaltung/Setup/Table.js +++ b/public/js/components/LVVerwaltung/Setup/Table.js @@ -100,7 +100,6 @@ export default { expanded: [], selectedColumnValues: [], tagEndpoint: ApiTag, - iconPath: FHC_JS_DATA_STORAGE_OBJECT.app_root + '/skin/images/lehrtyp_', tabulatorEvents: [ { event: 'rowSelectionChanged', @@ -119,7 +118,8 @@ export default { handler: (data) => { this.getExpandedRows() } - },{ + }, + { event: 'dataTreeRowCollapsed', handler: (data) => { this.getExpandedRows() @@ -157,19 +157,18 @@ export default { initialSort:[ {column: 'lv_bezeichnung', dir: 'desc'}, ], + dataTreeChildIndent: 20, dataTreeElementColumn: "lv_kurzbz", - dataTreeFilter: true, dataTreeStartExpanded: false, dataTreeCollapseElement: '', dataTreeExpandElement: '', columnDefaults: { tooltip: true, headerFilter: "input", - headerFilterFunc: extendedHeaderFilter + headerFilterFunc: extendedHeaderFilter, }, layout: 'fitDataStretch', - layoutColumnsOnNewData: false, - height: '100%', + persistenceID: 'lehrveranstaltungen_2025_07_07_v1', selectableRowsRangeMode: 'click', selectableRows: true, rowContextMenu: (component, e) => { @@ -217,7 +216,6 @@ export default { ]; }, - persistenceID: 'lehrveranstaltungen_2025_05_27_v1', columns: [ { title: this.$p.t('lehre', 'kurzbz'), @@ -302,45 +300,55 @@ export default { }, width: 150, }, + { + title: this.$p.t('lehre', 'kurzbz'), + field: "lv_kurzbz_anzeige", + headerFilterFuncParams: {field: 'lv_kurzbz_anzeige'}, + formatter: (cell, formatterParams) => { + let rowData = cell.getRow().getData(); + return rowData?.lv_kurzbz?.toUpperCase(); + }, + headerFilter: true + }, { title: this.$p.t('lehre', 'lehrveranstaltung_id'), field: "lehrveranstaltung_id", headerFilterFuncParams: {field: 'lehrveranstaltung_id'}, - headerFilter: true + headerFilter: true, + visible: false }, {title: this.$p.t('ui', 'bezeichnung'), field: "lv_bezeichnung", headerFilter: true, headerFilterFuncParams: {field: 'lv_bezeichnung'}}, - {title: this.$p.t('lehre', 'bezeichnungeng'), field: "lv_bezeichnung_english", headerFilter: true, headerFilterFuncParams: {field: 'lv_bezeichnung_english'}}, + {title: this.$p.t('lehre', 'bezeichnungeng'), field: "lv_bezeichnung_english", headerFilter: true, headerFilterFuncParams: {field: 'lv_bezeichnung_english'}, visible: false}, { title: this.$p.t('lehre', 'studiengangskennzahlLehre'), field: "lv_studiengang_kz", headerFilter: true, - headerFilterFuncParams: {field: 'lv_studiengang_kz'} + headerFilterFuncParams: {field: 'lv_studiengang_kz'}, + visible: false }, - {title: this.$p.t('lehre', 'studiengang'), field: "studiengang", headerFilter: true, headerFilterFuncParams: {field: 'studiengang'}}, + {title: this.$p.t('lehre', 'studiengang'), field: "studiengang", headerFilter: true, headerFilterFuncParams: {field: 'studiengang'}, visible: false}, {title: this.$p.t('lehre', 'semester'), field: "semester", headerFilter: true, headerFilterFuncParams: {field: 'semester'}}, - {title: this.$p.t('global', 'sprache'), field: "sprache", headerFilter: true, headerFilterFuncParams: {field: 'sprache'}}, - {title: this.$p.t('lehre', 'ects'), field: "lv_ects", headerFilter: true, headerFilterFuncParams: {field: 'lv_ects'}}, - {title: this.$p.t('lehre', 'semesterstunden'), field: "semesterstunden", headerFilter: true, headerFilterFuncParams: {field: 'semesterstunden'}}, - {title: this.$p.t('global', 'anmerkung'), field: "anmerkung", headerFilter: true, headerFilterFuncParams: {field: 'anmerkung'}}, - {title: this.$p.t('lehre', 'lehre'), field: "lehre", headerFilter: true, headerFilterFuncParams: {field: 'lehre'}}, - {title: "Lehreverzeichnis", field: "lehreverzeichnis", headerFilter: true, headerFilterFuncParams: {field: 'lehreverzeichnis'}}, - {title: this.$p.t('person', 'aktiv'), field: "aktiv", headerFilter: true, headerFilterFuncParams: {field: 'aktiv'}}, - {title: "Planfaktor", field: "planfaktor", headerFilter: true, headerFilterFuncParams: {field: 'planfaktor'}}, - {title: "Planlektoren", field: "planlektoren", headerFilter: true, headerFilterFuncParams: {field: 'planlektoren'}}, - {title: "planpersonalkosten", field: "planpersonalkosten", headerFilter: true, headerFilterFuncParams: {field: 'planpersonalkosten'}}, - {title: "plankostenprolektor", field: "plankostenprolektor", headerFilter: true, headerFilterFuncParams: {field: 'plankostenprolektor'}}, - {title: this.$p.t('ui', 'organisationsform'), field: "orgform_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'orgform_kurzbz'}}, - {title: this.$p.t('ui', 'studienplan_id'), field: "studienplan_id", headerFilter: true, headerFilterFuncParams: {field: 'studienplan_id'}}, - {title: "studienplan_bezeichnung", field: "studienplan_bezeichnung", headerFilter: true, headerFilterFuncParams: {field: 'studienplan_bezeichnung'}}, - {title: "lehrtyp_kurzbz", field: "lehrtyp_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'lehrtyp_kurzbz'}}, + {title: this.$p.t('global', 'sprache'), field: "sprache", headerFilter: true, headerFilterFuncParams: {field: 'sprache'}, visible: false}, + {title: this.$p.t('lehre', 'ects'), field: "lv_ects", headerFilter: true, headerFilterFuncParams: {field: 'lv_ects'}, visible: false}, + {title: this.$p.t('lehre', 'semesterstunden'), field: "semesterstunden", headerFilter: true, headerFilterFuncParams: {field: 'semesterstunden'}, visible: false}, + {title: this.$p.t('global', 'anmerkung'), field: "anmerkung", headerFilter: true, headerFilterFuncParams: {field: 'anmerkung'}, visible: false}, + {title: this.$p.t('lehre', 'lehre'), field: "lehre", headerFilter: true, headerFilterFuncParams: {field: 'lehre'}, formatter: (cell) => cell.getValue() ? this.toUpperCase(this.$p.t('ui', 'ja')) : this.toUpperCase(this.$p.t('ui', 'nein')), visible: false}, + {title: this.$p.t('person', 'aktiv'), field: "aktiv", headerFilter: true, headerFilterFuncParams: {field: 'aktiv'}, formatter: (cell) => cell.getValue() ? this.toUpperCase(this.$p.t('ui', 'ja')) : this.toUpperCase(this.$p.t('ui', 'nein')), visible: false}, + {title: this.$p.t('lehre', 'organisationsform'), field: "orgform_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'orgform_kurzbz'}}, + {title: this.$p.t('ui', 'studienplan_id'), field: "studienplan_id", headerFilter: true, headerFilterFuncParams: {field: 'studienplan_id'}, visible: false}, + {title: this.$p.t('lehre', 'studienplan'), field: "studienplan_bezeichnung", headerFilter: true, headerFilterFuncParams: {field: 'studienplan_bezeichnung'}, visible: false}, + {title: this.$p.t('lehre', 'lehrtyp'), field: "lehrtyp_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'lehrtyp_kurzbz'}, visible: false}, {title: this.$p.t('lehre', 'lehrform'), field: "lehrform_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'lehrform_kurzbz'}}, - {title: this.$p.t('lehre', 'leplanstunden'), field: "le_planstunden", headerFilter: true, headerFilterFuncParams: {field: 'le_planstunden'}}, - {title: this.$p.t('lehre', 'lehreinheit_id'), field: "lehreinheit_id", headerFilter: true, headerFilterFuncParams: {field: 'lehreinheit_id'}}, - {title: this.$p.t('lehre', 'stundenblockung'), field: "stundenblockung", headerFilter: true, headerFilterFuncParams: {field: 'stundenblockung'}}, - {title: this.$p.t('lehre', 'wochenrhytmus'), field: "wochenrythmus", headerFilter: true, headerFilterFuncParams: {field: 'wochenrythmus'}}, - {title: this.$p.t('lehre', 'startkw'), field: "startkw", headerFilter: true, headerFilterFuncParams: {field: 'startkw'}}, - {title: this.$p.t('lehre', 'raumtyp'), field: "raumtyp", headerFilter: true, headerFilterFuncParams: {field: 'raumtyp'}}, - {title: this.$p.t('lehre', 'raumtypalternativ'), field: "raumtypalternativ", headerFilter: true, headerFilterFuncParams: {field: 'raumtypalternativ'}}, + {title: this.$p.t('lehre', 'leplanstunden'), field: "le_planstunden", headerFilter: true, headerFilterFuncParams: {field: 'le_planstunden'}, visible: false}, + {title: this.$p.t('lehre', 'lehreinheit_id'), field: "lehreinheit_id", headerFilter: true, headerFilterFuncParams: {field: 'lehreinheit_id'}, visible: false}, + {title: this.$p.t('lehre', 'studiensemester'), field: "studiensemester_kurzbz", headerFilter: true, headerFilterFuncParams: {field: 'studiensemester_kurzbz'}, visible: false}, + {title: this.$p.t('lehre', 'unr'), field: "unr", headerFilter: true, headerFilterFuncParams: {field: 'unr'}, visible: false}, + {title: this.$p.t('lehre', 'fachbereich'), field: "fachbereich", headerFilter: true, headerFilterFuncParams: {field: 'fachbereich'}, visible: false}, + {title: this.$p.t('lehre', 'stundenblockung'), field: "stundenblockung", headerFilter: true, headerFilterFuncParams: {field: 'stundenblockung'}, visible: false}, + {title: this.$p.t('lehre', 'wochenrhythmus'), field: "wochenrythmus", headerFilter: true, headerFilterFuncParams: {field: 'wochenrythmus'}, visible: false}, + {title: this.$p.t('lehre', 'startkw'), field: "start_kw", headerFilter: true, headerFilterFuncParams: {field: 'startkw'}, visible: false}, + {title: this.$p.t('lehre', 'raumtyp'), field: "raumtyp", headerFilter: true, headerFilterFuncParams: {field: 'raumtyp'}, visible: false}, + {title: this.$p.t('lehre', 'raumtypalternativ'), field: "raumtypalternativ", headerFilter: true, headerFilterFuncParams: {field: 'raumtypalternativ'}, visible: false}, {title: this.$p.t('lehre', 'gruppen'), field: "gruppen", headerFilter: true, headerFilterFuncParams: {field: 'gruppen'}}, {title: this.$p.t('lehre', 'lehrende'), field: "lektoren", headerFilter: true, headerFilterFuncParams: {field: 'lektoren'}}, ], @@ -359,6 +367,11 @@ export default { shouldAutoLoad() { return this.filter && this.filter.activeFilter; }, + toUpperCase(str) { + if (!str) + return ''; + return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase() + }, async reload() { @@ -369,7 +382,7 @@ export default { }, rowSelectionChanged(data) { this.selectedRows = this.$refs.table.tabulator.getSelectedRows(); - this.selectedColumnValues = this.selectedRows.filter(row => row.getData().lehreinheit_id !== undefined).map(row => row.getData().lehreinheit_id); + this.selectedColumnValues = this.selectedRows.filter(row => row.getData().lehreinheit_id !== undefined && row.getData().lehreinheit_id).map(row => row.getData().lehreinheit_id); if (data[0]?.lehreinheit_id !== undefined && this.selectedColumnValues.length === 1) { @@ -471,9 +484,7 @@ export default { if (Array.isArray(addedTag.response)) { addedTag.response.forEach(tag => { - - const all = this.getAllRows(table.getRows()); - const targetRow = all.find(row => row.getData().lehreinheit_id === tag.lehreinheit_id); + const targetRow = this.allRows.find(row => row.getData().lehreinheit_id === tag.lehreinheit_id); if (targetRow) { const rowData = targetRow.getData(); @@ -496,10 +507,7 @@ export default { }); }, deletedTag(deletedTag) { - const table = this.$refs.table.tabulator; - const all = this.getAllRows(table.getRows()); - - const targetRow = all.find(row => { + const targetRow = this.allRows.find(row => { const rowData = row.getData(); let tags = []; @@ -532,10 +540,7 @@ export default { }, updatedTag(updatedTag) { - const table = this.$refs.table.tabulator; - const all = this.getAllRows(table.getRows()); - - const targetRow = all.find(row => { + const targetRow = this.allRows.find(row => { const rowData = row.getData(); let tags = []; @@ -587,9 +592,8 @@ export default { async getExpandedRows() { this.expanded = []; - let rows = this.$refs.table.tabulator.getRows(); - let allRows = this.getAllRows(rows); - allRows.forEach(row => { + + this.allRows.forEach(row => { if (row.getTreeChildren().length > 0 && row.isTreeExpanded()) { this.expanded.push(row.getData().uniqueindex); @@ -597,9 +601,9 @@ export default { }); }, reexpandRows() { - const all = this.getAllRows(this.$refs.table.tabulator.getRows()); + this.allRows = this.getAllRows(this.$refs.table.tabulator.getRows()); - const matchingRows = all.filter(row => + const matchingRows = this.allRows.filter(row => this.expanded.includes(row.getData().uniqueindex) ); @@ -637,6 +641,39 @@ export default { }); return result; }, + resetTree() { + this.allRows.forEach(row => { + row._row.modules.dataTree.open = false; + }); + + let rootRows = this.$refs.table.tabulator.getRows(true); + var lastRow = rootRows[rootRows.length - 1]; + lastRow.treeCollapse(true) + + this.currentTreeLevel = 0; + }, + expandTree() + { + this.currentTreeLevel = (this.currentTreeLevel || 0) + 1; + + let lastMatchingRow = null; + + this.allRows.forEach(row => { + const level = row._row.modules.dataTree?.index ?? 0; + + if (level === this.currentTreeLevel - 1 ) + { + row._row.modules.dataTree.open = true; + lastMatchingRow = row; + } + }); + + if (lastMatchingRow) + { + lastMatchingRow.treeExpand(); + } + this.$refs.table.tabulator.redraw(); + }, }, template: ` + + -