From bf1bc8d1a97dbb52c2d1bd30a295a3909058da22 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Sun, 13 Oct 2024 13:32:15 +0200 Subject: [PATCH 001/388] 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 002/388] 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 003/388] 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 004/388] 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 005/388] 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 006/388] 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 007/388] 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 008/388] 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 bc484453041935f163a2b029a556aa7bffd98693 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Mon, 10 Feb 2025 13:05:44 +0100 Subject: [PATCH 009/388] - infocenter filter fuer electronic onboarding hinzugefuegt --- .../system/infocenter/InfoCenter.php | 44 +++++++ .../views/system/infocenter/onboarding.php | 47 +++++++ .../system/infocenter/onboardingData.php | 116 ++++++++++++++++++ system/filtersupdate.php | 23 ++++ 4 files changed, 230 insertions(+) create mode 100644 application/views/system/infocenter/onboarding.php create mode 100644 application/views/system/infocenter/onboardingData.php diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index f6e41d2e6..9024088f8 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -22,6 +22,7 @@ class InfoCenter extends Auth_Controller const REIHUNGSTESTABSOLVIERT_PAGE = 'reihungstestAbsolviert'; const ABGEWIESEN_PAGE = 'abgewiesen'; const AUFGENOMMEN_PAGE = 'aufgenommen'; + const ONBOARDING_PAGE = 'onboarding'; const SHOW_DETAILS_PAGE = 'showDetails'; const SHOW_ZGV_DETAILS_PAGE = 'showZGVDetails'; const ZGV_UBERPRUEFUNG_PAGE = 'ZGVUeberpruefung'; @@ -116,6 +117,7 @@ class InfoCenter extends Auth_Controller 'index' => 'infocenter:r', 'freigegeben' => 'infocenter:r', 'abgewiesen' => 'infocenter:r', + 'onboarding' => 'infocenter:r', 'aufgenommen' => 'infocenter:r', 'reihungstestAbsolviert' => 'infocenter:r', 'showDetails' => 'infocenter:r', @@ -230,6 +232,13 @@ class InfoCenter extends Auth_Controller $this->load->view('system/infocenter/infocenterAbgewiesen.php'); } + + public function onboarding() + { + $this->_setNavigationMenu(self::ONBOARDING_PAGE); // define the navigation menu for this page + + $this->load->view('system/infocenter/onboarding.php'); + } /** * Aufgenommene page of the InfoCenter tool @@ -1552,6 +1561,7 @@ class InfoCenter extends Auth_Controller $reihungstestAbsolviertLink = site_url(self::INFOCENTER_URI.'/'.self::REIHUNGSTESTABSOLVIERT_PAGE); $abgewiesenLink = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); $aufgenommenLink = site_url(self::INFOCENTER_URI.'/'.self::AUFGENOMMEN_PAGE); + $onboardingLink = site_url(self::INFOCENTER_URI.'/'.self::ONBOARDING_PAGE); $currentFilterId = $this->input->get(self::FILTER_ID); if (isset($currentFilterId)) @@ -1560,6 +1570,7 @@ class InfoCenter extends Auth_Controller $reihungstestAbsolviertLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; $abgewiesenLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; $aufgenommenLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; + $onboardingLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; } $this->navigationlib->setSessionMenu( @@ -1623,6 +1634,18 @@ class InfoCenter extends Auth_Controller '', // target 40 // sort ), + 'ohnePrestudent' => $this->navigationlib->oneLevel( + 'Electronic Onboarding', // description + $onboardingLink, // link + null, // children + 'users', // icon + null, // subscriptDescription + false, // expand + null, // subscriptLinkClass + null, // subscriptLinkValue + '', // target + 50 // sort + ), ) ); } @@ -1649,6 +1672,8 @@ class InfoCenter extends Auth_Controller $link = site_url(self::ZGV_UEBERPRUEFUNG_URI); if ($origin_page === self::ABGEWIESEN_PAGE) $link = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); + if ($origin_page === self::ONBOARDING_PAGE) + $link = site_url(self::INFOCENTER_URI.'/'.self::ONBOARDING_PAGE); if ($origin_page === self::AUFGENOMMEN_PAGE) $link = site_url(self::INFOCENTER_URI.'/'.self::AUFGENOMMEN_PAGE); @@ -1690,6 +1715,7 @@ class InfoCenter extends Auth_Controller $freigegebenLink = site_url(self::INFOCENTER_URI.'/'.self::FREIGEGEBEN_PAGE); $absolviertLink = site_url(self::INFOCENTER_URI.'/'.self::REIHUNGSTESTABSOLVIERT_PAGE); $abgewiesenLink = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); + $onboardingLink = site_url(self::INFOCENTER_URI.'/'.self::ONBOARDING_PAGE); $prevFilterId = $this->input->get(self::PREV_FILTER_ID); if (isset($prevFilterId)) { @@ -1766,6 +1792,24 @@ class InfoCenter extends Auth_Controller ) ); } + if($page == self::ONBOARDING_PAGE) + { + $this->navigationlib->setSessionElementMenu( + 'onboarding', + $this->navigationlib->oneLevel( + 'Electronic Onboarding', // description + $onboardingLink, // link + null, // children + 'users', // icon + null, // subscriptDescription + false, // expand + null, // subscriptLinkClass + null, // subscriptLinkValue + '', // target + 50 // sort + ) + ); + } } /** diff --git a/application/views/system/infocenter/onboarding.php b/application/views/system/infocenter/onboarding.php new file mode 100644 index 000000000..a600364d9 --- /dev/null +++ b/application/views/system/infocenter/onboarding.php @@ -0,0 +1,47 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Info Center', + 'jquery3' => true, + 'jqueryui1' => true, + 'jquerycheckboxes1' => true, + 'bootstrap3' => true, + 'fontawesome4' => true, + 'sbadmintemplate3' => true, + 'tablesorter2' => true, + 'ajaxlib' => true, + 'filterwidget' => true, + 'navigationwidget' => true, + 'dialoglib' => true, + 'phrases' => array( + 'person' => array('vorname', 'nachname'), + 'ui' => array('bitteEintragWaehlen') + ), + 'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js') + ) + ); +?> + +
+ + widgetlib->widget('NavigationWidget'); ?> + +
+
+
+
+ +
+
+
+ load->view('system/infocenter/onboardingData.php'); ?> +
+
+
+
+ +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/system/infocenter/onboardingData.php b/application/views/system/infocenter/onboardingData.php new file mode 100644 index 000000000..5ee66fdde --- /dev/null +++ b/application/views/system/infocenter/onboardingData.php @@ -0,0 +1,116 @@ +>0 as bezeichnung + FROM public.tbl_rueckstellung + JOIN public.tbl_rueckstellung_status USING(status_kurzbz) + JOIN public.tbl_person sp ON tbl_rueckstellung.person_id = sp.person_id + WHERE tbl_rueckstellung.rueckstellung_id = + ( + SELECT srueck.rueckstellung_id + FROM public.tbl_rueckstellung srueck + WHERE srueck.person_id = tbl_rueckstellung.person_id + AND datum_bis >= NOW() + ORDER BY srueck.datum_bis DESC LIMIT 1 + ) + ) rueck ON rueck.person_id = p.person_id + WHERE p.person_id NOT IN (SELECT person_id FROM public.tbl_prestudent)'; + + $filterWidgetArray = array( + 'query' => $query, + 'app' => InfoCenter::APP, + 'datasetName' => 'onboarding', + 'filter_id' => $this->input->get('filter_id'), + 'requiredPermissions' => 'infocenter', + 'datasetRepresentation' => 'tablesorter', + 'checkboxes' => 'PersonId', + 'additionalColumns' => array('Details'), + 'columnsAliases' => array( + 'PersonId', + ucfirst($this->p->t('person', 'vorname')) , + ucfirst($this->p->t('person', 'nachname')), + ucfirst($this->p->t('global', 'sperrdatum')), + ucfirst($this->p->t('global', 'gesperrtVon')), + ucfirst($this->p->t('infocenter', 'rueckstelldatum')), + ucfirst($this->p->t('infocenter', 'rueckstellgrund')), + ), + + 'formatRow' => function($datasetRaw) { + /* NOTE: Dont use $this here for PHP Version compatibility */ + $datasetRaw->{'Details'} = sprintf( + 'Details', + site_url('system/infocenter/InfoCenter/showDetails'), + $datasetRaw->{'PersonId'}, + 'onboarding', + (isset($_GET['fhc_controller_id']) ? $_GET['fhc_controller_id'] : ''), + (isset($_GET['filter_id']) ? $_GET['filter_id'] : '') + ); + + if ($datasetRaw->{'LockDate'} == null) + { + $datasetRaw->{'LockDate'} = '-'; + } + + if ($datasetRaw->{'LockUser'} == null) + { + $datasetRaw->{'LockUser'} = '-'; + } + + if ($datasetRaw->{'HoldDate'} == null) + { + $datasetRaw->{'HoldDate'} = '-'; + } + else + { + $datasetRaw->{'HoldDate'} = date_format(date_create($datasetRaw->{'HoldDate'}), 'Y-m-d H:i'); + } + + if ($datasetRaw->{'Rueckstellgrund'} === null) + { + $datasetRaw->{'Rueckstellgrund'} = '-'; + } + + return $datasetRaw; + }, + + 'markRow' => function($datasetRaw) { + + if ($datasetRaw->LockDate != null) + { + return FilterWidget::DEFAULT_MARK_ROW_CLASS; + } + } + + + + ); + + echo $this->widgetlib->widget('FilterWidget', $filterWidgetArray); +?> diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 51dd86314..cfcceb0f6 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -529,6 +529,29 @@ $filters = array( ', 'oe_kurzbz' => null, ), + array( + 'app' => 'infocenter', + 'dataset_name' => 'onboarding', + 'filter_kurzbz' => 'InfoCenterOnboarding', + 'description' => '{Alle}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "Electronic Onboarding - Alle", + "columns": [ + {"name": "PersonId"}, + {"name": "Vorname"}, + {"name": "Nachname"}, + {"name": "LockUser"}, + {"name": "HoldDate"}, + {"name": "Rueckstellgrund"} + ], + "filters": [] + } + ', + 'oe_kurzbz' => null, + ), array( 'app' => 'infocenter', 'dataset_name' => 'aufgenommen', From ea2be8026b463c8cf9c7132197aea82831aa9886 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 12 Mar 2025 08:06:23 +0100 Subject: [PATCH 010/388] 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 405062f5493fcdaaf3ed0e9b501a08e5aa93f081 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 7 May 2025 18:36:51 +0200 Subject: [PATCH 011/388] added Projektarbeit tab to Studierendenverwaltung, adding, editing, deleting of Projektarbeiten now possible --- .../api/frontend/v1/stv/Config.php | 5 + .../api/frontend/v1/stv/Projektarbeit.php | 334 +++++++ .../education/Lehrveranstaltung_model.php | 57 ++ .../models/education/Projektarbeit_model.php | 34 +- application/models/ressource/Firma_model.php | 21 +- public/js/api/factory/stv/projektarbeit.js | 80 ++ .../Details/Projektarbeit.js | 24 + .../Details/Projektarbeit/Betreuung.js | 847 ++++++++++++++++++ .../Details/Projektarbeit/Details.js | 461 ++++++++++ .../Details/Projektarbeit/Projektarbeit.js | 377 ++++++++ 10 files changed, 2230 insertions(+), 10 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/Projektarbeit.php create mode 100644 public/js/api/factory/stv/projektarbeit.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 455b1e8fc..dd2eaed02 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -123,6 +123,11 @@ class Config extends FHCAPI_Controller 'config' => $config['finalexam'] ]; + $result['projektarbeit'] = [ + 'title' => $this->p->t('stv', 'tab_projektarbeit'), + 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js' + ]; + $result['mobility'] = [ 'title' => $this->p->t('stv', 'tab_mobility'), 'component' => './Stv/Studentenverwaltung/Details/Mobility.js' diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php new file mode 100644 index 000000000..3be2b26a3 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -0,0 +1,334 @@ + ['admin:r', 'assistenz:r'], + 'loadProjektarbeit' => ['admin:r', 'assistenz:r'], + 'insertProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'updateProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'deleteProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'], + 'getFirmen' => ['admin:r', 'assistenz:r'], + 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], + 'getNoten' => ['admin:rw', 'assistenz:rw'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->load->model('education/Projekttyp_model', 'ProjekttypModel'); + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $this->load->model('ressource/Firma_model', 'FirmaModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('education/Note_model', 'NoteModel'); + $this->load->model('education/Projektbetreuer_model', 'BetreuerModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getProjektarbeit() + { + $student_uid = $this->input->get('uid'); + + if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektarbeitModel->getProjektarbeit($student_uid); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $projektarbeiten = getData($result); + + foreach ($projektarbeiten as $projektarbeit) + { + $projektarbeit_id = $projektarbeit->projektarbeit_id; + $abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id); + + if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL); + + if (hasData($abgabeRes)) + { + $paabgabe = getData($abgabeRes)[0]; + $projektarbeit->abgabedatum = $paabgabe->abgabedatum; + } + } + + $this->terminateWithSuccess($projektarbeiten); + } + + public function loadProjektarbeit() + { + $projektarbeit_id = $this->input->get('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) return $this->terminateWithError('Projektarbeit Id missing', self::ERROR_TYPE_GENERAL); + + $this->ProjektarbeitModel->addSelect( + 'lehre.tbl_projektarbeit.projektarbeit_id, titel, titel_english, themenbereich, projekttyp_kurzbz, firma_id, + lehrveranstaltung_id, lehreinheit_id, beginn, note, final, freigegeben, tbl_projektarbeit.anmerkung, fa.name AS firma_name' + ); + $this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id'); + $result = $this->ProjektarbeitModel->loadWhere( + array('projektarbeit_id' => $projektarbeit_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function insertProjektarbeit() + { + $student_uid = $this->input->post('uid'); + + if (!$student_uid) return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + + if (!$this->_hasBerechtigungForStudent($student_uid)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $formData = $this->input->post('formData'); + + $this->addMeta('form', $formData); + + if ($this->_validate($formData) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->ProjektarbeitModel->insert( + array_merge($formData, ['insertamum' => date('c'), 'insertvon' => getAuthUID(), 'student_uid' => $student_uid]) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function updateProjektarbeit() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!$projektarbeit_id || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $formData = $this->input->post('formData'); + + if ($this->_validate($formData) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->ProjektarbeitModel->update( + $projektarbeit_id, + array_merge($formData, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteProjektarbeit() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID'], self::ERROR_TYPE_GENERAL)); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $validate = $this->_validateDelete($projektarbeit_id); + + if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektarbeitModel->delete( + array('projektarbeit_id' => $projektarbeit_id) + ); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) + { + $this->outputJson($result); + } + + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getTypenProjektarbeit() + { + $result = $this->ProjekttypModel->loadWhere(['aktiv' => true]); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getFirmen() + { + $searchString = $this->input->get('searchString'); + + if (!isset($searchString)) $this->terminateWithError($this->p->t('projektarbeit', 'error_searchStringMissing', self::ERROR_TYPE_GENERAL)); + + $result = $this->FirmaModel->searchFirmen($searchString, $aktiv = true); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getLehrveranstaltungen() + { + $student_uid = $this->input->get('student_uid'); + $studiengang_kz = $this->input->get('studiengang_kz'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + $additional_lehrveranstaltung_id = $this->input->get('additional_lehrveranstaltung_id'); + + if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + if (!isset($studiensemester_kurzbz)) $this->terminateWithError('Studiensemster missing', self::ERROR_TYPE_GENERAL); + + $lvsResult = $this->LehrveranstaltungModel->getLvsForProjektarbeit($student_uid, $studiengang_kz, $additional_lehrveranstaltung_id); + + if (isError($lvsResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); + + $lvs = hasData($lvsResult) ? getData($lvsResult) : []; + + foreach ($lvs as $lv) + { + $lehreinheiten = $this->LehreinheitModel->getLesForLv( + $lv->lehrveranstaltung_id, $studiensemester_kurzbz + ); + + foreach ($lehreinheiten as $lehreinheit) + { + if (!isEmptyArray($lehreinheit->lektoren)) + { + $this->MitarbeiterModel->addSelect('kurzbz'); + $this->MitarbeiterModel->db->where_in('tbl_mitarbeiter.mitarbeiter_uid', $lehreinheit->lektoren); + $maResult = $this->MitarbeiterModel->load(); + + if (isError($maResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); + + $lehreinheit->lektoren = array_column(getData($maResult), 'kurzbz'); + } + } + + $lv->lehreinheiten = $lehreinheiten; + } + + return $this->terminateWithSuccess($lvs); + } + + public function getNoten() + { + $result = $this->NoteModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + /** + * + * @param + * @return object success or error + */ + private function _validate($formData) + { + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('titel', 'Titel', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel']) + ]); + + $this->form_validation->set_rules('projekttyp_kurzbz', 'Projekttyp', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp']) + ]); + + $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), + //'matches' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) + ]); + + $this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Beginn']) + ]); + + return $this->form_validation->run(); + } + + /** + * + * @param + * @return object success or error + */ + private function _validateDelete($projektarbeit_id) + { + $this->BetreuerModel->addSelect('1'); + $result = $this->BetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) return $result; + + if (hasData($result)) return error($this->p->t('projektarbeit', 'error_betreuerNichtGeloescht')); + + $this->PaabgabeModel->addSelect('1'); + $result = $this->PaabgabeModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) return $result; + + if (hasData($result)) return error($this->p->t('projektarbeit', 'error_paabgabeNichtGeloescht')); + + return success(); + } + + private function _hasBerechtigungForStudent($student_uid) + { + if (!$student_uid) + return false; + + $this->load->model('crm/Student_model', 'StudentModel'); + + $this->StudentModel->addSelect('studiengang_kz'); + $result = $this->StudentModel->load([$student_uid]); + if (isError($result) || !hasData($result)) + return false; + + $studiengang_kz = getData($result)[0]->studiengang_kz; + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz)) + return true; + + return false; + } +} diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 056fb45d7..446e6e9cf 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -988,4 +988,61 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($qry, $params); } + + /** + * Gets Lehrveranstaltungen for a student, as needed for a Projektarbeit. + * @param student_uid + * @param studiengang_kz optional, all Lvs of this Studiengang will be included + * @param additional_lehrveranstaltung_id optional, this lv will be added to result + * @return object success or error + */ + public function getLvsForProjektarbeit($student_uid, $studiengang_kz = null, $additional_lehrveranstaltung_id = null) + { + $params = array($student_uid, $student_uid); + + $qry = " + SELECT * + FROM + lehre.tbl_lehrveranstaltung + WHERE + ( + lehrveranstaltung_id IN ( + + SELECT + lehrveranstaltung_id + FROM + campus.vw_student_lehrveranstaltung + WHERE + uid=? + + UNION + + SELECT + lehrveranstaltung_id + FROM + lehre.tbl_zeugnisnote + WHERE + student_uid=? + )"; + + if (isset($studiengang_kz)) + { + $params[] = $studiengang_kz; + $qry .= " OR (studiengang_kz = ? AND semester IS NOT NULL)"; + } + + if (isset($additional_lehrveranstaltung_id)) + { + $params[] = $additional_lehrveranstaltung_id; + $qry .= " OR lehrveranstaltung_id = ?"; + } + + $qry .= " + ) + AND projektarbeit = TRUE + ORDER BY + semester, bezeichnung"; + + return $this->execQuery($qry, $params); + } } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 109e23373..2be79f8e9 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -24,15 +24,17 @@ class Projektarbeit_model extends DB_Model public function getProjektarbeit($student_uid, $studiengang_kz = null, $studiensemester_kurzbz = null, $projekttyp = null, $final = null) { $qry = "SELECT - tbl_projektarbeit.* , tbl_projekttyp.bezeichnung + tbl_projektarbeit.*, tbl_projekttyp.bezeichnung, + tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id, + tbl_firma.name AS firma_name FROM lehre.tbl_projektarbeit JOIN - lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung - + lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, public.tbl_firma WHERE tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND + tbl_projektarbeit.firma_id = tbl_firma.firma_id AND tbl_projektarbeit.student_uid = ?"; $params = array($student_uid); @@ -69,4 +71,30 @@ class Projektarbeit_model extends DB_Model return $this->execQuery($qry, $params); } + + /** + * + * @param + * @return object success or error + */ + public function hasBerechtigungForProjektarbeit($projektarbeit_id) + { + if (!$projektarbeit_id || !is_numeric($projektarbeit_id)) + return false; + + $this->ProjektarbeitModel->addSelect('studiengang_kz'); + $this->ProjektarbeitModel->addJoin('public.tbl_student', 'student_uid'); + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + if (isError($result) || !hasData($result)) + return false; + + $studiengang_kz = getData($result)[0]->studiengang_kz; + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz)) + return true; + + return false; + } } diff --git a/application/models/ressource/Firma_model.php b/application/models/ressource/Firma_model.php index 431f0815f..5ae53eeaf 100644 --- a/application/models/ressource/Firma_model.php +++ b/application/models/ressource/Firma_model.php @@ -12,17 +12,24 @@ class Firma_model extends DB_Model $this->pk = 'firma_id'; } - public function searchFirmen($filter) + public function searchFirmen($filter, $aktiv = null) { + $params = []; $filter = strtoLower($filter); $qry = " - SELECT + SELECT f.name, f.firma_id - FROM - public.tbl_firma f - WHERE - lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'"; + FROM + public.tbl_firma f + WHERE + lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'"; - return $this->execQuery($qry); + if (isset($aktiv) && is_bool($aktiv)) + { + $params[] = $aktiv; + $qry .= " AND aktiv = ?"; + } + + return $this->execQuery($qry, $params); } } diff --git a/public/js/api/factory/stv/projektarbeit.js b/public/js/api/factory/stv/projektarbeit.js new file mode 100644 index 000000000..243383de0 --- /dev/null +++ b/public/js/api/factory/stv/projektarbeit.js @@ -0,0 +1,80 @@ +/** + * 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 { + getProjektarbeit(uid) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getProjektarbeit', + params: { uid } + }; + }, + getTypenProjektarbeit() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getTypenProjektarbeit' + }; + }, + getFirmen(searchString) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getFirmen', + params: {searchString} + }; + }, + getLehrveranstaltungen(student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getLehrveranstaltungen', + params: { student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id } + }; + }, + getNoten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getNoten' + }; + }, + loadProjektarbeit(projektarbeit_id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/loadProjektarbeit', + params: { projektarbeit_id } + }; + }, + addNewProjektarbeit(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/insertProjektarbeit', + params + }; + }, + updateProjektarbeit(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/updateProjektarbeit', + params + }; + }, + deleteProjektarbeit(projektarbeit_id) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/deleteProjektarbeit', + params: { projektarbeit_id } + }; + } +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js new file mode 100644 index 000000000..3615e8f5d --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js @@ -0,0 +1,24 @@ +import Projektarbeit from './Projektarbeit/Projektarbeit.js'; + +export default { + name: "TabProjektarbeit", + components: { + Projektarbeit + }, + provide() { + return { + config: this.config + }; + }, + props: { + modelValue: Object, + config: Object + }, + data(){ + return {} + }, + template: ` +
+ +
` +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js new file mode 100644 index 000000000..5d223d694 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js @@ -0,0 +1,847 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; + +import ApiStvAbschlusspruefung from '../../../../../api/factory/stv/abschlusspruefung.js'; + +export default { + components: { + CoreFilterCmpt, + BsModal, + FormForm, + FormInput, + PvAutoComplete, + AbschlusspruefungDropdown, + PruefungList + }, + inject: { + cisRoot: { + from: 'cisRoot' + }, + config: { + from: 'config', + required: true + }, + $reloadList: { + from: '$reloadList', + required: true + }, + isBerechtigtDocAndOdt: { + from: 'hasPermissionOutputformat', + default: false + } + }, + computed: { + studentUids() { + if (this.student.uid) + { + return [this.student.uid]; + } + return this.student.map(e => e.uid); + }, + studentKzs(){ + if (this.student.uid) + { + return [this.student.studiengang_kz]; + } + return this.student.map(e => e.studiengang_kz); + }, + stg_kz(){ + return this.studentKzs[0]; + }, + }, + props: { + student: Object + }, + data() { + return { + tabulatorOptions: { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call(ApiStvAbschlusspruefung.getAbschlusspruefung(this.student.uid)), + ajaxResponse: (url, params, response) => response.data, + columns: [ + {title: "vorsitz", field: "vorsitz_nachname"}, + {title: "abschlussbeurteilung", field: "beurteilung_bezeichnung"}, + {title: "prueferIn1", field: "p1_nachname", visible: false}, + {title: "prueferIn2", field: "p2_nachname", visible: false}, + {title: "prueferIn3", field: "p3_nachname", visible: false}, + { + title: "datum", + field: "datum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + {title: "uhrzeit", field: "uhrzeit"}, + { + title: "freigabe", + field: "freigabedatum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + {title: "pruefungsantritt", field: "antritt_bezeichnung"}, + { + title: "sponsion", + field: "sponsion", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + {title: "anmerkung", field: "anmerkung"}, + {title: "abschlusspruefung_id", field: "abschlusspruefung_id", visible: false}, + {title: "typ", field: "pruefungstyp_kurzbz", visible: false}, + + { + title: 'Aktionen', field: 'actions', + minWidth: 150, // Ensures Action-buttons will be always fully displayed + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'bearbeiten'); + button.addEventListener('click', (event) => + this.actionEditAbschlusspruefung(cell.getData().abschlusspruefung_id) + ); + container.append(button); + + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', () => + this.actionDeleteAbschlusspruefung(cell.getData().abschlusspruefung_id) + ); + container.append(button); + + container.append(cell.getData().actionDiv); + + return container; + }, + frozen: true + }, + ], + layout: 'fitDataFill', + layoutColumnsOnNewData: false, + height: 'auto', + minHeight: '200', + selectable: true, + index: 'abschlusspruefung_id', + persistenceID: 'stv-details-finalexam' + }, + tabulatorEvents: [ + { + event: 'dataLoaded', + handler: data => this.tabulatorData = data.map(item => { + item.actionDiv = document.createElement('div'); + return item; + }), + }, + { + event: 'tableBuilt', + handler: async() => { + await this.$p.loadCategory(['global', 'person', 'stv', 'abschlusspruefung', 'ui']); + + + let cm = this.$refs.table.tabulator.columnManager; + + cm.getColumnByField('vorsitz_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'vorsitz_header') + }); + cm.getColumnByField('beurteilung_bezeichnung').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'abschlussbeurteilung') + }); + cm.getColumnByField('p1_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefer1') + }); + cm.getColumnByField('p2_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefer2') + }); + cm.getColumnByField('p3_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefer3') + }); + cm.getColumnByField('datum').component.updateDefinition({ + title: this.$p.t('global', 'datum') + }); + cm.getColumnByField('uhrzeit').component.updateDefinition({ + title: this.$p.t('global', 'uhrzeit') + }); + cm.getColumnByField('freigabedatum').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'freigabe') + }); + cm.getColumnByField('antritt_bezeichnung').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefungsantritt') + }); + cm.getColumnByField('sponsion').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'sponsion') + }); + cm.getColumnByField('anmerkung').component.updateDefinition({ + title: this.$p.t('global', 'anmerkung') + }); + cm.getColumnByField('pruefungstyp_kurzbz').component.updateDefinition({ + title: this.$p.t('global', 'typ') + }); + cm.getColumnByField('abschlusspruefung_id').component.updateDefinition({ + title: this.$p.t('ui', 'abschlusspruefung_id') + }); + /* + cm.getColumnByField('actions').component.updateDefinition({ + title: this.$p.t('global', 'aktionen') + }); + */ + } + } + ], + tabulatorData: [], + lastSelected: null, + formData: { + typStg: null, + pruefungstyp_kurzbz: null, + akadgrad_id: null, + vorsitz: null, + pruefungsantritt_kurzbz: null, + abschlussbeurteilung_kurzbz: null, + datum: null, + sponsion: null, + pruefer1: null, + pruefer2: null, + pruefer3: null, + anmerkung: null, + protokoll: null, + note: null, + link: null + }, + statusNew: true, + arrTypen: [], + arrAntritte: [], + arrBeurteilungen: [], + arrAkadGrad: [], + arrNoten: [], + filteredMitarbeiter: [], + filteredPruefer: [], + abortController: { + mitarbeiter: null, + pruefer: null + }, + stgInfo: { typ: '', oe_kurzbz: '' } + } + }, + watch: { + student(){ + if (this.$refs.table) { + this.$refs.table.reloadTable(); + } + this.getStudiengangByKz(); + } + }, + methods: { + getStudiengangByKz(){ + this.stgInfo = { typ: '', oe_kurzbz: '' }; + this.$api + .call(ApiStudiengang.getStudiengangByKz(this.stg_kz)) + .then(result => this.stgInfo = result.data) + .catch(this.$fhcAlert.handleSystemError); + }, + actionNewAbschlusspruefung() { + this.resetForm(); + this.statusNew = true; + this.$refs.finalexamModal.show(); + this.setDefaultFormData(); + }, + actionEditAbschlusspruefung(abschlusspruefung_id) { + this.resetForm(); + this.statusNew = false; + this.$refs.finalexamModal.show(); + this.loadAbschlusspruefung(abschlusspruefung_id); + }, + actionDeleteAbschlusspruefung(abschlusspruefung_id) { + this.$fhcAlert + .confirmDelete() + .then(result => result + ? abschlusspruefung_id + : Promise.reject({handled: true})) + .then(this.deleteAbschlusspruefung) + .catch(this.$fhcAlert.handleSystemError); + }, + addNewAbschlusspruefung() { + const dataToSend = { + uid: this.student.uid, + formData: this.formData + }; + + return this.$refs.formFinalExam + .call(ApiStvAbschlusspruefung.addNewAbschlusspruefung(dataToSend)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.hideModal('finalexamModal'); + this.resetForm(); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + hideModal(modalRef){ + this.$refs[modalRef].hide(); + }, + reload() { + this.$refs.table.reloadTable(); + }, + loadAbschlusspruefung(abschlusspruefung_id) { + return this.$api + .call(ApiStvAbschlusspruefung.loadAbschlusspruefung(abschlusspruefung_id)) + .then(result => { + this.formData = result.data; + //TODO(Manu) check if cisRoot is okay + this.formData.link = this.cisRoot + 'index.ci.php/lehre/Pruefungsprotokoll/showProtokoll?abschlusspruefung_id=' + this.formData.abschlusspruefung_id + '&fhc_controller_id=67481e5ed5490'; + return result; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + updateAbschlusspruefung(abschlusspruefung_id) { + const dataToSend = { + id: abschlusspruefung_id, + formData: this.formData + }; + return this.$refs.formFinalExam + .call(ApiStvAbschlusspruefung.updateAbschlusspruefung(dataToSend)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.hideModal('finalexamModal'); + this.resetForm(); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + deleteAbschlusspruefung(abschlusspruefung_id) { + return this.$api + .call(ApiStvAbschlusspruefung.deleteAbschlusspruefung(abschlusspruefung_id)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + resetForm() { + this.formData.pruefungstyp_kurzbz = null; + this.formData.akadgrad_id = null; + this.formData.vorsitz = null; + this.formData.pruefungsantritt_kurzbz = null; + this.formData.abschlussbeurteilung_kurzbz = null; + this.formData.datum = null; //oder new Date(); + this.formData.sponsion = null; + this.formData.pruefer1 = null; + this.formData.pruefer2 = null; + this.formData.pruefer3 = null; + this.formData.anmerkung = null; + this.formData.protokoll = null; + this.formData.note = null; + this.formData.p1 = null; + this.formData.p2 = null; + this.formData.p3 = null; + this.formData.pv = null; + }, + search(event) { + if (this.abortController.mitarbeiter) { + this.abortController.mitarbeiter.abort(); + } + this.abortController.mitarbeiter = new AbortController(); + + return this.$api + .call(ApiStvAbschlusspruefung.getMitarbeiter(event.query)) + .then(result => { + this.filteredMitarbeiter = result.data.retval; + }); + }, + searchNotAkad(event) { + if (this.abortController.pruefer) { + this.abortController.pruefer.abort(); + } + this.abortController.pruefer = new AbortController(); + + return this.$api + .call(ApiStvAbschlusspruefung.getPruefer(event.query)) + .then(result => { + this.filteredPruefer = result.data.retval; + }); + }, + setDefaultFormData() { + + this.resetForm(); + + if (this.stgInfo.typ === 'b') { + this.formData.pruefungstyp_kurzbz = 'Bachelor'; + this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); + } + if (this.stgInfo.typ === 'd' || this.stgInfo === 'm') { + this.formData.pruefungstyp_kurzbz = 'Diplom'; + this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); + } + if (this.stgInfo.typ === 'lg') { + this.formData.pruefungstyp_kurzbz = 'lgabschluss'; + } + + if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) { + this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id; + } + }, + printDocument(link) { + window.open(link, '_blank'); + }, + }, + created() { + this.$api + .call(ApiStvAbschlusspruefung.getTypenAbschlusspruefung()) + .then(result => { + this.arrTypen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getTypenAntritte()) + .then(result => { + this.arrAntritte = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getBeurteilungen()) + .then(result => { + this.arrBeurteilungen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getNoten()) + .then(result => { + this.arrNoten = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getAkadGrade(this.student.studiengang_kz)) + .then(result => { + this.arrAkadGrad = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + if (!this.student.length) { + this.$api + .call(ApiStudiengang.getStudiengangByKz(this.student.studiengang_kz)) + .then(result => { + this.stgInfo = result.data; + this.setDefaultFormData(); + }) + .catch(this.$fhcAlert.handleSystemError); + } else + this.getStudiengangByKz(); + }, + template: ` +
+

{{this.$p.t('stv','tab_finalexam')}}

+ +
+ +
+ + + + + + + + + + + + + {{this.$p.t('global','details')}} +

[{{$p.t('ui', 'neu')}}]

+
+ + + + + + + +
+ +
+ + + + +
+ +
+ + + + + +
+ +
+ + + + + + + +
+ +
+ + + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+
+

{{$p.t('abschlusspruefung', 'zurBeurteilung')}}

+
+ +
+ +
+ + + +
+ + + + +
+` +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js new file mode 100644 index 000000000..a6256ceb1 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -0,0 +1,461 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; + +import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js'; + +export default { + components: { + CoreFilterCmpt, + FormForm, + FormInput, + PvAutoComplete + }, + emits: ['details-saved'], + inject: { + defaultSemester: { + from: 'defaultSemester' + } + //~ cisRoot: { + //~ from: 'cisRoot' + //~ }, + //~ config: { + //~ from: 'config', + //~ required: true + //~ } + }, + computed: { + arrLes() { + let lehreinheiten = []; + if (this.formData.lehrveranstaltung_id) { + let lv = this.arrLvs.find(lv => {return lv.lehrveranstaltung_id == this.formData.lehrveranstaltung_id}); + if (lv) lehreinheiten = lv.lehreinheiten + } + + for (let le of lehreinheiten) + { + let bezeichnung = le.lehrfach_kurzbz + '-' + le.lehrform_kurzbz + ' ' + le.lehrfach_bezeichnung + ' '; + + for (let grp of le.lehreinheitgruppen) + { + bezeichnung += grp.gruppe_kurzbz ? grp.gruppe_kurzbz : '' + grp.semester ?? '' + grp.verband ?? '' + grp.gruppe ?? ''; + } + + bezeichnung += ' (' + le.lektoren.join(' ') + ') ID: ' + le.lehreinheit_id; + + le.bezeichnung = bezeichnung; + } + + return lehreinheiten; + }, + //~ preparedFormData() { + //~ console.log("FOR DATA CALLEd"); + //~ if (this.formData.projektarbeit_id == null) delete(this.formData.projektarbeit_id); + //~ if (this.formData.firma) this.formData.firma_id = this.formData.firma.firma_id; + //~ delete(this.formData.firma); + //~ delete(this.formData.firma_name); + //~ delete(this.formData.lehrveranstaltung_id); + //~ // convert null value fields from string to null + //~ return this.formData; + //~ } + }, + props: { + statusNew: Boolean, + student: Object, + projektarbeit: Object, + stg_kz: Number + }, + data() { + return { + formData: { + projektarbeit_id: null, + titel: null, + titel_english: null, + themenbereich: null, + projekttyp_kurzbz: null, + firma: null, + lehrveranstaltung_id: null, + lehreinheit_id: null, + beginn: null, + ende: null, + freigegeben: true, + gesperrtbis: null, + note: null, + final: true, + anmerkung: null + }, + arrTypen: [], + arrFirmen: [], + arrLvs: [], + arrNoten: [], + filteredFirmen: [], + abortController: { + firma: null + } + } + }, + methods: { + resetForm() { + this.formData.projektarbeit_id = null; + this.formData.titel = null; + this.formData.titel_english = null; + this.formData.themenbereich = null; + this.formData.projekttyp_kurzbz = null; + this.formData.firma = null; + this.formData.lehrveranstaltung_id = null; + this.formData.lehreinheit_id = null; + this.formData.beginn = null; + this.formData.ende = null; + this.formData.freigegeben = true; + this.formData.gesperrtbis = null; + this.formData.note = null; + this.formData.final = true; + this.formData.anmerkung = null; + }, + getFormData(statusNew, studiensemester_kurzbz, additional_lehrveranstaltung_id/*, successCallback*/) { + + //~ let callArray = [ + //~ this.$api.call(ApiStvProjektarbeit.getTypenProjektarbeit()), + //~ this.$api.call(ApiStvProjektarbeit.getLehrveranstaltungen( + //~ this.student.uid, + //~ projektarbeit_id ? null : this.student.studiengang_kz, + //~ studiensemester_kurzbz ?? this.defaultSemester, + //~ additional_lehrveranstaltung_id ?? null + //~ )), + //~ this.$api.call(ApiStvProjektarbeit.getNoten()) + //~ ]; + + //~ if (projektarbeit_id) callArray.push(this.$api.call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id))); + + //~ // Run when All promises are settled + //~ Promise.allSettled(callArray).then((results) => { + //~ let hasError = false; + //~ let allFormData = []; + //~ results.forEach((promise_result) => { + + //~ if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") { + //~ allFormData.push(promise_result.value.data); + //~ } else { + //~ hasError = true; + //~ //this.$fhcAlert.handleSystemError(promise_result); + //~ } + //~ //let data = promise_result.value.data; + //~ console.log(promise_result.status); + //~ }); + + //~ if (!hasError) { + //~ this.setFormData(allFormData[0], allFormData[1], allFormData[2], allFormData[3], allFormData[4] ?? null); + //~ if (successCallback) successCallback(); + //~ } + //~ }); + + this.$api + .call(ApiStvProjektarbeit.getTypenProjektarbeit()) + .then(result => { + this.arrTypen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvProjektarbeit.getLehrveranstaltungen( + this.student.uid, + statusNew ? this.student.studiengang_kz : null, + studiensemester_kurzbz ?? this.defaultSemester, + additional_lehrveranstaltung_id + )) + .then(result => { + this.arrLvs = result.data + } + ) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvProjektarbeit.getNoten()) + .then(result => { + this.arrNoten = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + setFormData(arrTypen, arrLvs, arrNoten, projektarbeitData) { + this.arrTypen = arrTypen; + this.arrLvs = arrLvs; + this.arrNoten = arrNoten; + if (projektarbeitData) { + projektarbeitData.firma = {firma_id: projektarbeitData.firma_id, name: projektarbeitData.firma_name}; + this.formData = projektarbeitData; + } + }, + loadProjektarbeit(projektarbeit_id) { + + return this.$api + .call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id)) + .then(result => { + this.formData = result.data; + return result; + }) + .catch(this.$fhcAlert.handleSystemError) + }, + addNewProjektarbeit() { + + let dataToSend = { + uid: this.student.uid, + formData: this.getPreparedFormData() + }; + + return this.$refs.formDetails + .call(ApiStvProjektarbeit.addNewProjektarbeit(dataToSend)); + }, + updateProjektarbeit() { + + let dataToSend = { + projektarbeit_id: this.formData.projektarbeit_id, + formData: this.getPreparedFormData() + }; + return this.$refs.formDetails + .call(ApiStvProjektarbeit.updateProjektarbeit(dataToSend)); + }, + searchFirma(event) { + if (this.abortController.firma) { + this.abortController.firma.abort(); + } + this.abortController.firma = new AbortController(); + + return this.$api + .call(ApiStvProjektarbeit.getFirmen(event.query)) + .then(result => { + this.filteredFirmen = result.data; + }); + }, + lvChanged(event) { + this.formData.lehreinheit_id = null; + }, + getPreparedFormData() { + let preparedFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy + + // delete "helper" fields + if (preparedFormData.projektarbeit_id == null) delete(preparedFormData.projektarbeit_id); + if (preparedFormData.firma) preparedFormData.firma_id = preparedFormData.firma.firma_id; + delete(preparedFormData.firma); + delete(preparedFormData.firma_name); + delete(preparedFormData.lehrveranstaltung_id); + + return preparedFormData; + } + //~ setDefaultFormData() { + //~ this.resetForm(); + //~ }, + }, + template: ` + + + {{this.$p.t('global','details')}} +

[{{$p.t('ui', 'neu')}}]

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + +
+ + +
+ + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + +
+ + +
+
+ +
+ + + + +
+ + +
+
+ +
+ + +
+ +
` +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js new file mode 100644 index 000000000..034b3fd6c --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -0,0 +1,377 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import BsModal from "../../../../Bootstrap/Modal.js"; +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; + + +import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js'; +import ProjektarbeitDetails from "./Details.js"; + +export default { + components: { + CoreFilterCmpt, + BsModal, + FormForm, + FormInput, + PvAutoComplete, + ProjektarbeitDetails + }, + inject: { + cisRoot: { + from: 'cisRoot' + }, + config: { + from: 'config', + required: true + }, + $reloadList: { + from: '$reloadList', + required: true + }, + isBerechtigtDocAndOdt: { + from: 'hasPermissionOutputformat', + default: false + } + }, + computed: { + //~ studentUids() { + //~ if (this.student.uid) + //~ { + //~ return [this.student.uid]; + //~ } + //~ return this.student.map(e => e.uid); + //~ }, + studentKzs(){ + if (this.student.uid) + { + return [this.student.studiengang_kz]; + } + return this.student.map(e => e.studiengang_kz); + }, + stg_kz(){ + return this.studentKzs.length > 0 ? this.studentKzs.length[0] : null; + } + }, + props: { + student: Object + }, + data() { + return { + tabulatorOptions: { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call(ApiStvProjektarbeit.getProjektarbeit(this.student.uid)), + ajaxResponse: (url, params, response) => response.data, + columns: [ + {title: "Projektarbeit ID", field: "projektarbeit_id", visible: false}, + {title: "Typ", field: "projekttyp_kurzbz"}, + {title: "Studiensemester", field: "studiensemester_kurzbz"}, + {title: "Titel", field: "titel"}, + { + title: "Abgabe Enduplad", + field: "abgabedatum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + { + title: "Beginn", + field: "beginn", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + }, + visible: false + }, + { + title: "Ende", + field: "ende", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + }, + visible: false + }, + { + title:"Freigegeben", + field:"freigegeben", + formatter:"tickCross", + hozAlign:"center", + formatterParams: { + tickElement: '', + crossElement: '' + }, + visible: false + }, + { + title: "Gesperrt bis", + field: "gesperrtbis", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + }, + visible: false + }, + {title: "Themenbereich", field: "themenbereich", visible: false}, + {title: "Anmerkung", field: "anmerkung", visible: false}, + {title: "Lehreinheit ID", field: "lehreinheit_id", visible: false}, + {title: "Student UID", field: "student_uid", visible: false}, + { + title:"Final", + field:"final", + formatter:"tickCross", + hozAlign:"center", + formatterParams: { + tickElement: '', + crossElement: '' + }, + visible: false + }, + {title: "Firma ID", field: "firma_id", visible: false}, + { + title: 'Aktionen', field: 'actions', + minWidth: 150, // Ensures Action-buttons will be always fully displayed + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'bearbeiten'); + button.addEventListener('click', (event) => { + let data = cell.getData(); + this.actionEditProjektarbeit(data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id); + }); + container.append(button); + + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', () => + this.actionDeleteProjektarbeit(cell.getData().projektarbeit_id) + ); + container.append(button); + + container.append(cell.getData().actionDiv); + + return container; + }, + frozen: true + }, + ], + layout: 'fitDataFill', + layoutColumnsOnNewData: false, + height: 'auto', + minHeight: '200', + selectable: 1, + index: 'projektarbeit_id', + persistenceID: 'stv-details-projektarbeit' + }, + tabulatorEvents: [ + { + event: 'rowSelectionChanged', + handler: this.rowSelectionChanged + }, + { + event: 'dataLoaded', + handler: data => this.tabulatorData = data.map(item => { + item.actionDiv = document.createElement('div'); + return item; + }), + }, + { + event: 'tableBuilt', + handler: async() => { + await this.$p.loadCategory(['global', 'person', 'stv', 'ui']); + + + let cm = this.$refs.table.tabulator.columnManager; + + //~ cm.getColumnByField('vorsitz_nachname').component.updateDefinition({ + //~ title: this.$p.t('abschlusspruefung', 'vorsitz_header') + //~ }); + /* + cm.getColumnByField('actions').component.updateDefinition({ + title: this.$p.t('global', 'aktionen') + }); + */ + } + }, + ], + tabulatorData: [], + lastSelected: null, + statusNew: true, + studiensemester_kurzbz: null, + lehrveranstaltung_id: null + } + }, + //~ watch: { + //~ student(){ + //~ if (this.$refs.table) { + //~ this.$refs.table.reloadTable(); + //~ } + //~ this.getStudiengangByKz(); + //~ } + //~ }, + methods: { + actionNewProjektarbeit() { + this.statusNew = true; + this.$refs.projektarbeitDetails.resetForm(); + this.$refs.projektarbeitDetails.getFormData(); + this.$refs.projektarbeitModal.show(); + }, + actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id) { + this.statusNew = false; + this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id); + this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id); + this.$refs.projektarbeitModal.show(); + }, + actionDeleteProjektarbeit(projektarbeit_id) { + this.$fhcAlert + .confirmDelete() + .then(result => result + ? projektarbeit_id + : Promise.reject({handled: true})) + .then(this.deleteProjektarbeit) + .catch(this.$fhcAlert.handleSystemError); + }, + addNewProjektarbeit() { + Promise.allSettled([ + this.$refs.projektarbeitDetails.addNewProjektarbeit() + ]).then((results) => { + let hasError = false; + results.forEach((promise_result) => { + + if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) { + + hasError = true; + } + }); + + if (!hasError) { + this.projektarbeitSaved(); + } + }); + }, + updateProjektarbeit() { + Promise.allSettled( + [ + this.$refs.projektarbeitDetails.updateProjektarbeit() + ]).then((results) => { + let hasError = false; + results.forEach((promise_result) => { + + if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) { + + hasError = true; + } + }); + + if (!hasError) { + this.projektarbeitSaved(); + } + }); + }, + deleteProjektarbeit(projektarbeit_id) { + return this.$api + .call(ApiStvProjektarbeit.deleteProjektarbeit(projektarbeit_id)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + projektarbeitSaved() { + this.reload(); + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.hideModal('projektarbeitModal'); + this.$refs.projektarbeitDetails.resetForm(); + }, + rowSelectionChanged(data) { + console.log("selection changed"); + this.lastSelected = data.length > 0 ? data[0] : null; + }, + hideModal(modalRef){ + this.$refs[modalRef].hide(); + }, + reload() { + this.$refs.table.reloadTable(); + } + }, + created() { + }, + template: ` +
+

{{this.$p.t('stv','tab_projektarbeit')}}

+ + + + + + + + + + + + + +
+` +} + From 382006aa8bfdec7696256d2b2236eb448003daf7 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 16 May 2025 13:37:21 +0200 Subject: [PATCH 012/388] Projektarbeit Studierendenverwaltung: now possible to save and edit Projektbetreuer --- application/config/stv.php | 7 +- .../api/frontend/v1/stv/Config.php | 5 +- .../api/frontend/v1/stv/Projektarbeit.php | 11 +- .../api/frontend/v1/stv/Projektbetreuer.php | 333 +++++++ .../models/education/Projektarbeit_model.php | 9 +- .../education/Projektbetreuer_model.php | 1 + application/models/person/Person_model.php | 19 +- .../models/ressource/Stundensatz_model.php | 95 +- public/js/api/factory/stv/projektbetreuer.js | 73 ++ .../Details/Projektarbeit/Betreuung.js | 847 ------------------ .../Details/Projektarbeit/Details.js | 27 +- .../Details/Projektarbeit/Projektarbeit.js | 86 +- .../Details/Projektarbeit/Projektbetreuer.js | 421 +++++++++ system/phrasesupdate.php | 2 +- 14 files changed, 1002 insertions(+), 934 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/Projektbetreuer.php create mode 100644 public/js/api/factory/stv/projektbetreuer.js delete mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js diff --git a/application/config/stv.php b/application/config/stv.php index 31ce3f521..f5c1599ab 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -54,7 +54,7 @@ $config['tabs'] = ], ] ]; - + // List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined $fieldsZgvDoktor = ['zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', 'zgvdoktor_erfuellt', 'zgvdoktor_code']; @@ -74,3 +74,8 @@ if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) { $fieldsZgvDoktor ); } + +$config['tabs']['projektarbeit']['defaultProjektbetreuerStunden'] = '4.0'; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStundenDiplom'] = '5.0'; +$config['tabs']['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz'] = true; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStundensatz'] = '80.0'; diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index dd2eaed02..afdf8efb8 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -125,7 +125,8 @@ class Config extends FHCAPI_Controller $result['projektarbeit'] = [ 'title' => $this->p->t('stv', 'tab_projektarbeit'), - 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js' + 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js', + 'config' => $config['projektarbeit'] ]; $result['mobility'] = [ @@ -323,7 +324,7 @@ class Config extends FHCAPI_Controller $title_eng = $this->p->t("global", "englisch"); $title_ff = $this->p->t("stv", "document_certificate"); $title_lv = $this->p->t("stv", "document_coursecertificate"); - + $link_ff = "documents/export/" . "zertifikat.rdf.php/" . "Zertifikat" . diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php index 3be2b26a3..70775fdbc 100644 --- a/application/controllers/api/frontend/v1/stv/Projektarbeit.php +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -17,7 +17,7 @@ class Projektarbeit extends FHCAPI_Controller 'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'], 'getFirmen' => ['admin:r', 'assistenz:r'], 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], - 'getNoten' => ['admin:rw', 'assistenz:rw'] + 'getNoten' => ['admin:r', 'assistenz:r'] ]); // Load Libraries @@ -91,7 +91,7 @@ class Projektarbeit extends FHCAPI_Controller ); $this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); $this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); - $this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id'); + $this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id', 'LEFT'); $result = $this->ProjektarbeitModel->loadWhere( array('projektarbeit_id' => $projektarbeit_id) ); @@ -170,7 +170,7 @@ class Projektarbeit extends FHCAPI_Controller if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); $result = $this->ProjektarbeitModel->delete( - array('projektarbeit_id' => $projektarbeit_id) + ['projektarbeit_id' => $projektarbeit_id] ); if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); @@ -273,10 +273,9 @@ class Projektarbeit extends FHCAPI_Controller 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp']) ]); - $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|numeric', [ + $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|is_natural', [ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), - //'matches' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), - 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) + 'is_natural' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) ]); $this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [ diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php new file mode 100644 index 000000000..ac6663132 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -0,0 +1,333 @@ + ['admin:r', 'assistenz:r'], + 'saveProjektbetreuer' => ['admin:rw', 'assistenz:rw'], + 'deleteProjektbetreuer' => ['admin:rw', 'assistenz:rw'], + 'getBetreuerarten' => ['admin:r', 'assistenz:r'], + 'getNoten' => ['admin:r', 'assistenz:r'], + 'getDefaultStundensaetze' => ['admin:r', 'assistenz:r'], + 'getProjektbetreuerBySearchQuery' => ['admin:r', 'assistenz:r'], + 'validateProjektbetreuer' => ['admin:r', 'assistenz:r'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); + $this->load->model('education/Betreuerart_model', 'BetreuerartModel'); + $this->load->model('ressource/Stundensatz_model', 'StundensatzModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->load->model('education/Note_model', 'NoteModel'); + $this->load->model('person/Person_model', 'PersonModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getProjektbetreuer() + { + $projektarbeit_id = $this->input->get('projektarbeit_id'); + + if (!isset($projektarbeit_id)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + $this->ProjektbetreuerModel->addSelect( + 'projektarbeit_id, person_id, nachname, vorname, note, punkte, stunden, stundensatz, betreuerart_kurzbz, vertrag_id, titelpre, titelpost' + ); + $this->ProjektbetreuerModel-> addSelect("CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=pers.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=pers.person_id) + THEN 'Student' + ELSE 'Person' + END AS status"); + $this->ProjektbetreuerModel->addJoin('public.tbl_person pers', 'person_id'); + $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $projektbetreuer = getData($result); + + //~ foreach ($projektbetreuer as $projektarbeit) + //~ { + //~ $projektarbeit_id = $projektarbeit->projektarbeit_id; + //~ $abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id); + + //~ if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL); + + //~ if (hasData($abgabeRes)) + //~ { + //~ $paabgabe = getData($abgabeRes)[0]; + //~ $projektarbeit->abgabedatum = $paabgabe->abgabedatum; + //~ } + //~ } + + $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); + } + + public function saveProjektbetreuer() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $projektbetreuer = $this->input->post('projektbetreuerListe'); + + //$this->addMeta('form', $projektbetreuer); + + if (!is_array($projektbetreuer)) + { + return $this->terminateWithError( + $this->p->t('projektarbeit', 'error_invalidProjektbetreuer'), self::ERROR_TYPE_GENERAL + ); + } + + foreach ($projektbetreuer as $pb) + { + if ($this->_validate($pb) == false) + { + $this->addMeta('test', 'foisch'); + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + } + + $result = null; + + foreach ($projektbetreuer as $pb) + { + //~ $this->addMeta('form', $pb); + //~ error_log(print_r($pb, true)); + //die(); + + //~ $this->ProjektbetreuerModel->addSelect('1'); + //~ $checkResult = $this->ProjektbetreuerModel->loadWhere( + //~ ['person_id' => $pb['person_id'], 'projektarbeit_id' => $projektarbeit_id, 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz']] + //~ ); + + //~ if (isError($checkResult)) $this->terminateWithError(getError($checkResult), self::ERROR_TYPE_GENERAL); + + $betreuer = [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $pb['person_id'], + 'note' => $pb['note'], + 'stunden' => $pb['stunden'], + 'stundensatz' => $pb['stundensatz'], + 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz'] + ]; + + if (isset($pb['person_id_old']) && isset($pb['betreuerart_kurzbz_old'])) + { + $result = $this->ProjektbetreuerModel->update( + [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $pb['person_id_old'], + 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz_old'] + ], + array_merge($betreuer, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) + ); + } + else + { + $result = $this->ProjektbetreuerModel->insert( + array_merge($betreuer, ['insertamum' => date('c'), 'insertvon' => getAuthUID()]) + ); + } + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function deleteProjektbetreuer() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $person_id = $this->input->post('person_id'); + $betreuerart_kurzbz = $this->input->post('betreuerart_kurzbz'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektbetreuer ID'], self::ERROR_TYPE_GENERAL)); + + if (!isset($person_id) || !is_numeric($person_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID'], self::ERROR_TYPE_GENERAL)); + + if (!isset($betreuerart_kurzbz)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Betreuerart'], self::ERROR_TYPE_GENERAL)); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $validate = $this->_validateDelete($projektarbeit_id, $person_id); + + if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektbetreuerModel->delete( + ['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz] + ); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) + { + $this->outputJson($result); + } + + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getBetreuerarten() + { + $result = $this->BetreuerartModel->loadWhere(['aktiv' => true]); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getNoten() + { + $result = $this->NoteModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getDefaultStundensaetze() + { + $person_id = $this->input->get('person_id'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + + $result = $this->StundensatzModel->getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz); + + $this->addMeta('res', $result); + + //if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess($result); + } + + public function getProjektbetreuerBySearchQuery() + { + $searchString = $this->input->get('searchString'); + + if (!isset($searchString)) $this->terminateWithError($this->p->t('projektarbeit', 'error_searchStringMissing', self::ERROR_TYPE_GENERAL)); + + $result = $this->PersonModel->searchPerson($searchString); + + $this->addMeta('met', $result); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? $this->_addFullNameToBetreuer(getData($result)) : []); + } + + /** + * + * @param + * @return object success or error + */ + public function validateProjektbetreuer() + { + $projektbetreuerArr = $this->input->post('projektbetreuer'); + + if (!is_array($projektbetreuerArr)) $projektbetreuerArr = [$projektbetreuerArr]; + + foreach ($projektbetreuerArr as $pb) + { + if ($this->_validate($pb) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + } + + $this->terminateWithSuccess([]); + } + + /** + * + * @param + * @return object success or error + */ + private function _validate($formData) + { + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('betreuerart_kurzbz', 'Betreuerart', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Betreuerart']) + ]); + + $this->form_validation->set_rules('person_id', 'Person', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Person ID']) + ]); + + $this->form_validation->set_rules('stunden', 'Stunden', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stunden']) + ]); + + $this->form_validation->set_rules('stundensatz', 'Stundensatz', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stundensatz']) + ]); + + + return $this->form_validation->run(); + } + + /** + * + * @param + * @return object success or error + */ + private function _validateDelete($projektarbeit_id, $person_id) + { + $this->ProjektbetreuerModel->addSelect('vertrag_id'); + $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id]); + + if (isError($result)) return $result; + + if (hasData($result) && getData($result)[0]->vertrag_id != null) return error($this->p->t('projektarbeit', 'error_betreuerHatVertrag')); + + return success(); + } + + /** + * + * @param + * @return object success or error + */ + private function _addFullNameToBetreuer($betreuerArr) + { + foreach ($betreuerArr as $betreuer) + { + $betreuer->name = ($betreuer->titelpre ? $betreuer->titelpre . ' ' : '') . + $betreuer->nachname . ' ' . $betreuer->vorname . ($betreuer->titelpost ? ' ' . $betreuer->titelpre : ''). + ' (' . $betreuer->status . ')'; + } + + return $betreuerArr; + } +} diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 2be79f8e9..357886de1 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -29,12 +29,11 @@ class Projektarbeit_model extends DB_Model tbl_firma.name AS firma_name FROM lehre.tbl_projektarbeit - JOIN - lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, public.tbl_firma + JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) + JOIN lehre.tbl_lehreinheit USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) + LEFT JOIN public.tbl_firma USING (firma_id) WHERE - tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND - tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND - tbl_projektarbeit.firma_id = tbl_firma.firma_id AND tbl_projektarbeit.student_uid = ?"; $params = array($student_uid); diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 95950bf95..02368ae21 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -10,6 +10,7 @@ class Projektbetreuer_model extends DB_Model parent::__construct(); $this->dbTable = 'lehre.tbl_projektbetreuer'; $this->pk = array('betreuerart_kurzbz', 'projektarbeit_id', 'person_id'); + $this->hasSequence = false; } /** diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php index 997048972..d955f6401 100644 --- a/application/models/person/Person_model.php +++ b/application/models/person/Person_model.php @@ -151,12 +151,21 @@ class Person_model extends DB_Model */ public function searchPerson($filter) { - $this->addSelect('vorname, nachname, gebdatum, person_id'); + $this->addSelect('vorname, nachname, gebdatum, person_id, titelpre, titelpost'); + $this->addSelect("CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=tbl_person.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=tbl_person.person_id) + THEN 'Student' + ELSE 'Person' + END AS status"); $result = $this->loadWhere( - 'lower(nachname) like '.$this->db->escape('%'.$filter.'%')." + 'lower(nachname) like '.$this->db->escape('%'.mb_strtolower($filter).'%')." OR lower(vorname) like ".$this->db->escape('%'.$filter.'%')." - OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.$filter.'%')." - OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%') + OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.mb_strtolower($filter).'%')." + OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.mb_strtolower($filter).'%') ); return $result; @@ -423,4 +432,4 @@ class Person_model extends DB_Model return success($result); } } -} \ No newline at end of file +} diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index 10f5a6aa1..9d41dfbd9 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -2,7 +2,7 @@ class Stundensatz_model extends DB_Model { - + /** * Constructor */ @@ -42,4 +42,95 @@ class Stundensatz_model extends DB_Model return $this->execQuery($qry, $params); } -} \ No newline at end of file + + public function getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz) + { + $this->load->config('stv'); + + $useFixangestelltStundensatz = $this->config->item('tabs')['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz']; + $defaultStundensatz = $this->config->item('tabs')['projektarbeit']['defaultProjektbetreuerStundensatz']; + + $stundensatz = ''; + + if(isset($person_id) && isset($studiensemester_kurzbz)) + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addSelect('start, ende'); + $result = $this->StudiensemesterModel->load($studiensemester_kurzbz); + + if (hasData($result)) + { + $studiensemester = getData($result)[0]; + + if (isset($useFixangestelltStundensatz) && !$useFixangestelltStundensatz) + { + // load Mitarbeiter + $params = [$person_id]; + $qry = " + SELECT + mitarbeiter_uid, fixangestellt + FROM + public.tbl_mitarbeiter + JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid) + WHERE + person_id=? + ORDER BY + tbl_mitarbeiter.insertamum DESC NULLS LAST + LIMIT 1"; + + $result = $this->execQuery($qry, $params); + + if (hasData($result)) + { + foreach (getData($result) as $ma) + { + if (!$ma->fixangestellt) + { + $stundensatzRes = $this->getStundensatzByDatum( + $ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre' + ); + + if (hasData($stundensatzRes)) + $stundensatz = getData($stundensatzRes)[0]->stundensatz; + else + $stundensatz = '0.00'; + } + } + } + else + { + $stundensatz = '0.00'; + } + + } + else + { + $params = [$person_id, $studiensemester->ende, $studiensemester->start]; + $qry = "SELECT ss.stundensatz + FROM hr.tbl_stundensatz ss + JOIN public.tbl_mitarbeiter ON ss.uid = tbl_mitarbeiter.mitarbeiter_uid + JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid) + WHERE person_id=? + AND stundensatztyp = 'lehre' + AND gueltig_von <= ? + AND (gueltig_bis >= ? OR gueltig_bis IS NULL) + ORDER BY gueltig_bis DESC NULLS FIRST, gueltig_von DESC NULLS LAST LIMIT 1"; + + $result = $this->execQuery($qry, $params); + + if (hasData($result)) + { + $stundensatz = getData($result)[0]->stundensatz; + } + else + { + $stundensatz = $defaultStundensatz; + } + } + } + } + + return $stundensatz; + } +} diff --git a/public/js/api/factory/stv/projektbetreuer.js b/public/js/api/factory/stv/projektbetreuer.js new file mode 100644 index 000000000..fc710fe81 --- /dev/null +++ b/public/js/api/factory/stv/projektbetreuer.js @@ -0,0 +1,73 @@ +/** + * 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 { + getProjektbetreuer(projektarbeit_id ) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuer', + params: { projektarbeit_id } + }; + }, + getBetreuerarten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getBetreuerarten' + }; + }, + getDefaultStundensaetze(person_id, studiensemester_kurzbz) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getDefaultStundensaetze', + params: { person_id, studiensemester_kurzbz } + }; + }, + getNoten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getNoten' + }; + }, + saveProjektbetreuer(projektarbeit_id, projektbetreuerListe) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/saveProjektbetreuer', + params: { projektarbeit_id, projektbetreuerListe } + }; + }, + deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/deleteProjektbetreuer', + params: { projektarbeit_id, person_id, betreuerart_kurzbz } + }; + }, + getProjektbetreuerBySearchQuery(searchString) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuerBySearchQuery', + params: { searchString } + }; + }, + validateProjektbetreuer(projektbetreuer) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/validateProjektbetreuer', + params: { projektbetreuer } + }; + } +}; diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js deleted file mode 100644 index 5d223d694..000000000 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js +++ /dev/null @@ -1,847 +0,0 @@ -import {CoreFilterCmpt} from "../../../../filter/Filter.js"; -import FormForm from '../../../../Form/Form.js'; -import FormInput from '../../../../Form/Input.js'; -import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; - -import ApiStvAbschlusspruefung from '../../../../../api/factory/stv/abschlusspruefung.js'; - -export default { - components: { - CoreFilterCmpt, - BsModal, - FormForm, - FormInput, - PvAutoComplete, - AbschlusspruefungDropdown, - PruefungList - }, - inject: { - cisRoot: { - from: 'cisRoot' - }, - config: { - from: 'config', - required: true - }, - $reloadList: { - from: '$reloadList', - required: true - }, - isBerechtigtDocAndOdt: { - from: 'hasPermissionOutputformat', - default: false - } - }, - computed: { - studentUids() { - if (this.student.uid) - { - return [this.student.uid]; - } - return this.student.map(e => e.uid); - }, - studentKzs(){ - if (this.student.uid) - { - return [this.student.studiengang_kz]; - } - return this.student.map(e => e.studiengang_kz); - }, - stg_kz(){ - return this.studentKzs[0]; - }, - }, - props: { - student: Object - }, - data() { - return { - tabulatorOptions: { - ajaxURL: 'dummy', - ajaxRequestFunc: () => this.$api.call(ApiStvAbschlusspruefung.getAbschlusspruefung(this.student.uid)), - ajaxResponse: (url, params, response) => response.data, - columns: [ - {title: "vorsitz", field: "vorsitz_nachname"}, - {title: "abschlussbeurteilung", field: "beurteilung_bezeichnung"}, - {title: "prueferIn1", field: "p1_nachname", visible: false}, - {title: "prueferIn2", field: "p2_nachname", visible: false}, - {title: "prueferIn3", field: "p3_nachname", visible: false}, - { - title: "datum", - field: "datum", - formatter: function (cell) { - const dateStr = cell.getValue(); - if (!dateStr) return ""; - - const date = new Date(dateStr); - return date.toLocaleString("de-DE", { - day: "2-digit", - month: "2-digit", - year: "numeric", - hour12: false - }); - } - }, - {title: "uhrzeit", field: "uhrzeit"}, - { - title: "freigabe", - field: "freigabedatum", - formatter: function (cell) { - const dateStr = cell.getValue(); - if (!dateStr) return ""; - - const date = new Date(dateStr); - return date.toLocaleString("de-DE", { - day: "2-digit", - month: "2-digit", - year: "numeric", - hour12: false - }); - } - }, - {title: "pruefungsantritt", field: "antritt_bezeichnung"}, - { - title: "sponsion", - field: "sponsion", - formatter: function (cell) { - const dateStr = cell.getValue(); - if (!dateStr) return ""; - - const date = new Date(dateStr); - return date.toLocaleString("de-DE", { - day: "2-digit", - month: "2-digit", - year: "numeric", - hour12: false - }); - } - }, - {title: "anmerkung", field: "anmerkung"}, - {title: "abschlusspruefung_id", field: "abschlusspruefung_id", visible: false}, - {title: "typ", field: "pruefungstyp_kurzbz", visible: false}, - - { - title: 'Aktionen', field: 'actions', - minWidth: 150, // Ensures Action-buttons will be always fully displayed - formatter: (cell, formatterParams, onRendered) => { - let container = document.createElement('div'); - container.className = "d-flex gap-2"; - - let button = document.createElement('button'); - button.className = 'btn btn-outline-secondary btn-action'; - button.innerHTML = ''; - button.title = this.$p.t('ui', 'bearbeiten'); - button.addEventListener('click', (event) => - this.actionEditAbschlusspruefung(cell.getData().abschlusspruefung_id) - ); - container.append(button); - - button = document.createElement('button'); - button.className = 'btn btn-outline-secondary btn-action'; - button.innerHTML = ''; - button.title = this.$p.t('ui', 'loeschen'); - button.addEventListener('click', () => - this.actionDeleteAbschlusspruefung(cell.getData().abschlusspruefung_id) - ); - container.append(button); - - container.append(cell.getData().actionDiv); - - return container; - }, - frozen: true - }, - ], - layout: 'fitDataFill', - layoutColumnsOnNewData: false, - height: 'auto', - minHeight: '200', - selectable: true, - index: 'abschlusspruefung_id', - persistenceID: 'stv-details-finalexam' - }, - tabulatorEvents: [ - { - event: 'dataLoaded', - handler: data => this.tabulatorData = data.map(item => { - item.actionDiv = document.createElement('div'); - return item; - }), - }, - { - event: 'tableBuilt', - handler: async() => { - await this.$p.loadCategory(['global', 'person', 'stv', 'abschlusspruefung', 'ui']); - - - let cm = this.$refs.table.tabulator.columnManager; - - cm.getColumnByField('vorsitz_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'vorsitz_header') - }); - cm.getColumnByField('beurteilung_bezeichnung').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'abschlussbeurteilung') - }); - cm.getColumnByField('p1_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefer1') - }); - cm.getColumnByField('p2_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefer2') - }); - cm.getColumnByField('p3_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefer3') - }); - cm.getColumnByField('datum').component.updateDefinition({ - title: this.$p.t('global', 'datum') - }); - cm.getColumnByField('uhrzeit').component.updateDefinition({ - title: this.$p.t('global', 'uhrzeit') - }); - cm.getColumnByField('freigabedatum').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'freigabe') - }); - cm.getColumnByField('antritt_bezeichnung').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefungsantritt') - }); - cm.getColumnByField('sponsion').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'sponsion') - }); - cm.getColumnByField('anmerkung').component.updateDefinition({ - title: this.$p.t('global', 'anmerkung') - }); - cm.getColumnByField('pruefungstyp_kurzbz').component.updateDefinition({ - title: this.$p.t('global', 'typ') - }); - cm.getColumnByField('abschlusspruefung_id').component.updateDefinition({ - title: this.$p.t('ui', 'abschlusspruefung_id') - }); - /* - cm.getColumnByField('actions').component.updateDefinition({ - title: this.$p.t('global', 'aktionen') - }); - */ - } - } - ], - tabulatorData: [], - lastSelected: null, - formData: { - typStg: null, - pruefungstyp_kurzbz: null, - akadgrad_id: null, - vorsitz: null, - pruefungsantritt_kurzbz: null, - abschlussbeurteilung_kurzbz: null, - datum: null, - sponsion: null, - pruefer1: null, - pruefer2: null, - pruefer3: null, - anmerkung: null, - protokoll: null, - note: null, - link: null - }, - statusNew: true, - arrTypen: [], - arrAntritte: [], - arrBeurteilungen: [], - arrAkadGrad: [], - arrNoten: [], - filteredMitarbeiter: [], - filteredPruefer: [], - abortController: { - mitarbeiter: null, - pruefer: null - }, - stgInfo: { typ: '', oe_kurzbz: '' } - } - }, - watch: { - student(){ - if (this.$refs.table) { - this.$refs.table.reloadTable(); - } - this.getStudiengangByKz(); - } - }, - methods: { - getStudiengangByKz(){ - this.stgInfo = { typ: '', oe_kurzbz: '' }; - this.$api - .call(ApiStudiengang.getStudiengangByKz(this.stg_kz)) - .then(result => this.stgInfo = result.data) - .catch(this.$fhcAlert.handleSystemError); - }, - actionNewAbschlusspruefung() { - this.resetForm(); - this.statusNew = true; - this.$refs.finalexamModal.show(); - this.setDefaultFormData(); - }, - actionEditAbschlusspruefung(abschlusspruefung_id) { - this.resetForm(); - this.statusNew = false; - this.$refs.finalexamModal.show(); - this.loadAbschlusspruefung(abschlusspruefung_id); - }, - actionDeleteAbschlusspruefung(abschlusspruefung_id) { - this.$fhcAlert - .confirmDelete() - .then(result => result - ? abschlusspruefung_id - : Promise.reject({handled: true})) - .then(this.deleteAbschlusspruefung) - .catch(this.$fhcAlert.handleSystemError); - }, - addNewAbschlusspruefung() { - const dataToSend = { - uid: this.student.uid, - formData: this.formData - }; - - return this.$refs.formFinalExam - .call(ApiStvAbschlusspruefung.addNewAbschlusspruefung(dataToSend)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); - this.hideModal('finalexamModal'); - this.resetForm(); - }) - .catch(this.$fhcAlert.handleSystemError) - .finally(() => { - this.reload(); - }); - }, - hideModal(modalRef){ - this.$refs[modalRef].hide(); - }, - reload() { - this.$refs.table.reloadTable(); - }, - loadAbschlusspruefung(abschlusspruefung_id) { - return this.$api - .call(ApiStvAbschlusspruefung.loadAbschlusspruefung(abschlusspruefung_id)) - .then(result => { - this.formData = result.data; - //TODO(Manu) check if cisRoot is okay - this.formData.link = this.cisRoot + 'index.ci.php/lehre/Pruefungsprotokoll/showProtokoll?abschlusspruefung_id=' + this.formData.abschlusspruefung_id + '&fhc_controller_id=67481e5ed5490'; - return result; - }) - .catch(this.$fhcAlert.handleSystemError); - }, - updateAbschlusspruefung(abschlusspruefung_id) { - const dataToSend = { - id: abschlusspruefung_id, - formData: this.formData - }; - return this.$refs.formFinalExam - .call(ApiStvAbschlusspruefung.updateAbschlusspruefung(dataToSend)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); - this.hideModal('finalexamModal'); - this.resetForm(); - }) - .catch(this.$fhcAlert.handleSystemError) - .finally(() => { - this.reload(); - }); - }, - deleteAbschlusspruefung(abschlusspruefung_id) { - return this.$api - .call(ApiStvAbschlusspruefung.deleteAbschlusspruefung(abschlusspruefung_id)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); - }) - .catch(this.$fhcAlert.handleSystemError) - .finally(() => { - this.reload(); - }); - }, - resetForm() { - this.formData.pruefungstyp_kurzbz = null; - this.formData.akadgrad_id = null; - this.formData.vorsitz = null; - this.formData.pruefungsantritt_kurzbz = null; - this.formData.abschlussbeurteilung_kurzbz = null; - this.formData.datum = null; //oder new Date(); - this.formData.sponsion = null; - this.formData.pruefer1 = null; - this.formData.pruefer2 = null; - this.formData.pruefer3 = null; - this.formData.anmerkung = null; - this.formData.protokoll = null; - this.formData.note = null; - this.formData.p1 = null; - this.formData.p2 = null; - this.formData.p3 = null; - this.formData.pv = null; - }, - search(event) { - if (this.abortController.mitarbeiter) { - this.abortController.mitarbeiter.abort(); - } - this.abortController.mitarbeiter = new AbortController(); - - return this.$api - .call(ApiStvAbschlusspruefung.getMitarbeiter(event.query)) - .then(result => { - this.filteredMitarbeiter = result.data.retval; - }); - }, - searchNotAkad(event) { - if (this.abortController.pruefer) { - this.abortController.pruefer.abort(); - } - this.abortController.pruefer = new AbortController(); - - return this.$api - .call(ApiStvAbschlusspruefung.getPruefer(event.query)) - .then(result => { - this.filteredPruefer = result.data.retval; - }); - }, - setDefaultFormData() { - - this.resetForm(); - - if (this.stgInfo.typ === 'b') { - this.formData.pruefungstyp_kurzbz = 'Bachelor'; - this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); - } - if (this.stgInfo.typ === 'd' || this.stgInfo === 'm') { - this.formData.pruefungstyp_kurzbz = 'Diplom'; - this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); - } - if (this.stgInfo.typ === 'lg') { - this.formData.pruefungstyp_kurzbz = 'lgabschluss'; - } - - if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) { - this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id; - } - }, - printDocument(link) { - window.open(link, '_blank'); - }, - }, - created() { - this.$api - .call(ApiStvAbschlusspruefung.getTypenAbschlusspruefung()) - .then(result => { - this.arrTypen = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getTypenAntritte()) - .then(result => { - this.arrAntritte = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getBeurteilungen()) - .then(result => { - this.arrBeurteilungen = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getNoten()) - .then(result => { - this.arrNoten = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getAkadGrade(this.student.studiengang_kz)) - .then(result => { - this.arrAkadGrad = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - if (!this.student.length) { - this.$api - .call(ApiStudiengang.getStudiengangByKz(this.student.studiengang_kz)) - .then(result => { - this.stgInfo = result.data; - this.setDefaultFormData(); - }) - .catch(this.$fhcAlert.handleSystemError); - } else - this.getStudiengangByKz(); - }, - template: ` -
-

{{this.$p.t('stv','tab_finalexam')}}

- -
- -
- - - - - - - - - - - - - {{this.$p.t('global','details')}} -

[{{$p.t('ui', 'neu')}}]

-
- - - - - - - -
- -
- - - - -
- -
- - - - - -
- -
- - - - - - - -
- -
- - - - - -
- -
- - - - -
- -
- - - - -
- -
-
-

{{$p.t('abschlusspruefung', 'zurBeurteilung')}}

-
- -
- -
- - - -
- - - - -
-` -} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js index a6256ceb1..7f98948d4 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -1,4 +1,3 @@ -import {CoreFilterCmpt} from "../../../../filter/Filter.js"; import FormForm from '../../../../Form/Form.js'; import FormInput from '../../../../Form/Input.js'; import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; @@ -7,7 +6,6 @@ import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js export default { components: { - CoreFilterCmpt, FormForm, FormInput, PvAutoComplete @@ -48,23 +46,12 @@ export default { } return lehreinheiten; - }, - //~ preparedFormData() { - //~ console.log("FOR DATA CALLEd"); - //~ if (this.formData.projektarbeit_id == null) delete(this.formData.projektarbeit_id); - //~ if (this.formData.firma) this.formData.firma_id = this.formData.firma.firma_id; - //~ delete(this.formData.firma); - //~ delete(this.formData.firma_name); - //~ delete(this.formData.lehrveranstaltung_id); - //~ // convert null value fields from string to null - //~ return this.formData; - //~ } + } }, props: { statusNew: Boolean, student: Object, - projektarbeit: Object, - stg_kz: Number + projektarbeit: Object }, data() { return { @@ -177,21 +164,13 @@ export default { }) .catch(this.$fhcAlert.handleSystemError); }, - setFormData(arrTypen, arrLvs, arrNoten, projektarbeitData) { - this.arrTypen = arrTypen; - this.arrLvs = arrLvs; - this.arrNoten = arrNoten; - if (projektarbeitData) { - projektarbeitData.firma = {firma_id: projektarbeitData.firma_id, name: projektarbeitData.firma_name}; - this.formData = projektarbeitData; - } - }, loadProjektarbeit(projektarbeit_id) { return this.$api .call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id)) .then(result => { this.formData = result.data; + if (this.formData.firma_id) this.formData.firma = {firma_id: this.formData.firma_id, name: this.formData.firma_name}; return result; }) .catch(this.$fhcAlert.handleSystemError) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js index 034b3fd6c..15c9aeeee 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -7,6 +7,7 @@ import PvAutoComplete from "../../../../../../../index.ci.php/public/js/componen import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js'; import ProjektarbeitDetails from "./Details.js"; +import Projektbetreuer from "./Projektbetreuer.js"; export default { components: { @@ -15,7 +16,8 @@ export default { FormForm, FormInput, PvAutoComplete, - ProjektarbeitDetails + ProjektarbeitDetails, + Projektbetreuer }, inject: { cisRoot: { @@ -174,7 +176,9 @@ export default { button.title = this.$p.t('ui', 'bearbeiten'); button.addEventListener('click', (event) => { let data = cell.getData(); - this.actionEditProjektarbeit(data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id); + this.actionEditProjektarbeit( + data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id, data.projekttyp_kurzbz + ); }); container.append(button); @@ -195,7 +199,6 @@ export default { }, ], layout: 'fitDataFill', - layoutColumnsOnNewData: false, height: 'auto', minHeight: '200', selectable: 1, @@ -240,25 +243,20 @@ export default { lehrveranstaltung_id: null } }, - //~ watch: { - //~ student(){ - //~ if (this.$refs.table) { - //~ this.$refs.table.reloadTable(); - //~ } - //~ this.getStudiengangByKz(); - //~ } - //~ }, methods: { actionNewProjektarbeit() { this.statusNew = true; this.$refs.projektarbeitDetails.resetForm(); this.$refs.projektarbeitDetails.getFormData(); + this.$refs.projektbetreuer.getData(); this.$refs.projektarbeitModal.show(); }, - actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id) { + actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id, projekttyp_kurzbz) { this.statusNew = false; this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id); + // TODO: maybe preload projektarbeit? not just on edit? this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id); + this.$refs.projektbetreuer.getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz); this.$refs.projektarbeitModal.show(); }, actionDeleteProjektarbeit(projektarbeit_id) { @@ -271,41 +269,41 @@ export default { .catch(this.$fhcAlert.handleSystemError); }, addNewProjektarbeit() { - Promise.allSettled([ - this.$refs.projektarbeitDetails.addNewProjektarbeit() - ]).then((results) => { - let hasError = false; - results.forEach((promise_result) => { + this.$refs.projektbetreuer.validateProjektbetreuer() + .then(() => { + return this.$refs.projektarbeitDetails.addNewProjektarbeit(); + }) + .then((result) => { + const projektarbeit_id = result.data; + console.log(projektarbeit_id); - if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) { - - hasError = true; + if (!isNaN(projektarbeit_id)) { + return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id); } - }); - - if (!hasError) { + }) + .then((result) => { + console.log(result); this.projektarbeitSaved(); - } - }); + }) + .catch(this.$fhcAlert.handleSystemError); }, updateProjektarbeit() { - Promise.allSettled( - [ - this.$refs.projektarbeitDetails.updateProjektarbeit() - ]).then((results) => { - let hasError = false; - results.forEach((promise_result) => { + this.$refs.projektbetreuer.validateProjektbetreuer() + .then(() => { + return this.$refs.projektarbeitDetails.updateProjektarbeit(); + }) + .then((result) => { + const projektarbeit_id = result.data; + console.log(projektarbeit_id); - if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) { - - hasError = true; + if (!isNaN(projektarbeit_id)) { + return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id); } - }); - - if (!hasError) { + }) + .then((result) => { this.projektarbeitSaved(); - } - }); + }) + .catch(this.$fhcAlert.handleSystemError); }, deleteProjektarbeit(projektarbeit_id) { return this.$api @@ -325,7 +323,6 @@ export default { this.$refs.projektarbeitDetails.resetForm(); }, rowSelectionChanged(data) { - console.log("selection changed"); this.lastSelected = data.length > 0 ? data[0] : null; }, hideModal(modalRef){ @@ -362,7 +359,14 @@ export default {

{{$p.t('projektarbeit', 'projektarbeitBearbeiten')}}

- +
+
+ +
+
+ +
+
` -}; \ No newline at end of file +}; diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index a4381b00d..433a52d3e 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -41789,7 +41789,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Title', + 'text' => 'title', 'description' => '', 'insertvon' => 'system' ) @@ -41809,7 +41809,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Title English', + 'text' => 'title English', 'description' => '', 'insertvon' => 'system' ) @@ -41829,7 +41829,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Topic area', + 'text' => 'topic area', 'description' => '', 'insertvon' => 'system' ) @@ -41849,7 +41849,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Type', + 'text' => 'type', 'description' => '', 'insertvon' => 'system' ) @@ -41869,7 +41869,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Company', + 'text' => 'company', 'description' => '', 'insertvon' => 'system' ) @@ -41889,7 +41889,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Course', + 'text' => 'course', 'description' => '', 'insertvon' => 'system' ) @@ -41909,7 +41909,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Teaching unit', + 'text' => 'teaching unit', 'description' => '', 'insertvon' => 'system' ) @@ -41920,6 +41920,26 @@ and represent the current state of research on the topic. The prescribed citatio 'category' => 'projektarbeit', 'phrase' => 'betreuer', 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Betreuer', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'assessor', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerGross', + 'insertvon' => 'system', 'phrases' => array( array( 'sprache' => 'German', @@ -41935,6 +41955,26 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerart', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Betreuerart', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'assessor type', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'projektarbeit', @@ -41949,7 +41989,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Grade', + 'text' => 'grade', 'description' => '', 'insertvon' => 'system' ) @@ -41969,7 +42009,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Hours', + 'text' => 'hours', 'description' => '', 'insertvon' => 'system' ) @@ -41989,7 +42029,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Hourly rate', + 'text' => 'hourly rate', 'description' => '', 'insertvon' => 'system' ) @@ -42029,7 +42069,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Start', + 'text' => 'start', 'description' => '', 'insertvon' => 'system' ) @@ -42049,7 +42089,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'End', + 'text' => 'end', 'description' => '', 'insertvon' => 'system' ) @@ -42089,7 +42129,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Locked until', + 'text' => 'locked until', 'description' => '', 'insertvon' => 'system' ) @@ -42109,7 +42149,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Annotation', + 'text' => 'annotation', 'description' => '', 'insertvon' => 'system' ) @@ -42129,7 +42169,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Company Id', + 'text' => 'company Id', 'description' => '', 'insertvon' => 'system' ) @@ -42215,6 +42255,326 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'neuePersonAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Neue Person anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create new person', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'titelPre', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel (Pre)', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title (Pre)', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'titelPost', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel (Post)', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title (Post)', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'weitereVornamen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Weitere Vornamen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'other first names', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'bestehendeAdresseUeberschreiben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bestehende Adresse überschreiben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Replace existing address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'adresseHinzufuegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Adresse hinzufügen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Add new address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'adresseNichtAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Adresse nicht anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Do not create address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'land', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Land', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'nation', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'mobil', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Mobil', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'mobile phone', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'letzeAusbildung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Letzte Ausbildung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'most recent education', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'ausbildungsart', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ausbildungsart', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'education type', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'anmerkungen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Anmerkungen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'notes', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'personAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Person anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create person', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'interessentAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'InteressentIn anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create candidate', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'personExistiertPruefung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfung ob Person bereits existiert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Check if a person already exists', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'ui', + 'phrase' => 'zurueck', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Zurück', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Back', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From 750b956dd22ce736fe8341312ec141dad0265cad Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 2 Jun 2025 15:28:10 +0200 Subject: [PATCH 020/388] Studentenverwaltung Projektarbeit: added button for editing contact data --- .../Details/Projektarbeit/Projektbetreuer.js | 31 +++++++++++++++++-- system/phrasesupdate.php | 20 ++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 079b8b796..4f3095cab 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -1,18 +1,22 @@ import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import BsModal from "../../../../Bootstrap/Modal.js"; import FormForm from '../../../../Form/Form.js'; import FormInput from '../../../../Form/Input.js'; import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; import NewPerson from "../../List/New.js"; +import Contact from "../Kontakt/Contact.js"; import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js'; export default { components: { CoreFilterCmpt, + BsModal, FormForm, FormInput, PvAutoComplete, - NewPerson + NewPerson, + Contact }, inject: { }, @@ -340,6 +344,10 @@ export default { this.$refs.newPersonModal.reset(); this.$refs.newPersonModal.open(); }, + actionKontaktdatenBearbeiten() { + if (!this.autocompleteSelectedBetreuer) return; + this.$refs.kontaktdatenModal.show(); + }, personSaved(result) { this.$api .call(ApiStvProjektbetreuer.getPerson(result.person_id)) @@ -384,9 +392,12 @@ export default {
-
+
+
+ +
@@ -455,6 +466,22 @@ export default { + + + + + + +
+
+ + +
+
+ +
` } diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 433a52d3e..d467252d7 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42575,6 +42575,26 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'kontaktdatenBearbeiten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Kontaktdaten bearbeiten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Edit contact data', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ) ); From fe81e7fb7c5bb528f911d315bd64c28c894fb0e6 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 3 Jun 2025 21:18:03 +0200 Subject: [PATCH 021/388] Studierendenverwaltung Projektarbeit: added button for Projektarbeit download --- .../api/frontend/v1/stv/Projektbetreuer.php | 26 +- .../Details/Projektarbeit/Projektbetreuer.js | 251 ++++++++++-------- system/phrasesupdate.php | 20 ++ 3 files changed, 171 insertions(+), 126 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php index 34f626eca..7a1b803b9 100644 --- a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -3,6 +3,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); use \DateTime as DateTime; +use CI3_Events as Events; class Projektbetreuer extends FHCAPI_Controller { @@ -85,6 +86,21 @@ class Projektbetreuer extends FHCAPI_Controller //~ } //~ } + foreach ($projektbetreuer as $pb) + { + $downloadLink = null; + Events::trigger( + 'projektbeurteilung_download_link', + $pb->projektarbeit_id, + $pb->betreuerart_kurzbz, + $pb->person_id, + function ($value) use (&$downloadLink) { + $downloadLink = $value; + } + ); + $pb->projektarbeitDownload = $downloadLink; + } + $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); } @@ -105,11 +121,7 @@ class Projektbetreuer extends FHCAPI_Controller foreach ($projektbetreuer as $pb) { - if ($this->_validate($pb) == false) - { - $this->addMeta('test', 'foisch'); - $this->terminateWithValidationErrors($this->form_validation->error_array()); - } + if ($this->_validate($pb) == false) $this->terminateWithValidationErrors($this->form_validation->error_array()); } $result = null; @@ -210,10 +222,6 @@ class Projektbetreuer extends FHCAPI_Controller $result = $this->StundensatzModel->getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz); - $this->addMeta('res', $result); - - //if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - return $this->terminateWithSuccess($result); } diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 4f3095cab..bf459ebc5 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -113,6 +113,7 @@ export default { arrNoten: [], filteredBetreuer: [], autocompleteSelectedBetreuer: null, + projektarbeitDownload: null, abortController: { betreuer: null } @@ -146,6 +147,7 @@ export default { if (idx >= 0) { betreuer = projektbetreuerListe[idx]; this.formData = betreuer; + if (betreuer.projektarbeitDownload) this.projektarbeitDownload = betreuer.projektarbeitDownload this.autocompleteSelectedBetreuer = { person_id: this.formData.person_id, name: this.formData.name, @@ -268,6 +270,7 @@ export default { }, resetForm() { this.formData = this.getDefaultFormData(); + this.projektarbeitDownload = null; this.autocompleteSelectedBetreuer = null; this.initialFormData = null; if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz); @@ -358,130 +361,144 @@ export default { } }, template: ` -
+
- {{this.$p.t('projektarbeit','betreuerGross')}} - +
- - + {{this.$p.t('projektarbeit','betreuerGross')}} + - -
- - -
+ + -
-
- -
-
- -
-
- -
- -
+ + +
+ + + + + + + + + +
+
+ + +
+
+ +
` } diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index d467252d7..d10f915cc 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42594,6 +42594,26 @@ and represent the current state of research on the topic. The prescribed citatio 'insertvon' => 'system' ) ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'projektbeurteilungErstellen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektbeurteilung erstellen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create project assessment document', + 'description' => '', + 'insertvon' => 'system' + ) + ) ) ); From e26bce2cf7d21d78e59c09ba16c46097c6d4ef0b Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 10 Jun 2025 14:14:32 +0200 Subject: [PATCH 022/388] removed merge text from code --- application/models/ressource/Stundensatz_model.php | 1 - 1 file changed, 1 deletion(-) diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index 553bdd20b..c8ee367d8 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -150,4 +150,3 @@ class Stundensatz_model extends DB_Model return $default_stundensatz; } } -==== BASE ==== From d15d27b3e14dbbf179fa85e4167b71c09c49c5f0 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 13 Jun 2025 16:19:53 +0200 Subject: [PATCH 023/388] =?UTF-8?q?Studierendenverwaltung=20Projektarbeit:?= =?UTF-8?q?=20added=20Vertr=C3=A4ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/frontend/v1/stv/Config.php | 6 +- .../api/frontend/v1/stv/Projektbetreuer.php | 2 +- .../api/frontend/v1/stv/Vertrag.php | 104 +++++++++++ .../models/accounting/Vertrag_model.php | 20 +++ public/js/api/factory/stv/vertrag.js | 20 +++ .../Details/Projektarbeit/Details.js | 6 +- .../Details/Projektarbeit/Projektarbeit.js | 24 --- .../Details/Projektarbeit/Projektbetreuer.js | 103 +++++++---- .../Details/Projektarbeit/Vertrag.js | 168 ++++++++++++++++++ system/phrasesupdate.php | 68 ++++++- 10 files changed, 457 insertions(+), 64 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/Vertrag.php create mode 100644 public/js/api/factory/stv/vertrag.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 98a06ffb5..83173375e 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -127,7 +127,11 @@ class Config extends FHCAPI_Controller $result['projektarbeit'] = [ 'title' => $this->p->t('stv', 'tab_projektarbeit'), 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js', - 'config' => $config['projektarbeit'] + 'config' => array_merge( + $config['projektarbeit'], + ['showVertragsdetails' => + defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN') && FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN] + ) ]; $result['mobility'] = [ diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php index 7a1b803b9..af0a11d0f 100644 --- a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -98,7 +98,7 @@ class Projektbetreuer extends FHCAPI_Controller $downloadLink = $value; } ); - $pb->projektarbeitDownload = $downloadLink; + $pb->beurteilungDownloadLink = $downloadLink; } $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); diff --git a/application/controllers/api/frontend/v1/stv/Vertrag.php b/application/controllers/api/frontend/v1/stv/Vertrag.php new file mode 100644 index 000000000..f94fe795e --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Vertrag.php @@ -0,0 +1,104 @@ + ['admin:r', 'assistenz:r'], + 'cancelVertrag' => ['admin:r', 'assistenz:r'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getVertrag() + { + $vertrag_id = $this->input->get('vertrag_id'); + + if (!isset($vertrag_id) || !is_numeric($vertrag_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL); + + $result = $this->VertragModel->getVertragById($vertrag_id); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $vertrag = getData($result)[0]; + + $this->terminateWithSuccess($vertrag); + } + + public function cancelVertrag() + { + $vertrag_id = $this->input->post('vertrag_id'); + $person_id = $this->input->post('person_id'); + + if (!isset($vertrag_id) || !is_numeric($vertrag_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL); + if (!isset($person_id) || !is_numeric($person_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL); + + // * first find lehrveranstaltung_id of the contracts lehrveranstaltung + $this->VertragModel->addSelect('lehrveranstaltung_id'); + $this->VertragModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id', 'LEFT'); + $result = $this->VertragModel->loadWhere(['vertrag_id' => $vertrag_id]); + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $lehrveranstaltung_id = getData($result)[0]->lehrveranstaltung_id; + + $allOe = $this->LehrveranstaltungModel->getAllOe($lehrveranstaltung_id); + + if (isError($allOe)) $this->terminateWithError(getError($allOe), self::ERROR_TYPE_GENERAL); + + $allOe = hasData($allOe) ? getData($allOe) : []; + + $this->addMeta('oe', $allOe); + + // * then check if the user has permissions to cancel the corresponding lv-organisational units + if (!$this->permissionlib->isBerechtigtMultipleOe('admin', $allOe, 'suid') && + !$this->permissionlib->isBerechtigtMultipleOe('lehre/lehrauftrag_bestellen', $allOe, 'suid')) + { + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'lehrauftrag_bestellen:rw']]); + } + + $uidResult = $this->BenutzerModel->getFromPersonId($person_id); + + if (isError($uidResult)) $this->terminateWithError(getError($uidResult), self::ERROR_TYPE_GENERAL); + + if (!hasData($uidResult)) $this->terminateWithError("no user found", self::ERROR_TYPE_GENERAL); + + $mitarbeiter_uid = getData($uidResult)[0]->uid; + + $result = $this->VertragModel->cancelVertrag($vertrag_id, $mitarbeiter_uid); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/models/accounting/Vertrag_model.php b/application/models/accounting/Vertrag_model.php index c17c676c7..4c036369b 100644 --- a/application/models/accounting/Vertrag_model.php +++ b/application/models/accounting/Vertrag_model.php @@ -402,6 +402,26 @@ class Vertrag_model extends DB_Model return $this->loadWhere(array('mitarbeiter_uid' => $mitarbeiter_uid, 'lehreinheit_id' => $lehreinheit_id)); } + public function getVertragById($vertrag_id) + { + $this->addSelect( + 'tbl_vertrag.vertrag_id, vertragstyp_kurzbz, vertragsstunden, vertragsstunden_studiensemester_kurzbz, status.vertragsstatus_kurzbz, + status.bezeichnung AS vertragsstatus, tbl_vertrag.betrag, lema.semesterstunden, lema.stundensatz' + ); + $this->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_vertrag.vertrag_id = lema.vertrag_id', 'LEFT'); + $this->addJoin(' + ( + SELECT DISTINCT ON(vst.vertrag_id) vst.vertrag_id, + bezeichnung, + tbl_vertragsstatus.vertragsstatus_kurzbz + FROM lehre.tbl_vertrag_vertragsstatus vst + JOIN lehre.tbl_vertragsstatus USING(vertragsstatus_kurzbz) + ORDER BY vst.vertrag_id, datum DESC + ) as status', 'status.vertrag_id = lehre.tbl_vertrag.vertrag_id', 'LEFT'); + + return $this->loadWhere(['tbl_vertrag.vertrag_id' => $vertrag_id]); + } + public function cancelVertrag($vertrag_id, $mitarbeiter_uid) { $vertrag = $this->load($vertrag_id); diff --git a/public/js/api/factory/stv/vertrag.js b/public/js/api/factory/stv/vertrag.js new file mode 100644 index 000000000..9070936da --- /dev/null +++ b/public/js/api/factory/stv/vertrag.js @@ -0,0 +1,20 @@ +export default { + + getVertrag(vertrag_id) + { + return { + method: 'get', + url: 'api/frontend/v1/stv/vertrag/getVertrag', + params: { vertrag_id }, + }; + }, + + cancelVertrag(data) + { + return { + method: 'post', + url: '/api/frontend/v1/stv/vertrag/cancelVertrag/', + params: data + }; + } +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js index 4f833621d..c2269c1b3 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -15,15 +15,13 @@ export default { defaultSemester: { from: 'defaultSemester' } - //~ cisRoot: { - //~ from: 'cisRoot' - //~ }, //~ config: { //~ from: 'config', //~ required: true //~ } }, computed: { + // prepared Lehreinheiten (with compound Bezeichnung) arrLes() { let lehreinheiten = []; if (this.formData.lehrveranstaltung_id) { @@ -133,7 +131,6 @@ export default { //~ //this.$fhcAlert.handleSystemError(promise_result); //~ } //~ //let data = promise_result.value.data; - //~ console.log(promise_result.status); //~ }); //~ if (!hasError) { @@ -214,6 +211,7 @@ export default { lvChanged(event) { this.formData.lehreinheit_id = null; }, + // enrich and modify data before sending getPreparedFormData() { let preparedFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js index 8314db8b3..3f9958a26 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -30,29 +30,6 @@ export default { from: '$reloadList', required: true } - //~ isBerechtigtDocAndOdt: { - //~ from: 'hasPermissionOutputformat', - //~ default: false - //~ } - }, - computed: { - //~ studentUids() { - //~ if (this.student.uid) - //~ { - //~ return [this.student.uid]; - //~ } - //~ return this.student.map(e => e.uid); - //~ }, - //~ studentKzs(){ - //~ if (this.student.uid) - //~ { - //~ return [this.student.studiengang_kz]; - //~ } - //~ return this.student.map(e => e.studiengang_kz); - //~ }, - //~ stg_kz(){ - //~ return this.studentKzs.length > 0 ? this.studentKzs.length[0] : null; - //~ } }, props: { student: Object @@ -271,7 +248,6 @@ export default { actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id, projekttyp_kurzbz) { this.statusNew = false; this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id); - // TODO: maybe preload projektarbeit? not just on edit? this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id); this.$refs.projektbetreuer.getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz); this.$refs.projektarbeitModal.show(); diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index bf459ebc5..8368534c7 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -5,6 +5,7 @@ import FormInput from '../../../../Form/Input.js'; import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; import NewPerson from "../../List/New.js"; import Contact from "../Kontakt/Contact.js"; +import Vertrag from "./Vertrag.js"; import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js'; @@ -16,9 +17,13 @@ export default { FormInput, PvAutoComplete, NewPerson, - Contact + Contact, + Vertrag }, - inject: { + provide() { + return { + configShowVertragsdetails: this.config.showVertragsdetails + } }, computed: { betreuerFormOpened() { @@ -107,13 +112,13 @@ export default { initialFormData: null, defaultFormDataValues: {stunden: null, stundensatz: null}, projektarbeit_id: null, - statusNew: true, editedBetreuerIdx: -1, arrBetreuerart: [], arrNoten: [], filteredBetreuer: [], autocompleteSelectedBetreuer: null, - projektarbeitDownload: null, + beurteilungDownloadLink: null, + vertragFieldsDisabled: false, abortController: { betreuer: null } @@ -122,19 +127,19 @@ export default { methods: { actionNewProjektbetreuer() { this.resetForm(); - this.statusNew = true; this.newMode = !this.newMode; this.editMode = false; this.captureFormData(); }, actionEditProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { - - this.statusNew = false; this.editMode = true; + this.newMode = false; this.$api .call(ApiStvProjektbetreuer.getDefaultStundensaetze(person_id, this.studiensemester_kurzbz)) .then(result => { this.resetForm(); + + // get betreuer from tabulator list let projektbetreuerListe = this.$refs.projektbetreuerTable.tabulator.getData(); const idx = projektbetreuerListe.findIndex( betr => @@ -144,18 +149,29 @@ export default { ); let betreuer = []; - if (idx >= 0) { + if (idx >= 0) { // if betreuer found betreuer = projektbetreuerListe[idx]; + + // set currently edited betreuera this.formData = betreuer; - if (betreuer.projektarbeitDownload) this.projektarbeitDownload = betreuer.projektarbeitDownload + + // set download link + if (betreuer.beurteilungDownloadLink) this.beurteilungDownloadLink = betreuer.beurteilungDownloadLink + + // set betreuer for autocomplete field this.autocompleteSelectedBetreuer = { person_id: this.formData.person_id, name: this.formData.name, vorname: this.formData.vorname, - nachname: this.formData.nachname + nachname: this.formData.nachname, + vertrag_id: this.formData.vertrag_id }; } + + // set default stundensatz (if no other is set yet) if (this.formData.stundensatz == null) this.formData.stundensatz = result.data; + + // capture initial form data for detecting changes this.captureFormData(); }) .catch(this.$fhcAlert.handleSystemError); @@ -167,10 +183,12 @@ export default { ? {projektarbeit_id, person_id, betreuerart_kurzbz} : Promise.reject({handled: true})) .then(result => { - return this.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) + return this.$api + .call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz)) }) .then(result => { this.$refs.projektbetreuerTable.tabulator.deleteRow(betreuer_id); + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); }) .catch(this.$fhcAlert.handleSystemError); }, @@ -178,9 +196,12 @@ export default { this.studiensemester_kurzbz = studiensemester_kurzbz; + // default Stundensätze from config this.defaultFormDataValues.stunden = this.getDefaultStunden(projekttyp_kurzbz); this.defaultFormDataValues.stundensatz = this.config.defaultProjektbetreuerStundensatz; + this.resetModes(); + // get other initial data this.$api .call(ApiStvProjektbetreuer.getBetreuerarten()) .then(result => { @@ -209,6 +230,7 @@ export default { this.resetForm(); } }, + // confirming Betreuer means adding/updating him in list (but not yet saving in db) confirmProjektbetreuer() { if (!this.betreuerFormOpened) return; @@ -217,11 +239,9 @@ export default { this.$refs.projektbetreuerTable.tabulator.addData(this.addAutoCompleteBetreuerToFormData(this.formData)); } else { this.$refs.projektbetreuerTable.tabulator.updateData([this.formData]); - this.statusNew = true; } - this.newMode = false; - this.editMode = false; + this.resetModes(); }, confirmProjektbetreuerAfterValidation() { //if (!this.formDataModified()) return; @@ -239,14 +259,6 @@ export default { ApiStvProjektbetreuer.saveProjektbetreuer(projektarbeit_id, this.$refs.projektbetreuerTable.tabulator.getData()) ); }, - deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { - return this.$api - .call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); - }) - .catch(this.$fhcAlert.handleSystemError) - }, searchBetreuer(event) { if (this.abortController.betreuer) { this.abortController.betreuer.abort(); @@ -259,6 +271,7 @@ export default { this.filteredBetreuer = result.data; }); }, + // validate betreuer for data validateProjektbetreuer() { let alleBetreuer = this.$refs.projektbetreuerTable.tabulator.getData(); @@ -270,10 +283,15 @@ export default { }, resetForm() { this.formData = this.getDefaultFormData(); - this.projektarbeitDownload = null; + this.beurteilungDownloadLink = null; this.autocompleteSelectedBetreuer = null; this.initialFormData = null; if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz); + this.disableVertragFields(false); + }, + resetModes() { + this.newMode = false; + this.editMode = false; }, getDefaultFormData() { let formData = {betreuerart_kurzbz : null, note: null}; @@ -287,6 +305,7 @@ export default { captureFormData() { this.initialFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy }, + // add own betreuer ids to betreuer liste addIds(betreuerListe) { for (const idx in betreuerListe) { @@ -298,6 +317,7 @@ export default { } return betreuerListe; }, + // add the betreuer selected in automomplete to betreuer liste addAutoCompleteBetreuerToFormData() { let preparedFormData = this.formData; @@ -311,6 +331,7 @@ export default { return preparedFormData; }, + // get default values for stunden getDefaultStunden(projekttyp_kurzbz) { let stunden = '0.0'; if (projekttyp_kurzbz == 'Bachelor') stunden = this.config.defaultProjektbetreuerStunden; @@ -319,8 +340,10 @@ export default { }, setDefaultStunden(projekttyp_kurzbz) { this.projekttyp_kurzbz = projekttyp_kurzbz; + // if form data has not already been modified by user, set the default stunden if (!this.formDataModified()) this.formData.stunden = this.getDefaultStunden(projekttyp_kurzbz); }, + // get a new betreuer id (max + 1) getNewBetreuerId() { let max = 0; @@ -330,6 +353,7 @@ export default { return max + 1; }, + // check if form data has been modified since initial data has been captured formDataModified() { if (this.autocompleteSelectedBetreuer != null) return true; @@ -351,22 +375,27 @@ export default { if (!this.autocompleteSelectedBetreuer) return; this.$refs.kontaktdatenModal.show(); }, + // stuff to do after new person has been saved personSaved(result) { this.$api .call(ApiStvProjektbetreuer.getPerson(result.person_id)) .then(response => { + // set the new person in autocomplete field this.autocompleteSelectedBetreuer = response.data; }) .catch(this.$fhcAlert.handleSystemError) + }, + // disable fields which are dependent on Vertrag status + disableVertragFields(disabled) { + this.vertragFieldsDisabled = disabled; } }, template: `
-
+
{{this.$p.t('projektarbeit','betreuerGross')}} -
@@ -448,6 +478,7 @@ export default { type="text" name="stunden" :label="$p.t('projektarbeit', 'stunden')" + :disabled="vertragFieldsDisabled" v-model="formData.stunden" > @@ -459,6 +490,7 @@ export default { type="text" name="stundensatz" :label="$p.t('projektarbeit', 'stundensatz')" + :disabled="vertragFieldsDisabled" v-model="formData.stundensatz" > @@ -469,11 +501,23 @@ export default { - +
+ + {{ autocompleteSelectedBetreuer?.person_id && (!beurteilungDownloadLink || beurteilungDownloadLink == '') ? $p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') : ''}} +
- @@ -485,8 +529,7 @@ export default { + v-if="autocompleteSelectedBetreuer && autocompleteSelectedBetreuer.person_id">
-
+
-
+
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index fd796e3e1..9b02f9b01 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -84,13 +84,16 @@ export default { frozen: true }, ], - layout: 'fitDataFill', + //layout: 'fitDataFill', layoutColumnsOnNewData: false, height: 'auto', minHeight: '100', selectable: true, selectable: 1, index: 'betreuer_id', + persistence:{ + columns: true, //persist column layout + }, persistenceID: 'stv-details-projektbetreuer' }, tabulatorEvents: [ @@ -99,6 +102,13 @@ export default { handler: async() => { await this.$p.loadCategory(['global', 'person', 'stv', 'projektarbeit', 'ui']); } + }, + { + event: 'rowSelected', + handler: row => { + let data = row.getData(); + this.actionEditProjektbetreuer(data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz); + } } ], formData: { @@ -156,7 +166,7 @@ export default { this.formData = betreuer; // set download link - if (betreuer.beurteilungDownloadLink) this.beurteilungDownloadLink = betreuer.beurteilungDownloadLink + if (betreuer.beurteilungDownloadLink !== null) this.beurteilungDownloadLink = betreuer.beurteilungDownloadLink; // set betreuer for autocomplete field this.autocompleteSelectedBetreuer = { @@ -279,15 +289,16 @@ export default { alleBetreuer.push(this.addAutoCompleteBetreuerToFormData(this.formData)); } - return this.$api.call(ApiStvProjektbetreuer.validateProjektbetreuer(alleBetreuer)); + return this.$refs.formProjektbetreuer.call(ApiStvProjektbetreuer.validateProjektbetreuer(alleBetreuer)); }, resetForm() { this.formData = this.getDefaultFormData(); - this.beurteilungDownloadLink = null; + if (this.beurteilungDownloadLink !== null) this.beurteilungDownloadLink = ''; this.autocompleteSelectedBetreuer = null; this.initialFormData = null; if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz); this.disableVertragFields(false); + this.$refs.formProjektbetreuer.clearValidation(); }, resetModes() { this.newMode = false; @@ -417,7 +428,7 @@ export default { type="autocomplete" optionLabel="name" v-model="autocompleteSelectedBetreuer" - name="betreuer" + name="person_id" :suggestions="filteredBetreuer" @complete="searchBetreuer" :min-length="3" @@ -501,13 +512,13 @@ export default { -
+
- {{ autocompleteSelectedBetreuer?.person_id && (!beurteilungDownloadLink || beurteilungDownloadLink == '') ? $p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') : ''}} + {{ autocompleteSelectedBetreuer?.person_id && beurteilungDownloadLink === '' ? $p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') : ''}}
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js index 1f494d1ec..074d22bde 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js @@ -125,36 +125,22 @@ export default{
{{ betreuerProjektarbeit?.betreuerart_kurzbz && betreuerProjektarbeit?.vertrag_id == null ? ' – '+$p.t('lehre', 'nochKeinVertrag') : '' }}
-
- -
- {{$p.t('lehre', 'vertragurfassung')}}
- - +
+ {{ $p.t('lehre', 'vertragsstatus') }}: {{ vertragsstatus }} +
- - +
+ {{$p.t('lehre', 'vertragurfassung')}} +
+
+
+
+ {{ $p.t('lehre', 'semesterstunden') }}: {{ data.vertragsstunden }} +
+ {{ $p.t('lehre', 'studiensemester') }}: {{ data.vertragsstunden_studiensemester_kurzbz }} +
@@ -164,7 +150,7 @@ export default{ :disabled="vertragsstatus == vertragsstatus_storniert" @click="cancelVertrag" > - {{ $p.t('lehre', 'stornieren') }} + {{ $p.t('lehre', 'vertragStornieren') }}
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index db16dc247..24b37f594 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -43778,7 +43778,7 @@ and represent the current state of research on the topic. The prescribed citatio array( 'app' => 'core', 'category' => 'lehre', - 'phrase' => 'stornieren', + 'phrase' => 'vertragStornieren', 'insertvon' => 'system', 'phrases' => array( array( @@ -43789,7 +43789,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Cancel', + 'text' => 'Cancel contract', 'description' => '', 'insertvon' => 'system' ) From 5bda4db59218977c6f2fd95f841092a1eaab14d8 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Fri, 11 Jul 2025 07:33:10 +0200 Subject: [PATCH 041/388] unr beim kopieren setzen gruppen anzeige direktinskription rausgefillert datatree aufklappen bug gefixed kurzbz bei den icons statt eigene spalte --- .../api/frontend/v1/lv/Lehreinheit.php | 1 + .../education/Lehreinheitgruppe_model.php | 8 +++++- .../js/components/LVVerwaltung/Setup/Table.js | 28 ++++++++++--------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/application/controllers/api/frontend/v1/lv/Lehreinheit.php b/application/controllers/api/frontend/v1/lv/Lehreinheit.php index 0c42c0082..d58489453 100644 --- a/application/controllers/api/frontend/v1/lv/Lehreinheit.php +++ b/application/controllers/api/frontend/v1/lv/Lehreinheit.php @@ -215,6 +215,7 @@ class Lehreinheit extends FHCAPI_Controller $lehreinheit_id_new = getData($insert_result); + $this->_ci->LehreinheitModel->update(array('lehreinheit_id' => $lehreinheit_id_new), array('unr' => $lehreinheit_id_new)); if (in_array($art, array('gruppen', 'alle'))) { $gruppen_result = $this->_ci->LehreinheitgruppeModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id)); diff --git a/application/models/education/Lehreinheitgruppe_model.php b/application/models/education/Lehreinheitgruppe_model.php index 8fc8e09f3..bca395f31 100644 --- a/application/models/education/Lehreinheitgruppe_model.php +++ b/application/models/education/Lehreinheitgruppe_model.php @@ -470,6 +470,12 @@ 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)); + + $this->db->where('lehreinheit_id', $lehreinheit_id); + $this->db->group_start() + ->where('tbl_gruppe.direktinskription !=', true) + ->or_where('tbl_gruppe.direktinskription IS NULL') + ->group_end(); + return $this->load(); } } diff --git a/public/js/components/LVVerwaltung/Setup/Table.js b/public/js/components/LVVerwaltung/Setup/Table.js index 34a3b3399..a1b2830f1 100644 --- a/public/js/components/LVVerwaltung/Setup/Table.js +++ b/public/js/components/LVVerwaltung/Setup/Table.js @@ -168,7 +168,7 @@ export default { headerFilterFunc: extendedHeaderFilter, }, layout: 'fitDataStretch', - persistenceID: 'lehrveranstaltungen_2025_07_07_v1', + persistenceID: 'lehrveranstaltungen_2025_07_11_v1', selectableRowsRangeMode: 'click', selectableRows: true, rowContextMenu: (component, e) => { @@ -225,11 +225,19 @@ export default { formatter: (cell, formatterParams) => { const rowData = cell.getRow().getData(); const iconKey = (rowData.lehrtyp_kurzbz || '').toLowerCase(); + const lvkurzbz = (cell.getValue()).toUpperCase(); + const parentspan = document.createElement('span'); const span = document.createElement('span'); + + span.classList.add('lv_table_icon', `icon-${iconKey}`); span.title = iconKey || 'LV-Teil'; - return span; + + parentspan.appendChild(span); + parentspan.appendChild(document.createTextNode(` ${lvkurzbz}`)); + + return parentspan }, cellClick: (e, cell) => { @@ -300,16 +308,6 @@ 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", @@ -667,7 +665,11 @@ export default { if (level === this.currentTreeLevel - 1 ) { row._row.modules.dataTree.open = true; - lastMatchingRow = row; + + if (row._row.data._children?.length > 0) + { + lastMatchingRow = row; + } } }); From 12cdf5a83ef4c2b0e09fbefd25b32e638f8a756d Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 11 Jul 2025 17:11:19 +0200 Subject: [PATCH 042/388] =?UTF-8?q?accepting=20documents:=20enabled=20acce?= =?UTF-8?q?pting=20for=20all=20Studieng=C3=A4nge,=20not=20just=20master,?= =?UTF-8?q?=20added=20date=20and=20insertamum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/dokument.class.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/include/dokument.class.php b/include/dokument.class.php index 6dec9a66d..7b1d490fb 100644 --- a/include/dokument.class.php +++ b/include/dokument.class.php @@ -888,9 +888,10 @@ class dokument extends basis_db * Akzeptiert ein bestimmtes Dokument * @param char $dokument_kurzbz Bezeichner Dokument. * @param int $person_id Personenkennzeichen. + * @param array $studiengang_typen einschränken nach Studiengang Typ. * @return boolean true wenn akzeptiert bzw geprüft ohne Akzeptieren, false wenn Fehler */ - public function akzeptiereDokument($dokument_kurzbz, $person_id) + public function akzeptiereDokument($dokument_kurzbz, $person_id, $studiengang_typen = null) { $db = new basis_db(); $arrayDoksZuAkzeptieren = array(); @@ -902,7 +903,6 @@ class dokument extends basis_db tbl_prestudent ps, tbl_studiengang sg WHERE ps.studiengang_kz = sg.studiengang_kz - AND sg.typ = 'm' AND person_id = ".$this->db_add_param($person_id)." AND not exists( SELECT * @@ -910,6 +910,11 @@ class dokument extends basis_db where dok.prestudent_id = ps.prestudent_id and dokument_kurzbz = ".$this->db_add_param($dokument_kurzbz).")"; + if (isset($studiengang_typen) && is_array($studiengang_typen) && !empty($studiengang_typen)) + { + $qry .= ' AND sg.typ IN ('. $db->db_implode4SQL($studiengang_typen).')'; + } + //gibt ein Array von zu akzeptierenden Dokumenten zurück if ($db->db_query($qry)) { @@ -923,11 +928,14 @@ class dokument extends basis_db } //für alle prestudent_ids das Dokument akzeptieren - $qry = "INSERT INTO public.tbl_dokumentprestudent(dokument_kurzbz, prestudent_id) VALUES"; + $qry = "INSERT INTO public.tbl_dokumentprestudent(dokument_kurzbz, prestudent_id, datum, insertamum) VALUES"; foreach ($arrayDoksZuAkzeptieren as $prestudent_id) { - $qry .= "(".$this->db_add_param($dokument_kurzbz). ",". $prestudent_id. ")"; + $qry .= "(".$this->db_add_param($dokument_kurzbz). + ",".$this->db_add_param($prestudent_id, FHC_INTEGER). + ",".$this->db_add_param(date('Y-m-d')). + ",".$this->db_add_param(strftime('%Y-%m-%d %H:%M')). ")"; if (next($arrayDoksZuAkzeptieren) == true) { From 4eaf71e5c634cfe7a96bdce0b3d5d7a3b423eee6 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 14 Jul 2025 17:01:16 +0200 Subject: [PATCH 043/388] cancel Vertrag: correct error handling --- .../Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js index 074d22bde..c5de5a1fb 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js @@ -96,7 +96,7 @@ export default{ ? {vertrag_id: this.vertrag_id, person_id: this.person_id} : Promise.reject({handled: true})) .then(result => { - this.$api.call(ApiVertrag.cancelVertrag({vertrag_id: this.vertrag_id, person_id: this.person_id})) + return this.$api.call(ApiVertrag.cancelVertrag({vertrag_id: this.vertrag_id, person_id: this.person_id})) }) .then(result => { this.resetForm(); From 1f258c84d4d01aa4db7df27480d8cea3042b7772 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 15 Jul 2025 18:56:49 +0200 Subject: [PATCH 044/388] Studierendenverwaltung Projektarbeit: moved Beurteilung download to table actions, separate tabs for details and Betreuer --- .../Details/Projektarbeit/Projektarbeit.js | 34 +++++-- .../Details/Projektarbeit/Projektbetreuer.js | 88 +++++++++++++------ 2 files changed, 87 insertions(+), 35 deletions(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js index dd7c4913c..76953867f 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -348,19 +348,39 @@ export default { - + -
-
- - + + +
+
+
+
+ + +
+
-
- + +
+
+
+ +
+
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 9b02f9b01..183c81bc0 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -51,7 +51,8 @@ export default { {title: "Vertrag ID", field: "vertrag_id", visible: false}, {title: "Projektarbeit ID", field: "projektarbeit_id", visible: false}, { - title: 'Aktionen', field: 'actions', + title: 'Aktionen', + field: 'actions', minWidth: 150, // Ensures Action-buttons will be always fully displayed formatter: (cell, formatterParams, onRendered) => { let container = document.createElement('div'); @@ -62,6 +63,8 @@ export default { button.innerHTML = ''; button.title = this.$p.t('ui', 'bearbeiten'); button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); let data = cell.getData(); this.actionEditProjektbetreuer(data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz); }); @@ -71,13 +74,41 @@ export default { button.className = 'btn btn-outline-secondary btn-action'; button.innerHTML = ''; button.title = this.$p.t('ui', 'loeschen'); - button.addEventListener('click', () => { + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); const data = cell.getData(); this.actionDeleteProjektbetreuer(data.betreuer_id, data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz) }); container.append(button); - //container.append(cell.getData().actionDiv); + let data = cell.getData(); + if (data.beurteilungDownloadLink !== null) { + if (data.beurteilungDownloadLink == '') { + button = document.createElement('span'); + button.title = this.$p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') + button.innerHTML = ''; + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + }); + } + else { + button = document.createElement('a'); + button.setAttribute('href', data.beurteilungDownloadLink); + button.setAttribute('role', 'button'); + button.innerHTML = ''; + button.title = this.$p.t('projektarbeit', 'projektbeurteilungErstellen'); + button.className = 'btn btn-outline-secondary btn-action'; + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + window.location.href = data.beurteilungDownloadLink; + }); + } + container.append(button); + } return container; }, @@ -404,7 +435,7 @@ export default { template: `
-
+
{{this.$p.t('projektarbeit','betreuerGross')}} @@ -484,27 +515,28 @@ export default {
- - -
- -
- - +
+ + +
+
+ + +
@@ -512,17 +544,17 @@ export default { -
+
-
+
Date: Tue, 15 Jul 2025 23:08:12 +0200 Subject: [PATCH 045/388] Studierendenverwaltung archiv: removed tabulator columns from computed --- .../Stv/Studentenverwaltung/Details/Archiv.js | 91 ------------------- 1 file changed, 91 deletions(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js index 41bd222b8..d02b64c18 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js @@ -67,97 +67,6 @@ export default { }; }, computed: { - tabulatorColumns() { - const columns = [ - {title: "Akte Id", field: "akte_id", visible: false}, - {title: this.$p.t('stv', 'archiv_title'), field: "titel"}, - {title: this.$p.t('stv', 'archiv_description'), field: "bezeichnung"}, - {title: this.$p.t('stv', 'archiv_creation_date'), field: "erstelltam"}, - { - title: this.$p.t('stv', 'archiv_signiert'), - field: "signiert", - formatter:"tickCross", - hozAlign:"center", - formatterParams: { - tickElement: '', - crossElement: '' - } - }, - { - title: "Selfservice", - field: "stud_selfservice", - formatter:"tickCross", - hozAlign:"center", - formatterParams: { - tickElement: '', - crossElement: '' - }, - }, - {title: this.$p.t('stv', 'archiv_accepted_on_at'), field: "akzeptiertamum"}, - { - title: this.$p.t('stv', 'archiv_gedruckt'), - field: "gedruckt", - visible: false, - formatter:"tickCross", - hozAlign:"center", - formatterParams: { - tickElement: '', - crossElement: '' - } - }, - { - title: 'Aktionen', field: 'actions', - formatter: (cell, formatterParams, onRendered) => { - let container = document.createElement('div'); - container.className = "d-flex gap-2"; - - let downloadButton = document.createElement('button'); - downloadButton.className = 'btn btn-outline-secondary'; - downloadButton.innerHTML = ''; - downloadButton.title = this.$p.t('ui', 'downloadDok'); - downloadButton.addEventListener('click', evt => { - evt.stopPropagation(); - this.actionDownload(cell.getData().akte_id); - }); - container.append(downloadButton); - - if (this.config.showEdit) - { - let editButton = document.createElement('button'); - editButton.className = 'btn btn-outline-secondary'; - editButton.innerHTML = ''; - editButton.addEventListener('click', () => - this.$refs.edit.open(cell.getData()) - ); - container.append(editButton); - } - - let deleteButton = document.createElement('button'); - deleteButton.className = 'btn btn-outline-secondary'; - deleteButton.innerHTML = ''; - deleteButton.addEventListener('click', evt => { - evt.stopPropagation(); - this.$fhcAlert - .confirmDelete() - .then(result => result ? {akte_id: cell.getData().akte_id, studiengang_kz: this.modelValue.studiengang_kz} : Promise.reject({handled:true})) - .then(this.$fhcApi.factory.stv.archiv.delete) - .then(() => { - //cell.getRow().delete(); - this.reload(); - }) - .catch(this.$fhcAlert.handleSystemError); - }); - container.append(deleteButton); - - return container; - }, - minWidth: 150, // Ensures Action-buttons will be always fully displayed - maxWidth: 150, - frozen: true - } - ]; - return columns; - }, tabulatorOptions() { const options = { ajaxURL: 'dummy', From 1883e8a6f1df3acb10681fd4d90a8bba44e35a5c Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 16 Jul 2025 15:19:50 +0200 Subject: [PATCH 046/388] moved default stunden for projektbetreuer (master/bachelor) to config --- config/global.config-default.inc.php | 6 ++++++ content/student/studentprojektarbeit.js.php | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/config/global.config-default.inc.php b/config/global.config-default.inc.php index 8cfc36bfb..f24a302cc 100644 --- a/config/global.config-default.inc.php +++ b/config/global.config-default.inc.php @@ -162,6 +162,12 @@ define('CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON', ''); // Legt fest, ob Vertragsdetails zum Projektauftrag im Reiter Projektarbeit angezeigt werden define('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN', false); +// Legt default Stunden pro Projektarbeitsbetreuung für Bachelorarbeiten fest +define('FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_BACHELOR', '5.0'); + +// Legt default Stunden pro Projektarbeitsbetreuung für Masterarbeiten fest +define('FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_MASTER', '5.0'); + // Anzeigeoptionen für LV-Plan Menü define('CIS_LVPLAN_EXPORT_ANZEIGEN',true); define('CIS_LVPLAN_PERSONENAUSWAHL_ANZEIGEN',true); diff --git a/content/student/studentprojektarbeit.js.php b/content/student/studentprojektarbeit.js.php index 6c3919327..2005d85fc 100644 --- a/content/student/studentprojektarbeit.js.php +++ b/content/student/studentprojektarbeit.js.php @@ -1165,12 +1165,14 @@ function StudentProjektbetreuerDetailReset() if(document.getElementById('student-projektarbeit-menulist-projekttyp').value=='Diplom') { - document.getElementById('student-projektbetreuer-textbox-stunden').value='5.0'; + document.getElementById('student-projektbetreuer-textbox-stunden').value= + ; document.getElementById('student-projektbetreuer-menulist-betreuerart').value='Erstbegutachter'; } else if(document.getElementById('student-projektarbeit-menulist-projekttyp').value=='Bachelor') { - document.getElementById('student-projektbetreuer-textbox-stunden').value='4.0'; + document.getElementById('student-projektbetreuer-textbox-stunden').value= + ; document.getElementById('student-projektbetreuer-menulist-betreuerart').value='Begutachter'; } else if(document.getElementById('student-projektarbeit-menulist-projekttyp').value=='Praktikum') From 94e25da6c89afb2a173bde19df662dd96cf6d07e Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 16 Jul 2025 16:13:27 +0200 Subject: [PATCH 047/388] Added phrases for lvevaluierung --- system/phrasesupdate.php | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 8ac45c0fa..417eb9110 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42322,6 +42322,86 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'spracheAuswaehlen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sprache auswählen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Select language', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'fhtwLogo', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'FH Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'UAS Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungscodeEingeben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Evaluierungscode eingeben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Enter Evaluation code', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'fragebogen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Fragebogen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Questionnaire', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From 9fa23a1471712f8e3172b196e2b66c0d9ec161e9 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Thu, 17 Jul 2025 16:21:23 +0200 Subject: [PATCH 048/388] fixed check permission --- application/controllers/api/frontend/v1/lv/DirektGruppe.php | 4 +++- application/controllers/api/frontend/v1/lv/Gruppe.php | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/lv/DirektGruppe.php b/application/controllers/api/frontend/v1/lv/DirektGruppe.php index fe1737f6a..2dcf7d3cb 100644 --- a/application/controllers/api/frontend/v1/lv/DirektGruppe.php +++ b/application/controllers/api/frontend/v1/lv/DirektGruppe.php @@ -99,7 +99,9 @@ class DirektGruppe extends FHCAPI_Controller if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - $oe_array = $result; + $oe_array = []; + if (hasData($result)) + $oe_array = getData($result); if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && !$this->_ci->permissionlib->isBerechtigtMultipleOe('assistenz', $oe_array, 'suid')) diff --git a/application/controllers/api/frontend/v1/lv/Gruppe.php b/application/controllers/api/frontend/v1/lv/Gruppe.php index 09f253a59..4a1e68656 100644 --- a/application/controllers/api/frontend/v1/lv/Gruppe.php +++ b/application/controllers/api/frontend/v1/lv/Gruppe.php @@ -181,7 +181,10 @@ class Gruppe extends FHCAPI_Controller if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - $oe_array = $result; + + $oe_array = []; + if (hasData($result)) + $oe_array = getData($result); if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && !$this->_ci->permissionlib->isBerechtigtMultipleOe('assistenz', $oe_array, 'suid') && From 75adcefd5168f2b3da82d7fa19aaeb7eb6343821 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 21 Jul 2025 17:52:21 +0200 Subject: [PATCH 049/388] Studentenverwaltung Projektarbeit: made text input possible for all date input --- .../Studentenverwaltung/Details/Projektarbeit/Details.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js index e51828f98..2fdc9d996 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -350,7 +350,10 @@ export default { v-model="formData.beginn" auto-apply :enable-time-picker="false" + text-input + locale="de" format="dd.MM.yyyy" + model-type="yyyy-MM-dd" name="beginn" > @@ -361,7 +364,10 @@ export default { v-model="formData.ende" auto-apply :enable-time-picker="false" + text-input + locale="de" format="dd.MM.yyyy" + model-type="yyyy-MM-dd" name="ende" > @@ -375,7 +381,10 @@ export default { v-model="formData.gesperrtbis" auto-apply :enable-time-picker="false" + text-input + locale="de" format="dd.MM.yyyy" + model-type="yyyy-MM-dd" name="gesperrtbis" > From 96cb546b68477da2ef7d4ab2ab72ebb600db95aa Mon Sep 17 00:00:00 2001 From: ma0048 Date: Wed, 23 Jul 2025 14:14:03 +0200 Subject: [PATCH 050/388] permission check bug fixed --- application/controllers/api/frontend/v1/lv/Lehreinheit.php | 4 +++- application/controllers/api/frontend/v1/lv/Lektor.php | 4 +++- application/models/ressource/Stundenplandev_model.php | 5 +++-- public/js/api/lehrveranstaltung/gruppe.js | 2 +- public/js/components/LVVerwaltung/Lektor/Daten.js | 1 + 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/application/controllers/api/frontend/v1/lv/Lehreinheit.php b/application/controllers/api/frontend/v1/lv/Lehreinheit.php index d58489453..fd1c23667 100644 --- a/application/controllers/api/frontend/v1/lv/Lehreinheit.php +++ b/application/controllers/api/frontend/v1/lv/Lehreinheit.php @@ -414,7 +414,9 @@ class Lehreinheit extends FHCAPI_Controller if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - $oe_array = $result; + $oe_array = []; + if (hasData($result)) + $oe_array = getData($result); if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && !$this->_ci->permissionlib->isBerechtigtMultipleOe('assistenz', $oe_array, 'suid') && diff --git a/application/controllers/api/frontend/v1/lv/Lektor.php b/application/controllers/api/frontend/v1/lv/Lektor.php index 332bc47b6..4a244c1a1 100644 --- a/application/controllers/api/frontend/v1/lv/Lektor.php +++ b/application/controllers/api/frontend/v1/lv/Lektor.php @@ -284,7 +284,9 @@ class Lektor extends FHCAPI_Controller if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - $oe_array = $result; + $oe_array = []; + if (hasData($result)) + $oe_array = getData($result); return $this->checkPermissionGenerel($permissions, $oe_array); } diff --git a/application/models/ressource/Stundenplandev_model.php b/application/models/ressource/Stundenplandev_model.php index 82b3779ab..e718ba073 100644 --- a/application/models/ressource/Stundenplandev_model.php +++ b/application/models/ressource/Stundenplandev_model.php @@ -223,13 +223,14 @@ class Stundenplandev_model extends DB_Model public function deleteLektorPlanning($lehreinheit_id, $mitarbeiter_uid) { - $this->addDistinct('mitarbeiter_uid'); + //TODO (david) prüfen ob der check notwendig ist + /*$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'); + 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)); diff --git a/public/js/api/lehrveranstaltung/gruppe.js b/public/js/api/lehrveranstaltung/gruppe.js index 12c55509c..e22fdd847 100644 --- a/public/js/api/lehrveranstaltung/gruppe.js +++ b/public/js/api/lehrveranstaltung/gruppe.js @@ -30,7 +30,7 @@ export default { { return { method: 'post', - url: '/api/frontend/v1/lv/gruppe/deleteLVPlan/', + url: '/api/frontend/v1/lv/gruppe/deleteFromLVPlan/', params: deleteData }; }, diff --git a/public/js/components/LVVerwaltung/Lektor/Daten.js b/public/js/components/LVVerwaltung/Lektor/Daten.js index bb40f56fe..0f6b9e0f7 100644 --- a/public/js/components/LVVerwaltung/Lektor/Daten.js +++ b/public/js/components/LVVerwaltung/Lektor/Daten.js @@ -253,6 +253,7 @@ export default{ Date: Thu, 31 Jul 2025 09:10:11 +0200 Subject: [PATCH 051/388] studiensemester_kurzbz aus dem fronted beruecksichtigen extendedHeaderFilter suche in mehreren spalten moeglich getAllOe sql abfrage richtig gestellt --- .../api/frontend/v1/Lehrveranstaltung.php | 38 ++++-- .../models/education/Lehreinheit_model.php | 6 + .../education/Lehrveranstaltung_model.php | 16 ++- public/js/api/lehrveranstaltung.js | 20 +++- public/js/apps/LVVerwaltung.js | 66 ++++++++++- .../components/LVVerwaltung/LVVerwaltung.js | 112 ++++++++++-------- .../js/components/LVVerwaltung/Setup/Table.js | 64 ++-------- .../tabulator/filters/extendedHeaderFilter.js | 11 ++ 8 files changed, 201 insertions(+), 132 deletions(-) diff --git a/application/controllers/api/frontend/v1/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/Lehrveranstaltung.php index 098d44712..2e254bfc8 100644 --- a/application/controllers/api/frontend/v1/Lehrveranstaltung.php +++ b/application/controllers/api/frontend/v1/Lehrveranstaltung.php @@ -27,8 +27,8 @@ class Lehrveranstaltung extends FHCAPI_Controller public function __construct() { parent::__construct([ - 'loadByEmployee' => ['admin:r', 'assistenz:r'], - 'loadByStudiengang' => ['admin:r', 'assistenz:r'], + 'getByEmp' => ['admin:r', 'assistenz:r'], + 'getByStg' => ['admin:r', 'assistenz:r'], 'loadByLV' => ['admin:r', 'assistenz:r'], ]); @@ -37,6 +37,7 @@ class Lehrveranstaltung extends FHCAPI_Controller $this->_ci->load->model('education/Lehreinheit_model', 'LehreinheitModel'); $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); @@ -46,12 +47,14 @@ class Lehrveranstaltung extends FHCAPI_Controller ) ); } - 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'); + public function getByEmp($studiensemester_kurzbz = null, $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->getStudiensemesterKurzbz($studiensemester_kurzbz); $lehrveranstaltungen = $this->_ci->LehreinheitModel->getLvsByEmployee($mitarbeiter_uid, $studiensemester_kurzbz, $stg_kz); $lehrveranstaltungen_data = $this->getDataOrTerminateWithError($lehrveranstaltungen); @@ -72,8 +75,7 @@ class Lehrveranstaltung extends FHCAPI_Controller $this->terminateWithSuccess($tree); } - - public function loadByStudiengang($studiengang_kz = null, $semester = null) + public function getByStg($studiensemester_kurzbz = null, $studiengang_kz = null, $semester = null) { 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); @@ -87,7 +89,7 @@ class Lehrveranstaltung extends FHCAPI_Controller $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel'); - $studiensemester_kurzbz = $this->_ci->variablelib->getVar('semester_aktuell'); + $studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz); $studienplan_data = $this->_ci->StudienplanModel->getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $semester, $verband); $studienplan_ids = array(); @@ -107,7 +109,6 @@ class Lehrveranstaltung extends FHCAPI_Controller $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) { @@ -246,4 +247,19 @@ class Lehrveranstaltung extends FHCAPI_Controller } } } + + private function getStudiensemesterKurzbz($studiensemester_kurzbz = null) + { + if (!is_null($studiensemester_kurzbz)) + { + $studiensemester_result = $this->_ci->StudiensemesterModel->load($studiensemester_kurzbz); + + if (isError($studiensemester_result) || !hasData($studiensemester_result)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + return getData($studiensemester_result)[0]->studiensemester_kurzbz; + } + + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + } } diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index ce414bad2..c33b87ad4 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -356,6 +356,8 @@ EOSQL; gruppen.gruppen, mitarbeiter.lektoren, mitarbeiter.le_planstunden, + mitarbeiter.vorname, + mitarbeiter.nachname, mitarbeiter.semesterstunden, fachbereich.bezeichnung as fachbereich, UPPER(CONCAT(tbl_studiengang.typ,tbl_studiengang.kurzbz)) as studiengang, @@ -659,11 +661,15 @@ EOSQL; SELECT tbl_lehreinheitmitarbeiter.lehreinheit_id, STRING_AGG(m.kurzbz, ' ') AS lektoren, + STRING_AGG(tbl_person.vorname, ' ') AS vorname, + STRING_AGG(tbl_person.nachname, ' ') AS nachname, 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) + JOIN public.tbl_benutzer ON mitarbeiter_uid = uid + JOIN public.tbl_person ON tbl_benutzer.person_id = tbl_person.person_id GROUP BY tbl_lehreinheitmitarbeiter.lehreinheit_id )"; } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 121de9233..303bebe1e 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -1200,19 +1200,29 @@ class Lehrveranstaltung_model extends DB_Model public function getAllOe($lv_id, $stg_kz = null) { - $qry = "SELECT DISTINCT oe_kurzbz + $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 = ? "; + WHERE lehrveranstaltung_id = ?)"; $params = array($lv_id); if (!is_null($stg_kz)) { - $qry .= ' OR studiengang_kz = ?'; + $qry .= ' UNION + (SELECT oe_kurzbz + FROM public.tbl_studiengang WHERE studiengang_kz = ?)'; $params[] = $stg_kz; } + else + { + $qry .= ' UNION + (SELECT oe_kurzbz + FROM public.tbl_studiengang WHERE studiengang_kz = (SELECT tbl_lehrveranstaltung.studiengang_kz FROM lehre.tbl_lehrveranstaltung WHERE lehrveranstaltung_id = ?)) + '; + $params[] = $lv_id; + } return $this->execReadOnlyQuery($qry, $params); } diff --git a/public/js/api/lehrveranstaltung.js b/public/js/api/lehrveranstaltung.js index 0499572ba..8aa6becaf 100644 --- a/public/js/api/lehrveranstaltung.js +++ b/public/js/api/lehrveranstaltung.js @@ -7,16 +7,24 @@ export default { url: '/api/frontend/v1/Lehrveranstaltung/loadByLV/' + encodeURIComponent(lehrveranstaltung_id) }; }, - getByStg(studiengang_kz, semester) + getByStg(studiensemester_kurzbz, studiengang_kz, semester = null) { - return ("/api/frontend/v1/Lehrveranstaltung/loadByStudiengang/" + encodeURIComponent(studiengang_kz) + "/" + encodeURIComponent(semester)); - }, + let path = "/api/frontend/v1/Lehrveranstaltung/getByStg/" + encodeURIComponent(studiensemester_kurzbz) + "/" + encodeURIComponent(studiengang_kz); - getByEmpStg(mitarbeiter_uid, stg) + if (semester) + path += "/" + encodeURIComponent(semester); + + return path; + }, + getByEmp(studiensemester_kurzbz, mitarbeiter_uid, stg = null) { - return ("/api/frontend/v1/Lehrveranstaltung/loadByEmployee/" + encodeURIComponent(mitarbeiter_uid) + "/" + encodeURIComponent(stg)); - }, + let path = "/api/frontend/v1/Lehrveranstaltung/getByEmp/" + encodeURIComponent(studiensemester_kurzbz) + "/" + encodeURIComponent(mitarbeiter_uid); + if (stg) + path += "/" + encodeURIComponent(stg); + + return path; + }, getTable(url) { return { diff --git a/public/js/apps/LVVerwaltung.js b/public/js/apps/LVVerwaltung.js index c582f817e..2ab3fd98c 100644 --- a/public/js/apps/LVVerwaltung.js +++ b/public/js/apps/LVVerwaltung.js @@ -1,5 +1,6 @@ import LVVerwaltung from "../components/LVVerwaltung/LVVerwaltung.js"; import Phrasen from "../plugins/Phrasen.js"; +import {DEFAULT_MODE_RAUMINFO} from "../components/Cis/Mylv/RoomInformation"; const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router; @@ -13,8 +14,35 @@ const router = VueRouter.createRouter({ }, { name: `byEmp`, - path: `/emp/:emp/:stg?`, - component: LVVerwaltung + path: `/emp/:studiensemester_kurzbz/:emp/:stg?/:semester?`, + component: LVVerwaltung, + props: route => { + let {emp, stg, semester, studiensemester_kurzbz} = route.params; + + if (emp === '') + emp = undefined; + + if (stg === '') + stg = undefined; + + if (studiensemester_kurzbz === '') + studiensemester_kurzbz = undefined; + + return { + studiensemester_kurzbz: studiensemester_kurzbz, + emp: emp, + stg: stg, + }; + }, + beforeEnter: (to, from, next) => { + const { studiensemester_kurzbz } = to.params; + const isSemester = /^(SS|WS)\d{4}$/.test(studiensemester_kurzbz); + + if (!isSemester) + return next({ path: '/' }); + else + next(); + } }, /*{ name: `byFachbereich`, @@ -23,13 +51,41 @@ const router = VueRouter.createRouter({ },*/ { name: `byStg`, - path: `/stg/:stg/:semester?`, - component: LVVerwaltung + path: '/stg/:studiensemester_kurzbz/:stg?/:semester?/', + component: LVVerwaltung, + props: route => { + let { studiensemester_kurzbz, stg, semester } = route.params; + + if (semester === '') + semester = undefined; + + if (studiensemester_kurzbz === '') + studiensemester_kurzbz = undefined; + + if (stg === '') + semester = undefined; + + return { + studiensemester_kurzbz: studiensemester_kurzbz, + stg: stg, + semester: semester != null ? Number(semester) : null, + }; + }, + beforeEnter: (to, from, next) => { + const studiensemester_kurzbz = to.params?.studiensemester_kurzbz + const isSemester = /^(SS|WS)\d{4}$/.test(studiensemester_kurzbz); + + if (!isSemester) + return next({ path: '/' }); + else + next(); + } }, { path: '/:pathMatch(.*)*', redirect: '/' - } + }, + ] }); diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js index c7c34802d..7b8921c80 100644 --- a/public/js/components/LVVerwaltung/LVVerwaltung.js +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -26,16 +26,22 @@ export default { defaultSemester: String, lvRoot: String, permissions: Object, - config: Object + config: Object, + stg: { type: String, required: false }, + semester: { type: Number, required: false, default: null }, + studiensemester_kurzbz: { type: String, required: false, default: null }, + emp: { type: String, required: false, default: null } }, computed: { - type(){ - return this.$route.params.type + selectedStudiensemester() { + return this.studiensemester_kurzbz != null + ? this.studiensemester_kurzbz + : this.defaultSemester; } }, provide() { return { - currentSemester: Vue.computed(() => this.studiensemesterKurzbz), + currentSemester: Vue.computed(() => this.selectedStudiensemester), dropdowns: this.dropdowns, configShowVertragsdetails: this.config.showVertragsdetails, configShowGewichtung: this.config.showGewichtung, @@ -49,18 +55,26 @@ export default { } }, mounted() { - this.updateFilter(this.$route); + this.updateFilter(); }, watch: { - '$route'(to) { - this.updateFilter(to); + stg() { + this.updateFilter(); + }, + semester() { + this.updateFilter(); + }, + selectedStudiensemester() { + this.updateFilter(); + }, + emp() { + this.updateFilter(); }, }, data() { return { selected: [], - studiensemesterKurzbz: this.defaultSemester, - stg: "", + studiengang: "", filter: {}, endpoint: ApiStudiengangTree, dropdowns: { @@ -95,20 +109,16 @@ export default { } }, methods: { - updateFilter(route) + updateFilter() { - let filter = { ...route.params, ...route.query }; - if (!filter.activeFilter) - { - if (filter.emp) - { - filter.activeFilter = 'employee'; - } - else if (filter.stg) - { - filter.activeFilter = 'verband'; - } + const filter = { + stg: this.stg, + emp: this.emp, + semester: this.semester, + studiensemester_kurzbz: this.selectedStudiensemester, + activeFilter: this.emp ? 'employee' : this.stg ? 'verband' : null } + this.filter = filter; }, handleRowClicked(data) @@ -117,18 +127,26 @@ export default { }, onSelectEmployee(emp) { - let stg = this.stg === '' ? null : this.stg; + const { stg, semester } = this.filter; - this.$router.push({ - name: 'byEmp', - params: { emp, stg, activeFilter: 'employee'}, - }); + let studiensemester_kurzbz = this.selectedStudiensemester; + const params = { emp }; + + if (stg) + params.stg = stg; + if (semester !== null) + params.semester = semester; + if (studiensemester_kurzbz) + params.studiensemester_kurzbz = studiensemester_kurzbz; + + this.$router.push({ name: 'byEmp', params }) }, onSelectVerband({link}) { let stg = null; let semester = null; + let studiensemester_kurzbz = this.selectedStudiensemester; if (typeof link === 'number') stg = link; @@ -137,28 +155,22 @@ export default { [stg, semester] = link.split('/'); } - this.stg = stg; + const routeName = this.filter.emp ? 'byEmp' : 'byStg'; + const params = { 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' }, - }); - } + if (semester !== null) + params.semester = Number(semester); + if (studiensemester_kurzbz) + params.studiensemester_kurzbz = studiensemester_kurzbz; + if (this.filter.emp) + params.emp = this.filter.emp; + this.$router.push({ name: routeName, params }); this.selected = []; }, resetEmployeeFilter() { - const newParams = { ...this.$route.params, activeFilter: 'verband' }; + const newParams = { ...this.filter, activeFilter: 'verband' }; if (newParams.stg === '') this.$router.replace({ name: 'index' }); else @@ -166,24 +178,24 @@ export default { 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(); + const routeName = this.filter.activeFilter === 'employee' ? 'byEmp' : 'byStg'; + const newParams = {...this.filter, studiensemester_kurzbz: newValue}; + this.$router.push({ name: routeName, params: newParams }); this.selected = []; }, }, created() { - if (this.$route.params.stg !== undefined) + if (this.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.selectedStudiengang = this.semester !== '' && this.semester + ? `${this.stg}/${this.semester}` + : this.stg; } this.$p.loadCategory(['lehre', 'person', 'global']) @@ -250,7 +262,7 @@ export default {
- +
diff --git a/public/js/components/LVVerwaltung/Setup/Table.js b/public/js/components/LVVerwaltung/Setup/Table.js index a1b2830f1..5b4d45c24 100644 --- a/public/js/components/LVVerwaltung/Setup/Table.js +++ b/public/js/components/LVVerwaltung/Setup/Table.js @@ -61,42 +61,6 @@ export default { }, 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, @@ -168,7 +132,7 @@ export default { headerFilterFunc: extendedHeaderFilter, }, layout: 'fitDataStretch', - persistenceID: 'lehrveranstaltungen_2025_07_11_v1', + persistenceID: 'lehrveranstaltungen_2025_07_31_v1', selectableRowsRangeMode: 'click', selectableRows: true, rowContextMenu: (component, e) => { @@ -348,7 +312,7 @@ export default { {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'}}, + {title: this.$p.t('lehre', 'lehrende'), field: "lektoren", headerFilter: true, headerFilterFuncParams: {field: ['lektoren', 'vorname', 'nachname']}}, ], } @@ -417,18 +381,14 @@ export default { { if (this.filter.activeFilter === 'employee' && this.filter.emp) { - return this.$api.getUri(ApiLv.getByEmpStg( - this.filter.emp, - this.filter.stg - )); + const { emp, stg, studiensemester_kurzbz } = this.filter; + return this.$api.getUri(ApiLv.getByEmp(studiensemester_kurzbz, emp, stg)); } if (this.filter.activeFilter === 'verband' && this.filter.stg) { - return this.$api.getUri(ApiLv.getByStg( - this.filter.stg, - this.filter.semester - )); + const { stg, semester, studiensemester_kurzbz } = this.filter; + return this.$api.getUri(ApiLv.getByStg(studiensemester_kurzbz, stg, semester)); } }, resetEmployeeFilter() @@ -437,16 +397,6 @@ export default { 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(); @@ -649,7 +599,7 @@ export default { let rootRows = this.$refs.table.tabulator.getRows(true); var lastRow = rootRows[rootRows.length - 1]; - lastRow.treeCollapse(true) + lastRow?.treeCollapse(true) this.currentTreeLevel = 0; }, diff --git a/public/js/tabulator/filters/extendedHeaderFilter.js b/public/js/tabulator/filters/extendedHeaderFilter.js index 5dfcce205..1112d36f3 100644 --- a/public/js/tabulator/filters/extendedHeaderFilter.js +++ b/public/js/tabulator/filters/extendedHeaderFilter.js @@ -41,6 +41,17 @@ function parseFilterExpression(expression) export function extendedHeaderFilter(headerValue, rowValue, rowData, filterParams) { + const fields = Array.isArray(filterParams?.field) + ? filterParams.field + : [filterParams?.field]; + + if (fields.length > 1 && rowData) + { + rowValue = fields + .map(f => rowData[f] ?? '') + .filter(Boolean) + .join(' '); + } if (typeof headerValue === 'boolean') { return rowValue === headerValue; From 4d3ad0008ea3a12d56ca16ff554093768f92cafe Mon Sep 17 00:00:00 2001 From: ma0048 Date: Thu, 31 Jul 2025 09:33:11 +0200 Subject: [PATCH 052/388] deleted automated added import --- public/js/apps/LVVerwaltung.js | 1 - 1 file changed, 1 deletion(-) diff --git a/public/js/apps/LVVerwaltung.js b/public/js/apps/LVVerwaltung.js index 2ab3fd98c..c72f9fc9e 100644 --- a/public/js/apps/LVVerwaltung.js +++ b/public/js/apps/LVVerwaltung.js @@ -1,6 +1,5 @@ import LVVerwaltung from "../components/LVVerwaltung/LVVerwaltung.js"; import Phrasen from "../plugins/Phrasen.js"; -import {DEFAULT_MODE_RAUMINFO} from "../components/Cis/Mylv/RoomInformation"; const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router; From 5d07879ebdfedae988508c96db1a078cd89099a1 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Fri, 1 Aug 2025 11:44:23 +0200 Subject: [PATCH 053/388] org form hinzugefuegt im stree gruppe autocomplete auch auf die bezeichnung getalloe sql angepasst --- .../api/frontend/v1/lv/Lehreinheit.php | 2 +- .../api/frontend/v1/lv/StgTree.php | 26 +++++++++++ .../models/education/Lehreinheit_model.php | 2 +- .../education/Lehrveranstaltung_model.php | 46 +++++++++---------- .../models/organisation/Studienplan_model.php | 2 + public/js/apps/LVVerwaltung.js | 5 +- .../LVVerwaltung/Details/Gruppen.js | 2 +- .../components/LVVerwaltung/LVVerwaltung.js | 6 +-- 8 files changed, 59 insertions(+), 32 deletions(-) diff --git a/application/controllers/api/frontend/v1/lv/Lehreinheit.php b/application/controllers/api/frontend/v1/lv/Lehreinheit.php index fd1c23667..b851f8c22 100644 --- a/application/controllers/api/frontend/v1/lv/Lehreinheit.php +++ b/application/controllers/api/frontend/v1/lv/Lehreinheit.php @@ -80,7 +80,7 @@ class Lehreinheit extends FHCAPI_Controller $lehrveranstaltung = getData($lehrveranstaltung_result)[0]; - $oe_result = $this->_ci->LehrveranstaltungModel->getAllOe($lehrveranstaltung->lehrveranstaltung_id, $lehrveranstaltung->studiengang_kz); + $oe_result = $this->_ci->LehrveranstaltungModel->getAllOe($lehrveranstaltung->lehrveranstaltung_id); $oe_array = hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array(); if (!$this->_ci->permissionlib->isBerechtigtMultipleOe('admin', $oe_array, 'suid') && diff --git a/application/controllers/api/frontend/v1/lv/StgTree.php b/application/controllers/api/frontend/v1/lv/StgTree.php index fe3047902..8272da978 100644 --- a/application/controllers/api/frontend/v1/lv/StgTree.php +++ b/application/controllers/api/frontend/v1/lv/StgTree.php @@ -86,6 +86,32 @@ class StgTree extends FHCAPI_Controller ]); $list = $this->getDataOrTerminateWithError($result); + $result = $this->StudiengangModel->load($studiengang_kz); + $result = $this->getDataOrTerminateWithError($result); + if ($result) + { + if (current($result)->mischform) + { + $this->load->model('organisation/Studienordnung_model', 'StudienordnungModel'); + + $this->StudienordnungModel->addDistinct(); + $this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link"); + $this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name"); + $this->StudienordnungModel->addSelect("TRUE as leaf", false); + + $this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id'); + + $result = $this->StudienordnungModel->loadWhere([ + 'aktiv' => true, + 'studiengang_kz' => $studiengang_kz, + 'p.orgform_kurzbz !=' => 'DDP' + ]); + $result = $this->getDataOrTerminateWithError($result); + + $list = array_merge($list, $result); + } + } + $this->terminateWithSuccess($list); } } diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index c33b87ad4..c373f5449 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -322,7 +322,7 @@ EOSQL; if (hasData($result)) { $lehrveranstaltung = getData($result)[0]; - $oe_result = $this->LehrveranstaltungModel->getAllOe($lehrveranstaltung->lehrveranstaltung_id, $lehrveranstaltung->studiengang_kz); + $oe_result = $this->LehrveranstaltungModel->getAllOe($lehrveranstaltung->lehrveranstaltung_id); return success(hasData($oe_result) ? array_column(getData($oe_result), 'oe_kurzbz') : array('')); } } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 303bebe1e..31ec2901f 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -1161,7 +1161,7 @@ class Lehrveranstaltung_model extends DB_Model } if (!is_null($verband)) { - $qry .= ' AND (orgform_kurzbz = ? OR orgform_kurzbz IS NULL)'; + $qry .= ' AND (tbl_lehrveranstaltung.orgform_kurzbz = ? OR tbl_lehrveranstaltung.orgform_kurzbz IS NULL)'; $params[] = $verband; } @@ -1198,31 +1198,29 @@ class Lehrveranstaltung_model extends DB_Model "; } - public function getAllOe($lv_id, $stg_kz = null) + public function getAllOe($lv_id) { - $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 = ?)"; + $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 .= ' UNION - (SELECT oe_kurzbz - FROM public.tbl_studiengang WHERE studiengang_kz = ?)'; - $params[] = $stg_kz; - } - else - { - $qry .= ' UNION - (SELECT oe_kurzbz - FROM public.tbl_studiengang WHERE studiengang_kz = (SELECT tbl_lehrveranstaltung.studiengang_kz FROM lehre.tbl_lehrveranstaltung WHERE lehrveranstaltung_id = ?)) - '; - $params[] = $lv_id; - } + UNION + + ( + SELECT oe_kurzbz + FROM public.tbl_studiengang + WHERE studiengang_kz = ( + SELECT tbl_lehrveranstaltung.studiengang_kz + FROM lehre.tbl_lehrveranstaltung + WHERE lehrveranstaltung_id = ? + ) + ) + "; + + $params = array($lv_id, $lv_id); return $this->execReadOnlyQuery($qry, $params); } diff --git a/application/models/organisation/Studienplan_model.php b/application/models/organisation/Studienplan_model.php index 5a9097d9a..0b41a8c39 100644 --- a/application/models/organisation/Studienplan_model.php +++ b/application/models/organisation/Studienplan_model.php @@ -107,6 +107,8 @@ class Studienplan_model extends DB_Model )); } + // Deprecated + // im Lehrveranstaltung_model vorhanden public function getAllOesForLv($lehrveranstaltung_id) { $this->addDistinct('oe_kurzbz'); diff --git a/public/js/apps/LVVerwaltung.js b/public/js/apps/LVVerwaltung.js index c72f9fc9e..f365b74a8 100644 --- a/public/js/apps/LVVerwaltung.js +++ b/public/js/apps/LVVerwaltung.js @@ -31,6 +31,7 @@ const router = VueRouter.createRouter({ studiensemester_kurzbz: studiensemester_kurzbz, emp: emp, stg: stg, + semester: semester }; }, beforeEnter: (to, from, next) => { @@ -62,12 +63,12 @@ const router = VueRouter.createRouter({ studiensemester_kurzbz = undefined; if (stg === '') - semester = undefined; + stg = undefined; return { studiensemester_kurzbz: studiensemester_kurzbz, stg: stg, - semester: semester != null ? Number(semester) : null, + semester: semester, }; }, beforeEnter: (to, from, next) => { diff --git a/public/js/components/LVVerwaltung/Details/Gruppen.js b/public/js/components/LVVerwaltung/Details/Gruppen.js index 62dae172f..219b956d8 100644 --- a/public/js/components/LVVerwaltung/Details/Gruppen.js +++ b/public/js/components/LVVerwaltung/Details/Gruppen.js @@ -103,7 +103,7 @@ export default{ { const query = event.query.toLowerCase().trim(); this.filteredGroups = this.dropdowns.gruppen_array.filter(gruppe => { - return gruppe.gruppe_kurzbz.toLowerCase().includes(query); + return gruppe.gruppe_kurzbz.toLowerCase().includes(query) || gruppe?.bezeichnung?.toLowerCase().includes(query); }).map(gruppe => ({ label: gruppe.bezeichnung ? `${gruppe.gruppe_kurzbz.trim()} (${gruppe.bezeichnung})` diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js index 7b8921c80..7bfb3ec82 100644 --- a/public/js/components/LVVerwaltung/LVVerwaltung.js +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -28,7 +28,7 @@ export default { permissions: Object, config: Object, stg: { type: String, required: false }, - semester: { type: Number, required: false, default: null }, + semester: { type: [Number, String], required: false, default: null }, studiensemester_kurzbz: { type: String, required: false, default: null }, emp: { type: String, required: false, default: null } }, @@ -159,7 +159,7 @@ export default { const params = { stg }; if (semester !== null) - params.semester = Number(semester); + params.semester = semester; if (studiensemester_kurzbz) params.studiensemester_kurzbz = studiensemester_kurzbz; if (this.filter.emp) @@ -176,7 +176,7 @@ export default { else { delete newParams.emp; - newParams.semester = null; + this.$router.replace({ name: 'byStg', params: newParams }); } }, From be2419063651d3ceac7baafaa14883ca7f8117d6 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Mon, 4 Aug 2025 10:15:07 +0200 Subject: [PATCH 054/388] studiensemester auswahl abhaengig von url --- public/js/components/LVVerwaltung/LVVerwaltung.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js index 7bfb3ec82..faecbf71f 100644 --- a/public/js/components/LVVerwaltung/LVVerwaltung.js +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -262,7 +262,7 @@ export default {
- +
From 9ae78f2de673b62e4100b223219304b5a392d636 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Mon, 11 Aug 2025 09:23:18 +0200 Subject: [PATCH 055/388] master gemerged --- application/models/person/Notiz_model.php | 2 +- .../js/components/LVVerwaltung/LVVerwaltung.js | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/application/models/person/Notiz_model.php b/application/models/person/Notiz_model.php index b524451cb..bc4494f57 100644 --- a/application/models/person/Notiz_model.php +++ b/application/models/person/Notiz_model.php @@ -198,7 +198,7 @@ class Notiz_model extends DB_Model z.$type = ?"; if ($withoutTags) - $qry .= " AND tbl_notiz.typ IS NULL"; + $qry .= " AND n.typ IS NULL "; $qry .= "GROUP BY notiz_id, z.notizzuordnung_id, diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js index faecbf71f..e9d132848 100644 --- a/public/js/components/LVVerwaltung/LVVerwaltung.js +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -119,6 +119,12 @@ export default { activeFilter: this.emp ? 'employee' : this.stg ? 'verband' : null } + if (this.stg !== undefined) + { + this.selectedStudiengang = this.semester !== '' && this.semester + ? `${this.stg}/${this.semester}` + : this.stg; + } this.filter = filter; }, handleRowClicked(data) @@ -164,7 +170,6 @@ export default { params.studiensemester_kurzbz = studiensemester_kurzbz; if (this.filter.emp) params.emp = this.filter.emp; - this.$router.push({ name: routeName, params }); this.selected = []; }, @@ -191,13 +196,6 @@ export default { }, }, created() { - if (this.stg !== undefined) - { - this.selectedStudiengang = this.semester !== '' && this.semester - ? `${this.stg}/${this.semester}` - : this.stg; - } - this.$p.loadCategory(['lehre', 'person', 'global']) this.$api.call(ApiDetails.getStudiensemester()) @@ -261,7 +259,7 @@ export default {
- + From 3c3038362a0db114bd95ea932d703bdacd1fe2d5 Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Mon, 11 Aug 2025 10:38:26 +0200 Subject: [PATCH 056/388] update(MyLv VueRouter Studiensemester): adds the Studiensemester to the url of the vue router in the mylv view --- application/config/routes.php | 1 + public/js/apps/Dashboard/Fhc.js | 5 +++-- public/js/components/Cis/Mylv/Student.js | 13 ++++++------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/application/config/routes.php b/application/config/routes.php index 360005db7..3cba72628 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -63,6 +63,7 @@ $route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1'; $route['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1'; $route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1'; +$route['Cis/MyLv/.*'] = 'Cis/MyLv/index/$1'; // Studierendenverwaltung List Routes $route['api/frontend/v1/stv/[sS]tudents/inout'] = 'api/frontend/v1/stv/Students/index'; diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 473e1cf67..da1d8e39f 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -137,11 +137,12 @@ const router = VueRouter.createRouter({ component: CmsNews, props: true }, + //dafadsdafadsdafadsdafadsdafadsdafadsdafadsdafads { - path: `/Cis/MyLv`, + path: `/Cis/MyLv/:studiensemester?`, name: 'MyLv', component: MylvStudent, - props: true + props: true, }, { path: `/Cis/MyLv/Info/:studien_semester/:lehrveranstaltung_id`, diff --git a/public/js/components/Cis/Mylv/Student.js b/public/js/components/Cis/Mylv/Student.js index 508acb883..e70cd065d 100644 --- a/public/js/components/Cis/Mylv/Student.js +++ b/public/js/components/Cis/Mylv/Student.js @@ -75,17 +75,16 @@ export default { this.$refs.studiensemester.selectedIndex++; this.$refs.studiensemester.dispatchEvent(new Event('change', { bubbles: true })); }, - setHash(val) { - // TODO: make this a router param to enable history - location.hash = val; + updateRouter(val) { + this.$router.push(`/Cis/MyLv/${val}`); } }, created() { axios.get(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/components/Cis/Mylv/Studiensemester').then(res => { this.studiensemester = res.data.retval || []; - const hash = location.hash.substring(1); - if (hash && this.studiensemester.filter(s => s.studiensemester_kurzbz == hash).length) - this.currentSemester = hash; + const routerStudiensemester = this.$route.params.studiensemester; + if (routerStudiensemester && this.studiensemester.filter(s => s.studiensemester_kurzbz == routerStudiensemester).length) + this.currentSemester = routerStudiensemester; else this.currentSemester = this.nearestSem; }); @@ -104,7 +103,7 @@ export default { -
-
+
From 645da5a5bf4ed8a195eeb8949c73e1f208c38954 Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Wed, 13 Aug 2025 12:09:34 +0200 Subject: [PATCH 061/388] fix(Dashboard drag&drop): ensures dragend events trigger correctly in chrome --- public/js/components/Drop/Grid.js | 27 +++++++++++++++------------ public/js/composables/GridLogic.js | 3 ++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index ae1a6504c..cfe5747d4 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -434,11 +434,8 @@ export default { }, dragOver(evt) { if ((this.y + 1) > this.rows && (this.mode == MODE_MOVE || this.mode == MODE_RESIZE)) { - this.positionUpdates = this.positionUpdates?.filter(item => { - return item.widgetid == this.draggedItem.data.widgetid; - }) - this.dragEnd(); this.dragCancel(); + } if (!this.active) return this.dragCancel(); @@ -464,7 +461,7 @@ export default { this.draggedOffset[1] += y; y = 0; } - this.positionUpdates = this.dragGrid.move(this.draggedItem, x, y); + this.positionUpdates= this.dragGrid.move(this.draggedItem, x, y); break; } case MODE_RESIZE: { @@ -494,8 +491,11 @@ export default { }, dragEnd() { this.removeWidgetClones(); - if (this.mode == MODE_IDLE) + this.toggleDraggedItemOverlay(false); + + if (this.mode == MODE_IDLE){ return; + } // clean up unused classes let draggedItemNode = document.getElementById(this.draggedItem.data.widgetid); draggedItemNode.classList.remove("border-danger"); @@ -503,16 +503,19 @@ export default { ele.classList.remove("denied-dragging-animation"); }) - - - if (!this.active || this.x < 0 || this.y < 0 || this.x >= this.cols) - return this.dragCancel(); + //if (!this.active || this.x < 0 || this.y < 0 || this.x >= this.cols) + //return this.dragCancel(); + this.mode = MODE_IDLE; let updated = []; this.convertGridResultToUpdate(this.positionUpdates, updated); updated = this._updateFixedPositions(updated); if (updated.length) this.$emit('rearrangeItems', updated.filter(v => v)); + + this.draggedItem = null; + this.draggedNode = null; + this.$emit('draggedItem', null); }, _updateFixedPositions(updated) { updated.forEach((item, index) => { @@ -617,7 +620,7 @@ export default { @touchmove="dragOver" @touchend="dragCancel" @dragover.prevent="dragOver" - @drop="dragEnd" + @drop="dragEnd($event)" @mousemove="updateCursorOnMouseMove" @mouseleave="mouseLeave"> @@ -631,7 +634,7 @@ export default { @mouse-up="mouseUp" @start-resize="startResize" @dragging="dragging" - @end-drag="dragCancel" + @end-drag="dragEnd" @touch-end="dragEnd();mouseUp();" @touch-start="updateCursorOnMouseMove($event); mouseDown();" class="position-absolute" diff --git a/public/js/composables/GridLogic.js b/public/js/composables/GridLogic.js index 93c662eb5..ff8ae0c39 100644 --- a/public/js/composables/GridLogic.js +++ b/public/js/composables/GridLogic.js @@ -116,7 +116,7 @@ class GridLogic { prefer = DIR_RIGHT; } - const originalFrame = [...item.frame]; + const originalFrame = Array.isArray(item.frame) ? [...item.frame] : [item.frame]; const currItem = {...item}; currItem.x = x; @@ -146,6 +146,7 @@ class GridLogic { } } replaceUpdate[item.index] = { index: item.index, x, y }; + return replaceUpdate; } From 34a239a823ffdea8b6dac04b5471d0e0bcb74179 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 13 Aug 2025 14:54:43 +0200 Subject: [PATCH 062/388] Set Foto to null instead of empty String when Deleted --- application/controllers/api/frontend/v1/stv/Student.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/application/controllers/api/frontend/v1/stv/Student.php b/application/controllers/api/frontend/v1/stv/Student.php index ac09f39bb..70970d8b5 100644 --- a/application/controllers/api/frontend/v1/stv/Student.php +++ b/application/controllers/api/frontend/v1/stv/Student.php @@ -276,9 +276,14 @@ class Student extends FHCAPI_Controller $update_person = array(); foreach ($array_allowed_props_person as $prop) { $val = $this->input->post($prop); - if ($val !== null) { + if ($val !== null) + { $update_person[$prop] = $val; } + if($prop == 'foto' && $val == '') + { + $update_person[$prop] = null; + } } $array_allowed_props_student = ['matrikelnr']; From 4d78abf9ec2586e99b02c72f369fabd86814332e Mon Sep 17 00:00:00 2001 From: ma0068 Date: Thu, 14 Aug 2025 13:15:10 +0200 Subject: [PATCH 063/388] Tab Prestudent: use false for boolean and null for other variables for update if field is empty --- .../controllers/api/frontend/v1/stv/Prestudent.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Prestudent.php b/application/controllers/api/frontend/v1/stv/Prestudent.php index 4d0aa5fe1..2a427e569 100644 --- a/application/controllers/api/frontend/v1/stv/Prestudent.php +++ b/application/controllers/api/frontend/v1/stv/Prestudent.php @@ -142,15 +142,15 @@ class Prestudent extends FHCAPI_Controller $update_prestudent[$prop] = $val; } - // allowed to be null, but has to be in postparameter - if ( - in_array($prop, ['zgvdatum', 'zgvmadatum', 'zgvdoktordatum', 'zgv_code', 'zgvmas_code', 'zgvdoktor_code']) - && !isset($update_prestudent[$prop]) - && array_key_exists($prop, $_POST) - ) - { + //set null instead of empty string + if ($val === '' && ($prop != 'dual' || $prop != 'bismelden')){ $update_prestudent[$prop] = null; } + + //set false instead of empty string if boolean + if ($val === '' && ($prop === 'dual' || $prop === 'bismelden')) { + $update_prestudent[$prop] = false; + } } $update_prestudent['updateamum'] = date('c'); From e46f46c95bc41204e44d62010daf23cc10fe957e Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Thu, 14 Aug 2025 15:07:38 +0200 Subject: [PATCH 064/388] update(Dashboard grid): doesnt allow the user to drag a widget outside of the grid boundaries --- public/js/components/DashboardWidget/Url.js | 2 +- public/js/components/Drop/Grid.js | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/public/js/components/DashboardWidget/Url.js b/public/js/components/DashboardWidget/Url.js index 2763862a9..16eacab90 100644 --- a/public/js/components/DashboardWidget/Url.js +++ b/public/js/components/DashboardWidget/Url.js @@ -159,7 +159,7 @@ export default { // this.$emit('setConfig', true); -> use this to enable widget config mode if needed }, template: /*html*/ ` -
+
diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index cfe5747d4..d11e4c249 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -274,8 +274,23 @@ export default { dragging(event){ if(this.mode == MODE_MOVE){ this.toggleDraggedItemOverlay(true); - this.clonedWidget.style.top = `${this.clientY-20}px`; - this.clonedWidget.style.left = `${this.clientX-15}px`; + + const containerRect = this.$refs.container.getBoundingClientRect(); + const clonedWidgetRect = this.clonedWidget.getBoundingClientRect(); + + let desiredTop = this.clientY - 20; + let desiredLeft = this.clientX - 15; + + const minTop = 0; + const maxTop = containerRect.height - clonedWidgetRect.height; + const minLeft = 0; + const maxLeft = containerRect.width - clonedWidgetRect.width; + + const constrainedTop = Math.max(minTop, Math.min(maxTop, desiredTop)); + const constrainedLeft = Math.max(minLeft, Math.min(maxLeft, desiredLeft)); + + this.clonedWidget.style.top = `${constrainedTop}px`; + this.clonedWidget.style.left = `${constrainedLeft}px`; } }, createNewGrid(items) { @@ -413,6 +428,7 @@ export default { setTimeout(() => { this.draggedNode = evt.target.closest(".drop-grid-item"); //clones the widget for the drag Image + let clone = evt.target.closest(".drop-grid-item")?.cloneNode(true); clone.style.zIndex = 5; From 729618cbe7327da8dcc35b00dc04aa3e0cf166e7 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Thu, 14 Aug 2025 15:38:03 +0200 Subject: [PATCH 065/388] Tab Status: change format for Date for Check Bismeldestichtag --- application/controllers/api/frontend/v1/stv/Status.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Status.php b/application/controllers/api/frontend/v1/stv/Status.php index 629d5512a..7edb0305c 100644 --- a/application/controllers/api/frontend/v1/stv/Status.php +++ b/application/controllers/api/frontend/v1/stv/Status.php @@ -287,11 +287,11 @@ class Status extends FHCAPI_Controller ]); $this->form_validation->set_rules('_default', '', [ - ['meldestichtag_not_exceeded', function () use ($datum, $isBerechtigtNoStudstatusCheck) { + ['meldestichtag_not_exceeded', function () use ($datum_string, $isBerechtigtNoStudstatusCheck) { if ($isBerechtigtNoStudstatusCheck) return true; // Skip if access right says so - $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($datum); + $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($datum_string); return !$this->getDataOrTerminateWithError($result); }], @@ -733,6 +733,7 @@ class Status extends FHCAPI_Controller $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($oldstatus->datum); + //TODO(Manu) comment out: should not appear during delete (shiva) if (!$this->getDataOrTerminateWithError($result)) $this->terminateWithError( $this->p->t('lehre', 'error_dataVorMeldestichtag'), From a42e70e2fef192977b63926f64975f15070aa308 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Thu, 14 Aug 2025 16:28:20 +0200 Subject: [PATCH 066/388] comment out check Bismeldestichtag for deleteStatus --- application/controllers/api/frontend/v1/stv/Status.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Status.php b/application/controllers/api/frontend/v1/stv/Status.php index 7edb0305c..fdf2bc66a 100644 --- a/application/controllers/api/frontend/v1/stv/Status.php +++ b/application/controllers/api/frontend/v1/stv/Status.php @@ -731,15 +731,15 @@ class Status extends FHCAPI_Controller REST_Controller::HTTP_FORBIDDEN ); - $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($oldstatus->datum); + //TODO(Manu) check this check, meanwhile not active +/* $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($oldstatus->datum); - //TODO(Manu) comment out: should not appear during delete (shiva) if (!$this->getDataOrTerminateWithError($result)) $this->terminateWithError( $this->p->t('lehre', 'error_dataVorMeldestichtag'), self::ERROR_TYPE_GENERAL, REST_Controller::HTTP_FORBIDDEN - ); + );*/ } // Start DB transaction From f695d8b66a2437420e0e831d0a7d967dd61ba3ce Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Mon, 18 Aug 2025 10:21:18 +0200 Subject: [PATCH 067/388] update(Dashboard Widget Drag): shows hidden widget when dragging the widget on the dashboard --- public/js/components/Drop/Grid.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index d11e4c249..a7bea64e3 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -434,6 +434,8 @@ export default { clone.style.zIndex = 5; clone.classList.add("widgetClone"); this.$refs.container.appendChild(clone); + const hiddenWidget = clone.querySelector("[style='display: none;']"); + hiddenWidget.style.removeProperty("display"); this.clonedWidget = clone; }, 0); From eb8c3213dfb3628ba3a9cbd737ff463e1841b716 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Tue, 19 Aug 2025 07:37:33 +0200 Subject: [PATCH 068/388] - ects angabe bei der anmeldung - tablesorter hinzugefuegt - pruefungsort anderer raum moeglich (text) - pruefungsanmeldungen nur noch studiensemester dropdown - kompatible lvs vergleichen --- cis/private/lehre/pruefung/pruefung.js.php | 119 ++- .../pruefung/pruefungsanmeldung.json.php | 78 +- .../lehre/pruefung/pruefungsanmeldung.php | 14 + .../pruefung/pruefungsanmeldungen_liste.php | 10 +- .../pruefungsanmeldungen_liste_ohne_namen.php | 7 + .../pruefungsanmeldungen_verwalten.php | 59 +- config/global.config-default.inc.php | 3 + include/pruefungCis.class.php | 32 + include/pruefungsanmeldung.class.php | 12 +- include/pruefungstermin.class.php | 6 +- locale/de-AT/pruefung.php | 2 + locale/en-US/pruefung.php | 1 + system/dbupdate_3.4.php | 6 +- .../47972_pruefungsverwaltung_ects_angabe.php | 22 + ...hrveranstaltung_kompatibel_vergleichen.php | 682 ++++++++++++++++++ vilesci/lehre/studienordnung.js | 5 +- 16 files changed, 1006 insertions(+), 52 deletions(-) create mode 100644 system/dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php create mode 100644 vilesci/lehre/lehrveranstaltung_kompatibel_vergleichen.php diff --git a/cis/private/lehre/pruefung/pruefung.js.php b/cis/private/lehre/pruefung/pruefung.js.php index 4142e413c..f2fc2dc7e 100644 --- a/cis/private/lehre/pruefung/pruefung.js.php +++ b/cis/private/lehre/pruefung/pruefung.js.php @@ -382,7 +382,7 @@ function writePruefungsTable(e, data, anmeldung) } else if(new Date() > minimumFrist) { - button = "

"+frist+"'>

"; + button = "

"+frist+"'>

"; } } else @@ -479,13 +479,15 @@ function showPruefungsDetails(prfId, lvId) * @param {type} lvBezeichnung Bezeichnung der Lehrveranstaltung * @param {type} terminVon Beginn der Prüfung * @param {type} terminBis Ende der Prüfung + * @param {type} ects der LV * @returns {undefined} */ -function openDialog(lehrveranstaltung_id, termin_id, lvBezeichnung, terminVon, terminBis) +function openDialog(lehrveranstaltung_id, termin_id, lvBezeichnung, terminVon, terminBis, ects) { $("#lehrveranstaltungHidden").val(lehrveranstaltung_id); $("#terminHidden").val(termin_id); $("#lehrveranstaltung").html(lvBezeichnung); + $("#ectsangabe").val(ects); $.ajax({ dataType: 'json', @@ -582,6 +584,12 @@ function saveAnmeldung(lehrveranstaltung_id, termin_id) if($('#prestudent_studiengang').length) studiengang_kz = $('#prestudent_studiengang option:selected').val(); + var ects = null; + if ($('#ectsangabe').length) + { + ects = $('#ectsangabe').val(); + } + $.ajax({ dataType: 'json', url: "./pruefungsanmeldung.json.php", @@ -593,7 +601,8 @@ function saveAnmeldung(lehrveranstaltung_id, termin_id) bemerkung: bemerkungen, uid: uid, studienverpflichtung_id: studienverpflichtung_id, - studiengang_kz: studiengang_kz + studiengang_kz: studiengang_kz, + ects: ects }, error: loadError, success: function(data){ @@ -804,6 +813,7 @@ function writeAnmeldungen(data, showMessage = true) var pruefung_id = data.result.anmeldungen[0].pruefung_id; var lehrveranstaltung_id = data.result.anmeldungen[0].lehrveranstaltung_id; var ort_kurzbz = data.result.ort_kurzbz; + var anderer_raum = data.result.anderer_raum; var lv_bezeichnung = data.result.lv_bezeichnung; var lv_lehrtyp = data.result.lv_lehrtyp; var prf_termin = data.result.datum; @@ -816,24 +826,33 @@ function writeAnmeldungen(data, showMessage = true) count++; var vorname = d.student.vorname !== "null" ? d.student.vorname : ""; var nachname = d.student.nachname !== "null" ? d.student.nachname : ""; + + let ects = ""; + + ects = d.ects !== null ? "(" + d.ects + " ECTS) ": ""; + + + switch(d.status_kurzbz) { case 'angemeldet': - liste += "
  • "+vorname+" "+nachname+""; + liste += "
  • "+ects+vorname+" "+nachname+""; liste += "
    "+count+"
    ' onclick='anmeldungBestaetigen(\""+d.pruefungsanmeldung_id+"\", \""+terminId+"\", \""+lehrveranstaltung_id+"\");'>"; liste += "
    "; if(d.wuensche !== null) { - liste += ""; + let msg = $('
    ').text(d.wuensche).html(); + liste += `
    `; } liste += "
  • "; break; case 'bestaetigt': - liste += "
  • "+vorname+" "+nachname+""; + liste += "
  • "+ects+vorname+" "+nachname+""; liste += "
    "+count+"
    "; if(d.wuensche !== null) { - liste += ""; + let msg = $('
    ').text(d.wuensche).html(); + liste += `
    `; } break; @@ -848,9 +867,9 @@ function writeAnmeldungen(data, showMessage = true) $("#lvdaten").html(lv_bezeichnung+" ("+prf_termin+")"); $("#anmeldeDaten").html(liste); $("#listeDrucken").html(listenLinks); - if(ort_kurzbz !== null) + if(ort_kurzbz !== null || anderer_raum !== null) { - $("#raumLink").html("t('pruefung/pruefungsraum'); ?>"+ort_kurzbz); + $("#raumLink").html("t('pruefung/pruefungsraum'); ?>"+ (ort_kurzbz ?? anderer_raum)); } else { @@ -883,11 +902,17 @@ function writeAnmeldungen(data, showMessage = true) function openRaumDialog(terminId, lehrveranstaltung_id) { getRaeume(terminId); - $("#raum").html('

    t('pruefung/pruefungsraum'); ?>

    t('pruefung/imBuero'); ?>
    t('pruefung/raum'); ?>: '); + $("#raum").html('

    t('pruefung/pruefungsraum'); ?>

    t('pruefung/imBuero'); ?>
    t('pruefung/raum'); ?>:
    t('pruefung/andererRaum'); ?>
    '); $("#raumSpeichernButton").html("' onclick='saveRaum(\""+terminId+"\", \""+lehrveranstaltung_id+"\");'/>"); $("#raumDialog").dialog("open"); } +function openKommentarDialog(text) +{ + $('#kommentarimDialog').text(text); + $('#kommentarDialog').dialog('open'); +} + /** * speichert die Reihung der Studenten einer Prüfungsanmeldung * @param {type} terminId ID des Prüfungstermines @@ -1118,25 +1143,49 @@ function loadPruefungStudiengang(studiengang_kz, studiensemester) $("#pruefungenListe").empty(); if(data.result.length > 0) { - var liste = ""; - data.result.forEach(function(e){ - liste += "
    • "+e.bezeichnung+"
        "; - try + $('#table4').show() + let rows = ''; + + data.result.forEach(function(e) + { + let termine = e?.pruefung[0]?.termine || []; + + if (termine.length === 0) { - e.pruefung[0].termine.forEach(function(d){ - liste += "
      • "+convertDateTime(d.von)+" "+convertDateTime(d.von, "time")+" - "+convertDateTime(d.bis, "time")+"
      • "; + rows += ` + + + ${e.bezeichnung} + Keine Termine + `; + } + else + { + termine.forEach(function(d) { + let vonDate = convertDateTime(d.von); + let vonTime = convertDateTime(d.von, 'time'); + let bisTime = convertDateTime(d.bis, 'time'); + let onClick = `showAnmeldungen(${d.pruefungstermin_id}, ${e.lehrveranstaltung_id})`; + + rows += ` + + + ${e.studiengang} + ${e.bezeichnung} + ${vonDate} + ${vonTime} + ${bisTime} + t('pruefung/pruefungsbewertungAnmeldungen'); ?> + `; }); } - catch(err) - { - var errmsg = err.message; - } - liste += "
    "; }); - $("#pruefungenListe").append(liste); + $("#pruefungenListe").html(rows); + setTablesorter('table4') } else { + $('#table4').hide() $("#pruefungenListe").html("t('pruefung/keinePruefungenVorhanden'); ?>"); } } @@ -1241,6 +1290,7 @@ function loadStudiensemester() data.result.forEach(function(d){ selectData += ""; }); + $('#studiensemester').html(selectData); loadPruefungsfenster(); loadLehrveranstaltungen(); @@ -1540,7 +1590,7 @@ function loadPruefungsDetails(prfId) if(data.result.length === 0) { messageBox("message", "t('pruefung/keinePruefungsfensterGespeichert'); ?>", "red", "highlight", 10000); - $("#pruefungsfenster").html(""); + $("#pruefungsfenster").html(""); } else { @@ -2188,10 +2238,28 @@ function changeStateOfRaumDropdown() } } +function changeStateOfRaumInputs() +{ + if ($("#andererRaum").prop("checked") === true) + { + $("#raumInfos").hide(); + } + else + { + $("#raumInfos").show(); + } +} + function saveRaum(terminId, lehrveranstaltung_id) { var ort_kurzbz; - if($("#raum input[type=checkbox]").prop("checked") === true) + let anderer_raum = ''; + if ($("#andererRaum").prop("checked") === true && $('#andereRaumInput').val() !== '') + { + ort_kurzbz = ""; + anderer_raum = $('#andereRaumInput').val(); + } + else if($("#raum input[type=checkbox]").prop("checked") === true) { ort_kurzbz = "buero"; } @@ -2206,7 +2274,8 @@ function saveRaum(terminId, lehrveranstaltung_id) data: { method: "saveRaum", ort_kurzbz: ort_kurzbz, - terminId: terminId + terminId: terminId, + anderer_raum: anderer_raum }, error: loadError }).done(function(data){ diff --git a/cis/private/lehre/pruefung/pruefungsanmeldung.json.php b/cis/private/lehre/pruefung/pruefungsanmeldung.json.php index 6757cf391..54c064d14 100644 --- a/cis/private/lehre/pruefung/pruefungsanmeldung.json.php +++ b/cis/private/lehre/pruefung/pruefungsanmeldung.json.php @@ -108,7 +108,7 @@ switch($method) break; case 'getPruefungenStudiengang': $studiensemester = filter_input(INPUT_POST,"studiensemester"); - $data = getPruefungenStudiengang($uid, $studiensemester); + $data = getPruefungenStudiengangBySemester($studiensemester); break; case 'saveKommentar': $data = saveKommentar(); @@ -120,7 +120,8 @@ switch($method) case 'saveRaum': $terminId = $_REQUEST["terminId"]; $ort_kurzbz = $_REQUEST["ort_kurzbz"]; - $data = saveRaum($terminId, $ort_kurzbz, $uid); + $anderer_raum = $_REQUEST["anderer_raum"]; + $data = saveRaum($terminId, $ort_kurzbz, $uid, $anderer_raum); break; case 'getLvKompatibel': $lvid = filter_input(INPUT_POST, "lehrveranstaltung_id"); @@ -397,6 +398,7 @@ function saveAnmeldung($aktStudiensemester = null, $uid = null) $lv_besucht = false; $studienverpflichtung_id = filter_input(INPUT_POST, "studienverpflichtung_id"); $studiengang_kz = filter_input(INPUT_POST, "studiengang_kz"); + $ects = filter_input(INPUT_POST, "ects"); //Defaulteinstellung für Anzahlprüfungsversuche (wird durch Addon "ktu" überschrieben) $maxAnzahlVersuche = 0; @@ -731,6 +733,10 @@ function saveAnmeldung($aktStudiensemester = null, $uid = null) else $anmeldung->anrechnung_id = $anrechnung->anrechnung_id; + if (defined('CIS_PRUEFUNGSANMELDUNG_ECTS_ANGABE') && (CIS_PRUEFUNGSANMELDUNG_ECTS_ANGABE === true)) + { + $anmeldung->ects = $ects; + } if($anmeldung->save(true)) { $pruefung = new pruefungCis($termin->pruefung_id); @@ -1166,6 +1172,53 @@ function getPruefungenStudiengang($uid, $aktStudiensemester) return $data; } +function getPruefungenStudiengangBySemester($aktStudiensemester) +{ + $result = array(); + $pruefungen = new pruefungCis(); + $pruefungen->getPruefungByStudiensemester($aktStudiensemester); + + if((!empty($pruefungen->lehrveranstaltungen))) + { + $lehrveranstaltungen = []; + foreach ($pruefungen->lehrveranstaltungen as $prf) + { + $pruefung = new pruefungCis(); + $pruefung->load($prf->pruefung_id); + + if ($pruefung->storniert) + continue; + + $pruefung->getTermineByPruefung(); + + $lvid = $prf->lehrveranstaltung_id; + + if (!isset($lehrveranstaltungen[$lvid])) + { + $lv = new stdClass(); + $lehrveranstaltung = new lehrveranstaltung(); + $lehrveranstaltung->load($lvid); + + $studiengang = new studiengang(); + $studiengang->load($lehrveranstaltung->studiengang_kz); + + $lv->bezeichnung = $lehrveranstaltung->bezeichnung; + $lv->lehrveranstaltung_id = $lvid; + $lv->studiengang = $studiengang->kuerzel; + $lv->pruefung = []; + $lehrveranstaltungen[$lvid] = $lv; + } + + $lehrveranstaltungen[$lvid]->pruefung[] = $pruefung; + } + $result = array_values($lehrveranstaltungen); + } + $data['result']=$result; + $data['error']='false'; + $data['errormsg']=''; + return $data; +} + /** * * @return typespeichert ein Kommentar zu einer Prüfungsanmeldung @@ -1246,7 +1299,7 @@ function compareRaeume($a, $b) return strcmp($a->ort_kurzbz, $b->ort_kurzbz); } -function saveRaum($terminId, $ort_kurzbz, $uid) +function saveRaum($terminId, $ort_kurzbz, $uid, $anderer_raum = '') { $terminkollision = defined('CIS_PRUEFUNGSANMELDUNG_ERLAUBE_TERMINKOLLISION') ? CIS_PRUEFUNGSANMELDUNG_ERLAUBE_TERMINKOLLISION : false; $pruefungstermin = new pruefungstermin($terminId); @@ -1265,7 +1318,24 @@ function saveRaum($terminId, $ort_kurzbz, $uid) { $pruefung = new pruefungCis($pruefungstermin->pruefung_id); $mitarbeiter = new mitarbeiter($pruefung->mitarbeiter_uid); - if($ort_kurzbz === "buero") + + if ($ort_kurzbz === "" && $anderer_raum !== "") + { + $pruefungstermin->anderer_raum = $anderer_raum; + + if($pruefungstermin->save(false)) + { + $data['result']="reserviert"; + $data['error']='false'; + $data['errormsg']=''; + } + else + { + $data['error']='true'; + $data['errormsg']=$pruefungstermin->errormsg; + } + } + else if($ort_kurzbz === "buero") { $pruefungstermin->ort_kurzbz = $mitarbeiter->ort_kurzbz; if($pruefungstermin->save(false)) diff --git a/cis/private/lehre/pruefung/pruefungsanmeldung.php b/cis/private/lehre/pruefung/pruefungsanmeldung.php index c969c51aa..837e0c227 100644 --- a/cis/private/lehre/pruefung/pruefungsanmeldung.php +++ b/cis/private/lehre/pruefung/pruefungsanmeldung.php @@ -321,6 +321,20 @@ $studiensemester->getAll(); + + + + + t('pruefung/ects'); ?>: + + + + + + diff --git a/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php b/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php index 39ec68ad4..91c2ea084 100644 --- a/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php +++ b/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php @@ -235,12 +235,18 @@ $rechte->getBerechtigungen($uid); t('global/datum'); ?> t('benotungstool/note'); ?> t('global/anmerkung'); ?> + + + t('pruefung/ects'); ?> + + uid); @@ -269,6 +275,8 @@ $rechte->getBerechtigungen($uid); echo ''.$date.''; echo ''; echo ''; + if (defined('CIS_PRUEFUNGSANMELDUNG_ECTS_ANGABE') && (CIS_PRUEFUNGSANMELDUNG_ECTS_ANGABE === true)) + echo ''. $anmeldung->ects .''; echo ''; } ?> diff --git a/cis/private/lehre/pruefung/pruefungsanmeldungen_liste_ohne_namen.php b/cis/private/lehre/pruefung/pruefungsanmeldungen_liste_ohne_namen.php index 207ba4dd7..414ebdf15 100644 --- a/cis/private/lehre/pruefung/pruefungsanmeldungen_liste_ohne_namen.php +++ b/cis/private/lehre/pruefung/pruefungsanmeldungen_liste_ohne_namen.php @@ -233,6 +233,11 @@ $rechte->getBerechtigungen($uid); t('global/datum'); ?> t('benotungstool/note'); ?> t('global/anmerkung'); ?> + + t('pruefung/ects'); ?> + @@ -265,6 +270,8 @@ $rechte->getBerechtigungen($uid); echo ''.$date.''; echo ''; echo ''; + if (defined('CIS_PRUEFUNGSANMELDUNG_ECTS_ANGABE') && (CIS_PRUEFUNGSANMELDUNG_ECTS_ANGABE === true)) + echo ''. $anmeldung->ects .''; echo ''; } ?> diff --git a/cis/private/lehre/pruefung/pruefungsanmeldungen_verwalten.php b/cis/private/lehre/pruefung/pruefungsanmeldungen_verwalten.php index 22bca21cc..dd38950b1 100644 --- a/cis/private/lehre/pruefung/pruefungsanmeldungen_verwalten.php +++ b/cis/private/lehre/pruefung/pruefungsanmeldungen_verwalten.php @@ -95,7 +95,7 @@ if (empty($pruefung->result) && !$rechte->isBerechtigt('lehre/pruefungsanmeldung #prfWrapper { position: absolute; height: 70%; - width: 300px; + width: 40%; top: 180px; padding: 1.8em 1.5em 1.8em 1em; /*border-radius: 25px;*/ @@ -117,9 +117,9 @@ if (empty($pruefung->result) && !$rechte->isBerechtigt('lehre/pruefungsanmeldung #anmWrapper { position: absolute; /*top: 45px;*/ - left: 350px; + left: 45%; top: 180px; - width: 500px; + width: 40%; height: 70%; padding: 1.8em 1.5em 1.8em 1em; /*border-radius: 25px;*/ @@ -228,7 +228,6 @@ if (empty($pruefung->result) && !$rechte->isBerechtigt('lehre/pruefungsanmeldung

    t('pruefung/anmeldungenVerwalten'); ?>

    -
    -
    -

    t('global/studiengang'); ?>

    -
    -
    -

    t('global/studiensemester'); ?>

    result) && !$rechte->isBerechtigt('lehre/pruefungsanmeldung $studiensemester->getPlusMinus(null, 5); foreach($studiensemester->studiensemester as $sem) { - /*@var $sem studiensemester */ if ($aktuellesSemester == $sem->studiensemester_kurzbz) { echo ''; @@ -273,9 +290,20 @@ if (empty($pruefung->result) && !$rechte->isBerechtigt('lehre/pruefungsanmeldung

    t('pruefung/pruefungPruefungenTitle'); ?>

    -
      - -
    + + + + + + + + + + + + + +
    @@ -311,6 +339,9 @@ if (empty($pruefung->result) && !$rechte->isBerechtigt('lehre/pruefungsanmeldung
    +
    diff --git a/config/global.config-default.inc.php b/config/global.config-default.inc.php index 8cfc36bfb..89b02a8ce 100644 --- a/config/global.config-default.inc.php +++ b/config/global.config-default.inc.php @@ -263,6 +263,9 @@ define('CIS_SAALPLAN_ALLERAEUME_OPTION', false); //Legt fest ob Bestätigungsmails über eine Anmelung zu einer Prüfung an eine einzelne Person erfolgt oder an den jeweiligen Lektor. (Leerstring für jeweiligen Lektor | uid); define('CIS_PRUEFUNG_MAIL_EMPFAENGER_ANMEDLUNG',""); +//Gibt an, ob die Studierenden bei der Anmeldung zu einer Prüfung den Ausmas an ECTS angeben können +define('CIS_PRUEFUNGSANMELDUNG_ECTS_ANGABE', false); + // Username fuer STIP Schnittstelle define('STIP_USER_NAME','stipendienstelle'); // Passwort fuer STIP Schnittstelle diff --git a/include/pruefungCis.class.php b/include/pruefungCis.class.php index ec402ed5d..29b0c425d 100644 --- a/include/pruefungCis.class.php +++ b/include/pruefungCis.class.php @@ -464,6 +464,7 @@ class pruefungCis extends basis_db $obj->anmeldung_von= $row->anmeldung_von; $obj->anmeldung_bis = $row->anmeldung_bis; $obj->ort_kurzbz = $row->ort_kurzbz; + $obj->anderer_raum = $row->anderer_raum; $obj->sammelklausur = $row->sammelklausur; array_push($this->termine, $obj); } @@ -646,6 +647,37 @@ class pruefungCis extends basis_db return false; } + public function getPruefungByStudiensemester($studiensemester_kurzbz) + { + if(empty($studiensemester_kurzbz)) + { + $this->errormsg = "Kein Studiensemester übergeben.
    "; + return false; + } + + $qry = 'SELECT * + FROM campus.tbl_lehrveranstaltung_pruefung + JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN campus.tbl_pruefung USING (pruefung_id) + WHERE tbl_pruefung.studiensemester_kurzbz = ' . $this->db_add_param($studiensemester_kurzbz); + + if($this->db_query($qry)) + { + while($row = $this->db_fetch_object()) + { + $obj = new stdClass(); + $obj->lehrveranstaltung_pruefung_id = $row->lehrveranstaltung_pruefung_id; + $obj->lehrveranstaltung_id = $row->lehrveranstaltung_id; + $obj->pruefung_id = $row->pruefung_id; + $obj->storniert = $row->storniert; + $obj->bezeichnung = $row->bezeichnung; + array_push($this->lehrveranstaltungen, $obj); + } + return true; + } + return false; + } + /** * Lädt alle Prüfung-Lehrveranstaltung Kombinationen * @return boolean true, wenn ok; false, im Fehlerfall diff --git a/include/pruefungsanmeldung.class.php b/include/pruefungsanmeldung.class.php index e4fbec506..c23b0212b 100644 --- a/include/pruefungsanmeldung.class.php +++ b/include/pruefungsanmeldung.class.php @@ -39,6 +39,7 @@ class pruefungsanmeldung extends basis_db { public $statusupdatevon; //varchar(32) public $statusupdateamum; //timestamp public $anrechnung_id; //integer + public $ects; //integer public $pruefungstyp_kurzbz; //varchar(32) public $insertamum; // timestamp @@ -94,7 +95,7 @@ class pruefungsanmeldung extends basis_db { if($new) { - $qry = 'INSERT INTO campus.tbl_pruefungsanmeldung (uid, pruefungstermin_id, lehrveranstaltung_id, status_kurzbz, wuensche, reihung, kommentar, anrechnung_id, pruefungstyp_kurzbz) VALUES (' + $qry = 'INSERT INTO campus.tbl_pruefungsanmeldung (uid, pruefungstermin_id, lehrveranstaltung_id, status_kurzbz, wuensche, reihung, kommentar, anrechnung_id, pruefungstyp_kurzbz, ects) VALUES (' . $this->db_add_param($this->uid).', ' . $this->db_add_param($this->pruefungstermin_id).', ' . $this->db_add_param($this->lehrveranstaltung_id).', ' @@ -103,7 +104,8 @@ class pruefungsanmeldung extends basis_db { . $this->db_add_param($this->reihung).', ' . $this->db_add_param($this->kommentar).', ' . $this->db_add_param($this->anrechnung_id).', ' - . $this->db_add_param($this->pruefungstyp_kurzbz).');'; + . $this->db_add_param($this->pruefungstyp_kurzbz).', ' + . $this->db_add_param($this->ects).');'; } else { @@ -116,7 +118,8 @@ class pruefungsanmeldung extends basis_db { . 'reihung='.$this->db_add_param($this->reihung).', ' . 'kommentar='.$this->db_add_param($this->kommentar).', ' . 'anrechnung_id='.$this->db_add_param($this->anrechnung_id).', ' - . 'pruefungstyp_kurzbz='.$this->db_add_param($this->pruefungstyp_kurzbz) + . 'pruefungstyp_kurzbz='.$this->db_add_param($this->pruefungstyp_kurzbz).', ' + . 'ects='.$this->db_add_param($this->ects) . ' WHERE pruefungsanmeldung_id='.$this->db_add_param($this->pruefungsanmeldung_id).';'; } @@ -167,6 +170,7 @@ class pruefungsanmeldung extends basis_db { $this->statusupdatevon = $row->statusupdatevon; $this->anrechnung_id = $row->anrechnung_id; $this->pruefungstyp_kurzbz = $row->pruefungstyp_kurzbz; + $this->ects = $row->ects; $this->insertamum = $row->insertamum; } return true; @@ -221,6 +225,7 @@ class pruefungsanmeldung extends basis_db { $anmeldung->statusupdatevon = $row->statusupdatevon; $anmeldung->anrechnung_id = $row->anrechnung_id; $anmeldung->pruefungstyp_kurzbz = $row->pruefungstyp_kurzbz; + $anmeldung->ects = $row->ects; array_push($anmeldungen, $anmeldung); } return $anmeldungen; @@ -280,6 +285,7 @@ class pruefungsanmeldung extends basis_db { $anmeldung->statusupdatevon = $row->statusupdatevon; $anmeldung->anrechnung_id = $row->anrechnung_id; $anmeldung->pruefungstyp_kurzbz = $row->pruefungstyp_kurzbz; + $anmeldung->ects = $row->ects; $anmeldung->datum_anmeldung = $row->datum_anmeldung; array_push($anmeldungen, $anmeldung); } diff --git a/include/pruefungstermin.class.php b/include/pruefungstermin.class.php index 74222cceb..c7eb0b085 100644 --- a/include/pruefungstermin.class.php +++ b/include/pruefungstermin.class.php @@ -37,6 +37,7 @@ class pruefungstermin extends basis_db{ public $anmeldung_von; //date public $anmeldung_bis; //date public $ort_kurzbz; //varchar(16) + public $anderer_raum; //text public $sammelklausur; //boolean /** @@ -93,6 +94,7 @@ class pruefungstermin extends basis_db{ $this->anmeldung_von= $row->anmeldung_von; $this->anmeldung_bis = $row->anmeldung_bis; $this->ort_kurzbz = $row->ort_kurzbz; + $this->anderer_raum = $row->anderer_raum; $this->sammelklausur = $row->sammelklausur; } return true; @@ -179,7 +181,8 @@ class pruefungstermin extends basis_db{ . 'teilnehmer_min='.$this->db_add_param($this->teilnehmer_min).', ' . 'anmeldung_von='.$this->db_add_param($this->anmeldung_von).', ' . 'anmeldung_bis='.$this->db_add_param($this->anmeldung_bis).', ' - . 'ort_kurzbz='.$this->db_add_param($this->ort_kurzbz).' ' + . 'ort_kurzbz='.$this->db_add_param($this->ort_kurzbz).', ' + . 'anderer_raum='.$this->db_add_param($this->anderer_raum).' ' . 'WHERE pruefungstermin_id='.$this->db_add_param($this->pruefungstermin_id).';'; } @@ -228,6 +231,7 @@ class pruefungstermin extends basis_db{ $obj->anmeldung_von= $row->anmeldung_von; $obj->anmeldung_bis = $row->anmeldung_bis; $obj->ort_kurzbz = $row->ort_kurzbz; + $obj->anderer_raum = $row->anderer_raum; $obj->sammelklausur = $row->sammelklausur; array_push($this->result, $obj); } diff --git a/locale/de-AT/pruefung.php b/locale/de-AT/pruefung.php index 93b7039e0..9e75fa89e 100644 --- a/locale/de-AT/pruefung.php +++ b/locale/de-AT/pruefung.php @@ -57,6 +57,7 @@ $this->phrasen['pruefung/listeOhneNamenDrucken'] = 'Liste ohne Namen drucken'; $this->phrasen['pruefung/pruefungsraum'] = 'Prüfungsraum: '; $this->phrasen['pruefung/pruefungsort'] = 'Prüfungsort '; $this->phrasen['pruefung/imBuero'] = ' im Büro'; +$this->phrasen['pruefung/andererRaum'] = 'anderer Raum'; $this->phrasen['pruefung/raum'] = ' Raum'; $this->phrasen['pruefung/raumSpeichern'] = ' Raum speichern'; $this->phrasen['pruefung/reihunghErfolgreichGeaendert'] = 'Reihung erfolgreich geändert.'; @@ -95,6 +96,7 @@ $this->phrasen['pruefung/lvVonStudiengang'] = 'Lehrveranstaltungen von Studienga $this->phrasen['pruefung/lvAlle'] = 'Alle Lehrveranstaltungen'; $this->phrasen['pruefung/anmeldungSpeichern'] = 'Anmeldung speichern'; $this->phrasen['pruefung/studienverpflichtung'] = 'Studienverpflichtung'; +$this->phrasen['pruefung/ects'] = 'ECTS'; // liste $this->phrasen['pruefung/anmeldungsliste'] = 'Anmeldungsliste'; diff --git a/locale/en-US/pruefung.php b/locale/en-US/pruefung.php index cd5175c13..7b0cec97e 100644 --- a/locale/en-US/pruefung.php +++ b/locale/en-US/pruefung.php @@ -57,6 +57,7 @@ $this->phrasen['pruefung/listeOhneNamenDrucken'] = 'Liste ohne Namen drucken'; $this->phrasen['pruefung/pruefungsraum'] = 'Prüfungsraum: '; $this->phrasen['pruefung/pruefungsort'] = 'Prüfungsort '; $this->phrasen['pruefung/imBuero'] = ' im Büro'; +$this->phrasen['pruefung/andererRaum'] = 'other Room'; $this->phrasen['pruefung/raum'] = ' Raum'; $this->phrasen['pruefung/raumSpeichern'] = ' Raum speichern'; $this->phrasen['pruefung/reihunghErfolgreichGeaendert'] = 'Reihung erfolgreich geändert.'; diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index cf2f40ca8..3a743f065 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -77,6 +77,8 @@ require_once('dbupdate_3.4/55614_perm_verwaltetoe.php'); require_once('dbupdate_3.4/25999_C4_dashboard.php'); require_once('dbupdate_3.4/61730_Dashboard_Anpassungen.php'); require_once('dbupdate_3.4/40128_search.php'); +require_once('dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php'); +require_once('dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php'); // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

    Pruefe Tabellen und Attribute!

    '; @@ -159,8 +161,8 @@ $tabellen=array( "campus.tbl_paabgabe" => array("paabgabe_id","projektarbeit_id","paabgabetyp_kurzbz","fixtermin","datum","kurzbz","abgabedatum", "insertvon","insertamum","updatevon","updateamum"), "campus.tbl_pruefungsfenster" => array("pruefungsfenster_id","studiensemester_kurzbz","oe_kurzbz","start","ende"), "campus.tbl_pruefung" => array("pruefung_id","mitarbeiter_uid","studiensemester_kurzbz","pruefungsfenster_id","pruefungstyp_kurzbz","titel","beschreibung","methode","einzeln","storniert","insertvon","insertamum","updatevon","updateamum","pruefungsintervall"), - "campus.tbl_pruefungstermin" => array("pruefungstermin_id","pruefung_id","von","bis","teilnehmer_max","teilnehmer_min","anmeldung_von","anmeldung_bis","ort_kurzbz","sammelklausur"), - "campus.tbl_pruefungsanmeldung" => array("pruefungsanmeldung_id","uid","pruefungstermin_id","lehrveranstaltung_id","status_kurzbz","wuensche","reihung","kommentar","statusupdatevon","statusupdateamum","anrechnung_id","pruefungstyp_kurzbz","insertamum"), + "campus.tbl_pruefungstermin" => array("pruefungstermin_id","pruefung_id","von","bis","teilnehmer_max","teilnehmer_min","anmeldung_von","anmeldung_bis","ort_kurzbz","sammelklausur", "anderer_raum"), + "campus.tbl_pruefungsanmeldung" => array("pruefungsanmeldung_id","uid","pruefungstermin_id","lehrveranstaltung_id","status_kurzbz","wuensche","reihung","kommentar","statusupdatevon","statusupdateamum","anrechnung_id","pruefungstyp_kurzbz","insertamum", "ects"), "campus.tbl_pruefungsstatus" => array("status_kurzbz","bezeichnung"), "campus.tbl_reservierung" => array("reservierung_id","ort_kurzbz","studiengang_kz","uid","stunde","datum","titel","beschreibung","semester","verband","gruppe","gruppe_kurzbz","veranstaltung_id","insertamum","insertvon"), "campus.tbl_studierendenantrag" => array("studierendenantrag_id","prestudent_id","studiensemester_kurzbz","datum","typ","insertamum","insertvon","datum_wiedereinstieg","grund","dms_id"), diff --git a/system/dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php b/system/dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php new file mode 100644 index 000000000..7b961fa3d --- /dev/null +++ b/system/dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php @@ -0,0 +1,22 @@ +db_query("SELECT ects FROM campus.tbl_pruefungsanmeldung LIMIT 1")) +{ + $qry = 'ALTER TABLE campus.tbl_pruefungsanmeldung ADD COLUMN ects numeric(5,2);'; + + if(!$db->db_query($qry)) + echo ' campus.tbl_pruefungsanmeldung '.$db->db_last_error().'
    '; + else + echo '
    campus.tbl_pruefungsanmeldung: Neue Spalte ects hinzugefügt'; +} + +if(!@$db->db_query("SELECT anderer_raum FROM campus.tbl_pruefungstermin LIMIT 1")) +{ + $qry = 'ALTER TABLE campus.tbl_pruefungstermin ADD COLUMN anderer_raum text NULL;'; + + if(!$db->db_query($qry)) + echo ' campus.tbl_pruefungstermin '.$db->db_last_error().'
    '; + else + echo '
    campus.tbl_pruefungstermin: Neue Spalte anderer_raum hinzugefügt'; +} diff --git a/vilesci/lehre/lehrveranstaltung_kompatibel_vergleichen.php b/vilesci/lehre/lehrveranstaltung_kompatibel_vergleichen.php new file mode 100644 index 000000000..94e1af155 --- /dev/null +++ b/vilesci/lehre/lehrveranstaltung_kompatibel_vergleichen.php @@ -0,0 +1,682 @@ +load($_POST['lv_id']); + + $kompatibleLvs = $lv->loadLVkompatibel($_POST['lv_id']); + if (is_array($kompatibleLvs) && count($kompatibleLvs) > 0) + { + $result = array(); + foreach($kompatibleLvs as $lvId) + { + $lv->load($lvId); + $studiengang = new studiengang(); + $studiengang->load($lv->studiengang_kz); + $oe = new organisationseinheit(); + $oe->load($lv->oe_kurzbz); + + + $result[] = array( + "lehrveranstaltung_id" => $lv->lehrveranstaltung_id, + "kurzbz" => $lv->kurzbz, + "bezeichnung" => $lv->bezeichnung, + "ects" => $lv->ects, + "studiengang_kuerzel" => $studiengang->kuerzel, + "oe_bezeichnung" => $oe->bezeichnung + ); + } + echo json_encode(["result" => $result]); + exit(); + } + echo json_encode(["result" => array()]); + exit(); + } +} + +if (isset($_REQUEST['autocomplete']) && ($_REQUEST['autocomplete'] === 'From' || $_REQUEST['autocomplete'] === 'To')) +{ + $search = trim((isset($_REQUEST['term']) ? $_REQUEST['term'] : '')); + if (is_null($search) || $search == '') + { + exit(); + } + + $qry = "SELECT lehre.tbl_lehrveranstaltung.* + FROM lehre.tbl_lehrveranstaltung + WHERE + lower(bezeichnung) like '%" . $db->db_escape(mb_strtolower($search)) . "%' OR + lehrveranstaltung_id::text like '%" . $db->db_escape(mb_strtolower($search)) . "%' OR + studiengang_kz::text like '%" . $db->db_escape(mb_strtolower($search)) . "%' + ORDER BY lehrveranstaltung_id DESC + LIMIT 10 + "; + + if ($result = $db->db_query($qry)) + { + $result_obj = array(); + while ($row = $db->db_fetch_object($result)) + { + $item['lehrveranstaltung_id'] = html_entity_decode($row->lehrveranstaltung_id); + $item['bezeichnung'] = html_entity_decode($row->bezeichnung); + $item['oe_kurzbz'] = html_entity_decode($row->oe_kurzbz); + $result_obj[] = $item; + } + echo json_encode($result_obj); + } + exit(); +} +?> + + + Lehrveranstaltung Verwaltung + + + + + + + + + + + + + + +getBerechtigungen($user); + +if(!$rechte->isBerechtigt('lehre/lehrveranstaltung', 'suid')) + die('Sie haben keine Berechtigung fuer diese Seite'); + +$studiengang = new studiengang(); +$studiengang->getAll("kurzbzlang"); + +$organisationseinheit = new organisationseinheit(); +$organisationseinheit->getAll(true, true); + +echo "
    +
    +
    + + + + + + + + + "; + echo " + + + + + + + + + + +
    Suche: + +
    Studiengang: + + OE: +
    Semester: + +
    Lehrveranstaltungen: + +
    +
    + Kompatible Lehrveranstaltungen - + + + + + + + + + + + + + + + + +
    IDKurzbezeichnungBezeichnungECTSStudiengangOrganisationseiheitÜbernehmen?Löschen?
    + + + +
    +
    +
    + + + + + + + + + + "; + echo " + + + + + + + + + + +
    Suche: + +
    Studiengang: + + OE: +
    Semester: + +
    Lehrveranstaltungen: + +
    +
    + Kompatible Lehrveranstaltungen - + + + + + + + + + + + + + + +
    IDKurzbezeichnungBezeichnungECTSStudiengangOrganisationseiheitLöschen?
    +
    +"; + + +echo " + "; + +?> diff --git a/vilesci/lehre/studienordnung.js b/vilesci/lehre/studienordnung.js index 54fa9e81b..bf7ff34e7 100644 --- a/vilesci/lehre/studienordnung.js +++ b/vilesci/lehre/studienordnung.js @@ -695,15 +695,16 @@ function loadLVKompatibilitaet(lvid) }).success(function(data) { var html=''; + html = html+'kompatible Lehrveranstaltungen vergleichen

    '; + html = html+'kompatible Lehrveranstaltungen hinzufügen
    '; for(i in data.result) { if(data.result[i]) { lvdata = data.result[i]; if(!(lvdata.kurzbz===null && lvdata.bezeichnung===null && lvdata.studiengang_kz===null && lvdata.semester===null)) - html = html+'
    '+lvdata.kurzbz+' - '+lvdata.bezeichnung+' (Studiengang '+lvdata.studiengang_kz+', Semester '+lvdata.semester+')'; + html = html+'
    '+lvdata.kurzbz+' - '+lvdata.bezeichnung+' (Studiengang '+lvdata.studiengang_kz+', Semester '+lvdata.semester+')
    '; } - html = html+'

    kompatible Lehrveranstaltungen hinzufügen'; } $("#tab-kompatibel").html(html); From ca3f8bc554a71c5ebd66f61ec1750b6a821b0b15 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Tue, 19 Aug 2025 11:24:51 +0200 Subject: [PATCH 069/388] move statusofsemester select into shared function --- .../api/frontend/v1/stv/Students.php | 72 ++++--------------- 1 file changed, 12 insertions(+), 60 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 26b5000bb..4bd449715 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -334,18 +334,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect("'' AS gruppe"); $this->addSelectPrioRel(); - //add status per semester - $this->PrestudentModel->addSelect( - "( - SELECT status_kurzbz - FROM public.tbl_prestudentstatus pss - WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id - AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " - ORDER BY GREATEST(pss.datum, '0001-01-01') DESC - LIMIT 1 - ) AS statusofsemester" - ); - $this->addFilter($studiensemester_kurzbz); $result = $this->PrestudentModel->loadWhere($where); @@ -462,18 +450,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect('v.gruppe'); $this->PrestudentModel->addSelect("'' AS priorisierung_relativ"); - //add status per semester - $this->PrestudentModel->addSelect( - "( - SELECT status_kurzbz - FROM public.tbl_prestudentstatus pss - WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id - AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " - ORDER BY GREATEST(pss.datum, '0001-01-01') DESC - LIMIT 1 - ) AS statusofsemester" - ); - $where = []; @@ -562,18 +538,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect('v.verband'); $this->PrestudentModel->addSelect('v.gruppe'); - //add status per semester - $this->PrestudentModel->addSelect( - "( - SELECT status_kurzbz - FROM public.tbl_prestudentstatus pss - WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id - AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " - ORDER BY GREATEST(pss.datum, '0001-01-01') DESC - LIMIT 1 - ) AS statusofsemester" - ); - $this->addSelectPrioRel(); $this->addFilter($studiensemester_kurzbz); @@ -631,18 +595,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect('v.verband'); $this->PrestudentModel->addSelect('v.gruppe'); - //add status per semester - $this->PrestudentModel->addSelect( - "( - SELECT status_kurzbz - FROM public.tbl_prestudentstatus pss - WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id - AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " - ORDER BY GREATEST(pss.datum, '0001-01-01') DESC - LIMIT 1 - ) AS statusofsemester" - ); - $this->addSelectPrioRel(); @@ -696,18 +648,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect('v.verband'); $this->PrestudentModel->addSelect('v.gruppe'); - //add status per semester - $this->PrestudentModel->addSelect( - "( - SELECT status_kurzbz - FROM public.tbl_prestudentstatus pss - WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id - AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " - ORDER BY GREATEST(pss.datum, '0001-01-01') DESC - LIMIT 1 - ) AS statusofsemester" - ); - $this->addSelectPrioRel(); $this->addFilter($studiensemester_kurzbz); @@ -772,6 +712,18 @@ class Students extends FHCAPI_Controller // verband // gruppe + //add status per semester + $this->PrestudentModel->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + $this->PrestudentModel->addSelect('UPPER(stg.typ || stg.kurzbz) AS studiengang'); $this->PrestudentModel->addSelect('tbl_prestudent.studiengang_kz'); $this->PrestudentModel->addSelect('stg.bezeichnung AS stg_bezeichnung'); From 6ee3f1d241a2f9f4360dfcfe8cb4ed892e0069d2 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 20 Aug 2025 11:32:31 +0200 Subject: [PATCH 070/388] show Bezeichnung in Subject Vorlage, add adaption for Tinymce for openMode inSamePage --- .../api/frontend/v1/messages/Messages.php | 18 ++++------ public/js/api/factory/messages/messages.js | 4 +-- public/js/api/messages/person.js | 4 +-- .../Messages/Details/NewMessage/Modal.js | 19 ++++------- .../Messages/Details/NewMessage/NewDiv.js | 34 ++++++------------- 5 files changed, 28 insertions(+), 51 deletions(-) diff --git a/application/controllers/api/frontend/v1/messages/Messages.php b/application/controllers/api/frontend/v1/messages/Messages.php index fa6748f6a..6ca1c74c0 100644 --- a/application/controllers/api/frontend/v1/messages/Messages.php +++ b/application/controllers/api/frontend/v1/messages/Messages.php @@ -16,7 +16,7 @@ class Messages extends FHCAPI_Controller 'getNameOfDefaultRecipient' => ['admin:r', 'assistenz:r'], 'sendMessage' => ['admin:r', 'assistenz:r'], 'deleteMessage' => ['admin:r', 'assistenz:r'], - 'getVorlagentext' => ['admin:r', 'assistenz:r'], + 'getDataVorlage' => ['admin:r', 'assistenz:r'], 'getPreviewText' => ['admin:r', 'assistenz:r'], 'getReplyData' => ['admin:r', 'assistenz:r'], 'getPersonId' => ['admin:r', 'assistenz:r'], @@ -89,10 +89,8 @@ class Messages extends FHCAPI_Controller $this->terminateWithSuccess($data); } - public function getVorlagentext($vorlage_kurzbz) + public function getDataVorlage($vorlage_kurzbz) { - //$this->terminateWithError("vor " . $vorlage_kurzbz, self::ERROR_TYPE_GENERAL); - //$studiengang_kz = 227; //TODO(Manu) dynamisieren NULL $studiengang_kz = 0; $this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); $this->VorlagestudiengangModel->addOrder('version', 'DESC'); @@ -104,12 +102,8 @@ class Messages extends FHCAPI_Controller ]); $data = $this->getDataOrTerminateWithError($result); - - //not correct with Vorlage $vorlage = current($data); - - //$this->terminateWithSuccess($data); - $this->terminateWithSuccess($vorlage->text); + $this->terminateWithSuccess($vorlage); } public function getMessageVarsPerson($id, $typeId) @@ -154,7 +148,7 @@ class Messages extends FHCAPI_Controller public function sendMessage($recipient_id) { //has to be uid - // $this->terminateWithError("uid", $recipient_id, self::ERROR_TYPE_GENERAL); + // $this->terminateWithError("uid", $recipient_id, self::ERROR_TYPE_GENERAL); //default setting $receiversPersonId = $this->_getPersonId($recipient_id, 'uid'); @@ -223,7 +217,7 @@ class Messages extends FHCAPI_Controller } elseif($typeId == 'prestudent_id') { - // $this->terminateWithError("prestudent_id ", self::ERROR_TYPE_GENERAL); + // $this->terminateWithError("prestudent_id ", self::ERROR_TYPE_GENERAL); $result = $this->MessagesModel->parseMessageTextPrestudent($id, $body); $bodyParsed = $this->getDataOrTerminateWithError($result); @@ -429,7 +423,7 @@ class Messages extends FHCAPI_Controller private function _getPrestudentIdFromUid($uid) { - // $this->terminateWithError($uid, self::ERROR_TYPE_GENERAL); + // $this->terminateWithError($uid, self::ERROR_TYPE_GENERAL); $this->load->model('crm/Student_model', 'StudentModel'); $result = $this->StudentModel->loadWhere( ['student_uid' => $uid] diff --git a/public/js/api/factory/messages/messages.js b/public/js/api/factory/messages/messages.js index cec34ad8b..c6d4b67b6 100644 --- a/public/js/api/factory/messages/messages.js +++ b/public/js/api/factory/messages/messages.js @@ -62,10 +62,10 @@ export default { url: 'api/frontend/v1/messages/messages/getUid/' + userParams.id + '/' + userParams.type_id }; }, - getVorlagentext(vorlage_kurzbz){ + getDataVorlage(vorlage_kurzbz){ return { method: 'get', - url: 'api/frontend/v1/messages/messages/getVorlagentext/' + vorlage_kurzbz + url: 'api/frontend/v1/messages/messages/getDataVorlage/' + vorlage_kurzbz }; }, getNameOfDefaultRecipient(params){ diff --git a/public/js/api/messages/person.js b/public/js/api/messages/person.js index e2d2fd0c4..19b3603e2 100644 --- a/public/js/api/messages/person.js +++ b/public/js/api/messages/person.js @@ -20,8 +20,8 @@ export default { getUid(params){ return this.$fhcApi.get('api/frontend/v1/messages/messages/getUid/'+ params.id + '/' + params.type_id); }, - getVorlagentext(vorlage_kurzbz){ - return this.$fhcApi.get('api/frontend/v1/messages/messages/getVorlagentext/' + vorlage_kurzbz); + getDataVorlage(vorlage_kurzbz){ + return this.$fhcApi.get('api/frontend/v1/messages/messages/getDataVorlage/' + vorlage_kurzbz); }, getNameOfDefaultRecipient(params){ return this.$fhcApi.get('api/frontend/v1/messages/messages/getNameOfDefaultRecipient/' + params.id + '/' + params.type_id); diff --git a/public/js/components/Messages/Details/NewMessage/Modal.js b/public/js/components/Messages/Details/NewMessage/Modal.js index b0d8cca7d..ce9235617 100644 --- a/public/js/components/Messages/Details/NewMessage/Modal.js +++ b/public/js/components/Messages/Details/NewMessage/Modal.js @@ -136,17 +136,13 @@ export default { } ); }, - getVorlagentext(vorlage_kurzbz){ + getDataVorlage(vorlage_kurzbz){ return this.$api - .call(this.endpoint.getVorlagentext(vorlage_kurzbz)) + .call(this.endpoint.getDataVorlage(vorlage_kurzbz)) .then(response => { - this.formData.body = response.data; - }).catch(this.$fhcAlert.handleSystemError) - .finally(() => { - //this.resetForm(); - //closeModal - //closewindwo - }); + this.formData.body = response.data.text; + this.formData.subject = response.data.subject; + }).catch(this.$fhcAlert.handleSystemError); }, getPreviewText(){ const data = new FormData(); @@ -197,8 +193,7 @@ export default { }, handleSelectedVorlage(vorlage_kurzbz) { if (typeof vorlage_kurzbz === "string") { - this.getVorlagentext(vorlage_kurzbz); - this.formData.subject = vorlage_kurzbz; + this.getDataVorlage(vorlage_kurzbz); } }, showPreview(){ @@ -240,7 +235,7 @@ export default { handler(newVal){ if (newVal && newVal != null) { this.formData.subject = newVal; - return this.getVorlagentext(newVal); + return this.getDataVorlage(newVal); } } }, diff --git a/public/js/components/Messages/Details/NewMessage/NewDiv.js b/public/js/components/Messages/Details/NewMessage/NewDiv.js index 7622f0928..24674fd3f 100644 --- a/public/js/components/Messages/Details/NewMessage/NewDiv.js +++ b/public/js/components/Messages/Details/NewMessage/NewDiv.js @@ -136,15 +136,13 @@ export default { } ); }, - getVorlagentext(vorlage_kurzbz){ + getDataVorlage(vorlage_kurzbz){ return this.$api - .call(this.endpoint.getVorlagentext(vorlage_kurzbz)) + .call(this.endpoint.getDataVorlage(vorlage_kurzbz)) .then(response => { - this.formData.body = response.data; - }).catch(this.$fhcAlert.handleSystemError) - .finally(() => { - //this.resetForm(); - }); + this.formData.body = response.data.text; + this.formData.subject = response.data.subject; + }).catch(this.$fhcAlert.handleSystemError); }, getPreviewText(id, typeId){ const data = new FormData(); @@ -164,20 +162,11 @@ export default { insertVariable(selectedItem){ if (this.editor) { this.editor.insertContent(selectedItem.value + " "); - //TODO(Manu) check: Laden von Variblen geht nicht wenn kein Zeichen danach kommt - // nicht mal mit Punkt adden gehts ohne eintrag nach vars - //this.editor.focus(); - // this.editor.setDirty(true); - this.editor.setDirty(true);//seting dirty true if changes appear - // console.log(tinyMCE.activeEditor.isDirty());//dirty output = true - - - //this.editor.undoManager.add(); - - //this.editor.insertContent(selectedItem.value + "\u00A0"); - //this.editor.insertContent(`${selectedItem.value} `); - //this.editor.selection.setCursorLocation(this.editor.getBody(), 1); + this.editor.fire('input'); + this.editor.fire('change'); + this.editor.setDirty(true); + this.editor.save(); } else { console.error("Editor instance is not available."); @@ -202,8 +191,7 @@ export default { }, handleSelectedVorlage(vorlage_kurzbz) { if (typeof vorlage_kurzbz === "string") { - this.getVorlagentext(vorlage_kurzbz); - this.formData.subject = vorlage_kurzbz; + this.getDataVorlage(vorlage_kurzbz); } }, hideTemplate(){ @@ -248,7 +236,7 @@ export default { if (newVal && newVal != null) { this.formData.subject = newVal; - return this.getVorlagentext(newVal); + return this.getDataVorlage(newVal); } } }, From b73eac62b5dd36899ccd96a93f5db6dd59337e5d Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 11:54:01 +0200 Subject: [PATCH 071/388] add studiensemester param to incoming/outgoing/gs backend --- application/config/routes.php | 6 +++--- .../api/frontend/v1/stv/Students.php | 21 ++++++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/application/config/routes.php b/application/config/routes.php index da3a45f03..189400a72 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -70,9 +70,9 @@ $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv // (studiensemester_kurzbz)/inout[/(incoming|outgoing|gemeinsamestudien)] $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout'] = 'api/frontend/v1/stv/Students/index'; -$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/incoming'] = 'api/frontend/v1/stv/Students/getIncoming'; -$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/outgoing'] = 'api/frontend/v1/stv/Students/getOutgoing'; -$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/gemeinsamestudien'] = 'api/frontend/v1/stv/Students/getGemeinsamestudien'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/incoming'] = 'api/frontend/v1/stv/Students/getIncoming/$1'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/outgoing'] = 'api/frontend/v1/stv/Students/getOutgoing/$1'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/gemeinsamestudien'] = 'api/frontend/v1/stv/Students/getGemeinsamestudien/$1'; // (studiengang_kz)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]] $route['api/frontend/v1/stv/[sS]tudents/(:num)/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudents/$1'; diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 4bd449715..88a87804e 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -101,31 +101,46 @@ class Students extends FHCAPI_Controller } /** + * @param string $studiensemester_kurzbz + * * @return void */ - public function getIncoming() + public function getIncoming($studiensemester_kurzbz) { $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', [ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); // TODO(chris): IMPLEMENT! $this->terminateWithSuccess([]); } /** + * @param string $studiensemester_kurzbz + * * @return void */ - public function getOutgoing() + public function getOutgoing($studiensemester_kurzbz) { $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', [ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); // TODO(chris): IMPLEMENT! $this->terminateWithSuccess([]); } /** + * @param string $studiensemester_kurzbz + * * @return void */ - public function getGemeinsamestudien() + public function getGemeinsamestudien($studiensemester_kurzbz) { $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', [ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); // TODO(chris): IMPLEMENT! $this->terminateWithSuccess([]); } From 31a5caa5580b2002c337265fdd64447a3bcc9361 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 11:56:29 +0200 Subject: [PATCH 072/388] better (safer) output for semester verband gruppe prio --- .../api/frontend/v1/stv/Students.php | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 88a87804e..71b7be872 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -342,9 +342,11 @@ class Students extends FHCAPI_Controller $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect(" - CASE WHEN ps.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') - THEN ps.ausbildungssemester::text - ELSE ''::text END AS semester", false); + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN ps.ausbildungssemester::text + ELSE ''::text + END AS semester", false); $this->PrestudentModel->addSelect("'' AS verband"); $this->PrestudentModel->addSelect("'' AS gruppe"); $this->addSelectPrioRel(); @@ -549,9 +551,16 @@ class Students extends FHCAPI_Controller );*/ $this->prepareQuery($studiensemester_kurzbz); - $this->PrestudentModel->addSelect("COALESCE(v.semester::text, CASE WHEN public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') THEN public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)::text ELSE ''::text END) AS semester", false); - $this->PrestudentModel->addSelect('v.verband'); - $this->PrestudentModel->addSelect('v.gruppe'); + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); $this->addSelectPrioRel(); @@ -796,12 +805,12 @@ class Students extends FHCAPI_Controller SELECT count(*) FROM ( SELECT *, public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) AS laststatus - FROM PUBLIC.tbl_prestudent pss - JOIN PUBLIC.tbl_prestudentstatus USING (prestudent_id) + FROM public.tbl_prestudent pss + JOIN public.tbl_prestudentstatus USING (prestudent_id) WHERE person_id = p.person_id AND studiensemester_kurzbz = ( SELECT studiensemester_kurzbz - FROM PUBLIC.tbl_prestudentstatus + FROM public.tbl_prestudentstatus WHERE prestudent_id = tbl_prestudent.prestudent_id AND status_kurzbz = 'Interessent' LIMIT 1 @@ -810,7 +819,7 @@ class Students extends FHCAPI_Controller ) prest WHERE laststatus NOT IN ('Abbrecher', 'Abgewiesener', 'Absolvent') AND priorisierung <= tbl_prestudent.priorisierung - ) || ' (' || tbl_prestudent.priorisierung || ')' AS priorisierung_relativ", false); + ) || ' (' || COALESCE(tbl_prestudent.priorisierung::text, ' '::text) || ')' AS priorisierung_relativ", false); } /** From 923427b41f20bfde6304dba69102b7a993c08f89 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 11:57:31 +0200 Subject: [PATCH 073/388] Implement: stv/students/getIncoming --- .../api/frontend/v1/stv/Students.php | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 71b7be872..b4116ed0d 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -111,8 +111,43 @@ class Students extends FHCAPI_Controller $this->addMeta('ci_params', [ 'studiensemester_kurzbz' => $studiensemester_kurzbz ]); - // TODO(chris): IMPLEMENT! - $this->terminateWithSuccess([]); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + + $this->prepareQuery($studiensemester_kurzbz); + + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); + + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + + $selectIncoming = "SELECT 1 + FROM public.tbl_prestudentstatus test + WHERE test.prestudent_id=tbl_prestudent.prestudent_id + AND test.status_kurzbz='Incoming' + AND test.studiensemester_kurzbz=v.studiensemester_kurzbz"; + + $this->PrestudentModel->db->where("EXISTS (" . $selectIncoming . ")", null, false); + + $result = $this->PrestudentModel->load(); + + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); } /** From 5ba0007641ec0bd23f95a7944da07ba304a5b39c Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 14:34:19 +0200 Subject: [PATCH 074/388] fix: correct relative priority calculation --- application/controllers/api/frontend/v1/stv/Students.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index b4116ed0d..fe2167189 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -839,7 +839,7 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect("( SELECT count(*) FROM ( - SELECT *, public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) AS laststatus + SELECT *, public.get_rolle_prestudent(pss.prestudent_id, NULL) AS laststatus FROM public.tbl_prestudent pss JOIN public.tbl_prestudentstatus USING (prestudent_id) WHERE person_id = p.person_id From c9104749c54969682790843bd8ab3111827bd8c4 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 16:52:16 +0200 Subject: [PATCH 075/388] Faster Query for stv/students/getIncoming --- .../api/frontend/v1/stv/Students.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index fe2167189..8dcdbcc5e 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -116,6 +116,17 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->PrestudentModel->addJoin( + "( + SELECT prestudent_id + FROM public.tbl_prestudentstatus + WHERE status_kurzbz = 'Incoming' + AND studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ) test", + "prestudent_id" + ); + + $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect("COALESCE( @@ -134,14 +145,6 @@ class Students extends FHCAPI_Controller $this->addFilter($studiensemester_kurzbz); - $selectIncoming = "SELECT 1 - FROM public.tbl_prestudentstatus test - WHERE test.prestudent_id=tbl_prestudent.prestudent_id - AND test.status_kurzbz='Incoming' - AND test.studiensemester_kurzbz=v.studiensemester_kurzbz"; - - $this->PrestudentModel->db->where("EXISTS (" . $selectIncoming . ")", null, false); - $result = $this->PrestudentModel->load(); From 7de81fab7de9cb8472b670b25fe3b5e302d10968 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 17:00:14 +0200 Subject: [PATCH 076/388] Implement: stv/students/getOutgoing --- .../api/frontend/v1/stv/Students.php | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 8dcdbcc5e..0e4a311c9 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -164,8 +164,60 @@ class Students extends FHCAPI_Controller $this->addMeta('ci_params', [ 'studiensemester_kurzbz' => $studiensemester_kurzbz ]); - // TODO(chris): IMPLEMENT! - $this->terminateWithSuccess([]); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + + $this->PrestudentModel->addJoin( + "( + SELECT prestudent_id + FROM bis.tbl_bisio bis + JOIN public.tbl_student USING (student_uid) + JOIN public.tbl_studiensemester stdsem ON ( + (bis.von >= stdsem.start AND bis.von <= stdsem.ende) + OR + (bis.bis >= stdsem.start AND bis.bis <= stdsem.ende) + OR + (bis.von <= stdsem.start AND bis.bis >= stdsem.ende) + ) + WHERE NOT EXISTS ( + SELECT 1 + FROM public.tbl_prestudentstatus + WHERE status_kurzbz = 'Incoming' + AND prestudent_id = tbl_student.prestudent_id + ) AND stdsem.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + GROUP BY prestudent_id + ) test", + "prestudent_id" + ); + + + $this->prepareQuery($studiensemester_kurzbz); + + + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); + + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + + $result = $this->PrestudentModel->load(); + + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); } /** From 608e2b5171aa236497369813226080d7b65ddf66 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 21 Aug 2025 09:18:52 +0200 Subject: [PATCH 077/388] Implement: stv/students/getGemeinsamestudien --- .../api/frontend/v1/stv/Students.php | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 0e4a311c9..691e56b74 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -231,8 +231,46 @@ class Students extends FHCAPI_Controller $this->addMeta('ci_params', [ 'studiensemester_kurzbz' => $studiensemester_kurzbz ]); - // TODO(chris): IMPLEMENT! - $this->terminateWithSuccess([]); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + + $this->PrestudentModel->addJoin( + "( + SELECT prestudent_id + FROM bis.tbl_mobilitaet + WHERE studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ) bis", + "prestudent_id" + ); + + + $this->prepareQuery($studiensemester_kurzbz); + + + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); + + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + + $result = $this->PrestudentModel->load(); + + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); } public function getPrestudents($studiengang_kz, From 9b8ac595c6783060354e6ae0e8bbd1e9719e54a4 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 21 Aug 2025 12:59:24 +0200 Subject: [PATCH 078/388] Code Quality --- application/config/routes.php | 4 +- .../api/frontend/v1/stv/Students.php | 162 ++++++------------ 2 files changed, 56 insertions(+), 110 deletions(-) diff --git a/application/config/routes.php b/application/config/routes.php index 189400a72..58677e8ee 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -1,6 +1,6 @@ my_controller/my_method */ $route['default_controller'] = defined('CIS4') && CIS4 ? 'Cis4' : 'Vilesci'; -$route['translate_uri_dashes'] = FALSE; +$route['translate_uri_dashes'] = false; // Class name conflicts $route['api/v1/organisation/[S|s]tudiengang/(:any)'] = 'api/v1/organisation/studiengang2/$1'; diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 691e56b74..04dc7a33a 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -51,7 +51,6 @@ class Students extends FHCAPI_Controller 'lehre' ) ); - } /** @@ -75,7 +74,7 @@ class Students extends FHCAPI_Controller * /(studiengang_kz)/(orgform)/prestudent/(studiensemester_kurzbz)/(filter) => getPrestudentsOrgform * /(studiengang_kz)/(orgform)/prestudent/(studiensemester_kurzbz)/(filter)/(otherfilter) => getPrestudentsOrgform * - * /(studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe) => getStudentsSpezialguppe + * /(studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe) => getStudentsSpezialgruppe * * /(studiensemester_kurzbz)/(studiengang_kz) => getStudents * /(studiensemester_kurzbz)/(studiengang_kz)/(semester) => getStudents @@ -273,10 +272,11 @@ class Students extends FHCAPI_Controller $this->terminateWithSuccess($data); } - public function getPrestudents($studiengang_kz, - $studiensemester_kurzbz = null, $filter = null - ) - { + public function getPrestudents( + $studiengang_kz, + $studiensemester_kurzbz = null, + $filter = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiengang_kz' => $studiengang_kz, @@ -287,10 +287,12 @@ class Students extends FHCAPI_Controller $this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter); } - public function getPrestudentsOrgform($studiengang_kz, $orgform_kurzbz, - $studiensemester_kurzbz = null, $filter = null - ) - { + public function getPrestudentsOrgform( + $studiengang_kz, + $orgform_kurzbz, + $studiensemester_kurzbz = null, + $filter = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiengang_kz' => $studiengang_kz, @@ -370,7 +372,7 @@ class Students extends FHCAPI_Controller $stg = $this->getDataOrTerminateWithError($result); if (!$stg) - $this->terminateWithValidationErrors(['' => 'Studiengang does not exist']); // TODO(chris): phrase + $this->terminateWithSuccess([]); $stg = current($stg); $where['ps.status_kurzbz'] = 'Interessent'; @@ -439,7 +441,10 @@ class Students extends FHCAPI_Controller break; default: if (!$studiensemester_kurzbz) { - // TODO(chris): this does not work with $orgform_kurzbz != null + /** NOTE(chris): + * show all prestudents in this stg who don't have a status + * $orgform_kurzbz does not change the results since orgform is stored in the status table + */ $where['ps.status_kurzbz'] = null; } else { $this->PrestudentModel->db->where_in('ps.status_kurzbz', [ @@ -453,20 +458,6 @@ class Students extends FHCAPI_Controller break; } - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus ps', ' - ps.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') - AND ps.prestudent_id=tbl_prestudent.prestudent_id - AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') - AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect(" @@ -488,10 +479,13 @@ class Students extends FHCAPI_Controller $this->terminateWithSuccess($data); } - public function getStudents($studiensemester_kurzbz, - $studiengang_kz, $semester = null, $verband = null, $gruppe = null - ) - { + public function getStudents( + $studiensemester_kurzbz, + $studiengang_kz, + $semester = null, + $verband = null, + $gruppe = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -504,10 +498,14 @@ class Students extends FHCAPI_Controller $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, null); } - public function getStudentsOrgform($studiensemester_kurzbz, - $studiengang_kz, $orgform_kurzbz, $semester = null, $verband = null, $gruppe = null - ) - { + public function getStudentsOrgform( + $studiensemester_kurzbz, + $studiengang_kz, + $orgform_kurzbz, + $semester = null, + $verband = null, + $gruppe = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -521,10 +519,12 @@ class Students extends FHCAPI_Controller $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, $orgform_kurzbz); } - public function getStudentsSpezialgruppe($studiensemester_kurzbz, - $studiengang_kz, $semester, $gruppe_kurzbz, - $orgform_kurzbz = null) - { + public function getStudentsSpezialgruppe( + $studiensemester_kurzbz, + $studiengang_kz, + $semester, + $gruppe_kurzbz + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -536,10 +536,13 @@ class Students extends FHCAPI_Controller $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, null); } - public function getStudentsOrgformSpezialgruppe($studiensemester_kurzbz, - $orgform_kurzbz, $studiengang_kz, $semester, $gruppe_kurzbz - ) - { + public function getStudentsOrgformSpezialgruppe( + $studiensemester_kurzbz, + $orgform_kurzbz, + $studiengang_kz, + $semester, + $gruppe_kurzbz + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -563,8 +566,15 @@ class Students extends FHCAPI_Controller * * @return void */ - protected function fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester = null, $verband = null, $gruppe = null, $gruppe_kurzbz = null, $orgform_kurzbz = null) - { + protected function fetchStudents( + $studiensemester_kurzbz, + $studiengang_kz, + $semester = null, + $verband = null, + $gruppe = null, + $gruppe_kurzbz = null, + $orgform_kurzbz = null + ) { $this->load->model('crm/Prestudent_model', 'PrestudentModel'); $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); @@ -573,21 +583,6 @@ class Students extends FHCAPI_Controller $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); } - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz) - );*/ $this->prepareQuery($studiensemester_kurzbz, ''); $this->PrestudentModel->addSelect('v.semester'); @@ -627,7 +622,6 @@ class Students extends FHCAPI_Controller false ); } - } $this->addFilter($studiensemester_kurzbz); @@ -661,22 +655,6 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), - 'LEFT' - );*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect("COALESCE( @@ -725,22 +703,6 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), - 'LEFT' - );*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect('v.semester'); @@ -785,15 +747,6 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - /* - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), - 'LEFT' - );*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect('v.semester'); @@ -911,13 +864,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect('mentor'); $this->PrestudentModel->addSelect('b.aktiv AS bnaktiv'); - /*$this->PrestudentModel->addSelect('tbl_prestudent.reihungstest_id'); - $this->PrestudentModel->addSelect('tbl_prestudent.anmeldungreihungstest'); - $this->PrestudentModel->addSelect('tbl_prestudent.gsstudientyp_kurzbz'); - $this->PrestudentModel->addSelect('tbl_prestudent.priorisierung'); - $this->PrestudentModel->addSelect('p.zugangscode'); - $this->PrestudentModel->addSelect('p.bpk');*/ - $this->PrestudentModel->db->where_in('tbl_prestudent.studiengang_kz', $this->allowedStgs); $this->PrestudentModel->addOrder('nachname'); From fb9f2e86fc0bacc1610125b4a70e0fce3df8c1f8 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 21 Aug 2025 13:46:30 +0200 Subject: [PATCH 079/388] StV: tab ordering --- application/config/stv.php | 29 ++++++++++++++ .../api/frontend/v1/stv/Config.php | 38 ++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/application/config/stv.php b/application/config/stv.php index 675899108..295bb2544 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -83,3 +83,32 @@ if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) { $fieldsZgvDoktor ); } + +$config['student_tab_order'] = [ + 'messages', + 'details', + 'notes', + 'contact', + 'prestudent', + 'status', + 'documents', + 'archive', + 'banking', + 'grades', + 'exam', + 'exemptions', + 'finalexam', + 'mobility', + 'jointstudies', + 'admissionDates', + 'functions', + 'resources', + 'groups', + 'coursedates', +]; +$config['students_tab_order'] = [ + 'banking', + 'status', + 'finalexam', + 'archive', +]; diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 2fb436384..d52016943 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -184,7 +184,9 @@ class Config extends FHCAPI_Controller return $result; }); - $this->terminateWithSuccess($result); + $sortConfig = $this->config->item('student_tab_order'); + + $this->terminateWithSuccess($this->sortTabList($result, $sortConfig)); } public function students() @@ -231,7 +233,9 @@ class Config extends FHCAPI_Controller return $result; }); - $this->terminateWithSuccess($result); + $sortConfig = $this->config->item('students_tab_order'); + + $this->terminateWithSuccess($this->sortTabList($result, $sortConfig)); } protected function kontoColumns() @@ -507,4 +511,34 @@ class Config extends FHCAPI_Controller return $list; } + + /** + * Sort tab list + * + * @param array $input + * @param array $config + * + * @return array + */ + protected function sortTabList($input, $config) + { + // prepare config + if (!$config || !is_array($config)) + $config = []; + else + $config = array_flip($config); + + // fill missing items in config + foreach (array_keys($input) as $key) { + if (!isset($config[$key])) + $config[$key] = count($config); + } + + // do the sorting + uksort($input, function ($a, $b) use ($config) { + return $config[$a] - $config[$b]; + }); + + return $input; + } } From 11868d94967572ffc8ad6a7dc42c45af18aba1fc Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 21 Aug 2025 15:00:18 +0200 Subject: [PATCH 080/388] StV: tab final ordering --- application/config/stv.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/application/config/stv.php b/application/config/stv.php index 295bb2544..42afc318c 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -85,9 +85,9 @@ if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) { } $config['student_tab_order'] = [ - 'messages', 'details', 'notes', + 'messages', 'contact', 'prestudent', 'status', @@ -101,14 +101,15 @@ $config['student_tab_order'] = [ 'mobility', 'jointstudies', 'admissionDates', - 'functions', - 'resources', 'groups', + 'functions', 'coursedates', + 'resources', ]; $config['students_tab_order'] = [ 'banking', 'status', + 'groups', 'finalexam', 'archive', ]; From e79b7a525f7864d6bd2724e0f1f64e494eb6a3ba Mon Sep 17 00:00:00 2001 From: ma0048 Date: Tue, 26 Aug 2025 11:41:10 +0200 Subject: [PATCH 081/388] pruefung bestaetigen bestaetigungsmail schicken ermoeglicht --- cis/private/lehre/pruefung/pruefung.js.php | 58 ++++++++++++--- .../pruefung/pruefungsanmeldung.json.php | 74 ++++++++++++++++++- .../pruefungsanmeldungen_verwalten.php | 22 +++--- locale/de-AT/pruefung.php | 10 +++ locale/en-US/pruefung.php | 9 +++ 5 files changed, 145 insertions(+), 28 deletions(-) diff --git a/cis/private/lehre/pruefung/pruefung.js.php b/cis/private/lehre/pruefung/pruefung.js.php index f2fc2dc7e..73b808d14 100644 --- a/cis/private/lehre/pruefung/pruefung.js.php +++ b/cis/private/lehre/pruefung/pruefung.js.php @@ -863,7 +863,8 @@ function writeAnmeldungen(data, showMessage = true) }); liste += ""; $("#anmeldung_hinzufuegen").html("' onclick='saveAnmeldung(\""+lehrveranstaltung_id+"\",\""+terminId+"\");'/>"); - $("#reihungSpeichernButton").html("' onclick='saveReihung(\""+terminId+"\", \""+lehrveranstaltung_id+"\");'>' onclick='alleBestaetigen(\""+terminId+"\", \""+lehrveranstaltung_id+"\");'>"); + $("#reihungSpeichernButton").html("