load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); $this->load->helper('url'); $this->load->helper('hlp_sancho_helper'); $this->load->library('AnrechnungLib'); // Load configs $this->load->config('anrechnung'); } /** * Sets the Grades in FAS to angerechnet if the request was successfull * @return void */ public function setAnrechnungGrades() { $this->logInfo('Start Anrechnung Grades Job'); // get all accepted requests that are not in the grades table yet // get all placement tests with incorrect studyplan $qry = " SELECT student_uid, lehrveranstaltung_id, studiensemester_kurzbz, genehmigt_von FROM lehre.tbl_anrechnung JOIN public.tbl_student USING(prestudent_id) WHERE genehmigt_von is not null AND EXISTS( SELECT 1 FROM lehre.tbl_anrechnung_anrechnungstatus WHERE anrechnung_id = tbl_anrechnung.anrechnung_id AND status_kurzbz='approved' AND datum>=now()-'5 days'::interval ) AND NOT EXISTS( SELECT 1 FROM lehre.tbl_zeugnisnote WHERE lehrveranstaltung_id = tbl_anrechnung.lehrveranstaltung_id AND studiensemester_kurzbz = tbl_anrechnung.studiensemester_kurzbz AND student_uid = tbl_student.student_uid ) "; $db = new DB_Model(); $result_grades = $db->execReadOnlyQuery($qry); $cnt = 0; if (hasData($result_grades)) { $grades = getData($result_grades); foreach ($grades as $anrechnung) { $cnt++; // Set zeugnisnote to angerechnet (= note 6) $ret = $this->ZeugnisnoteModel->insert(array( 'lehrveranstaltung_id' => $anrechnung->lehrveranstaltung_id, 'student_uid' => $anrechnung->student_uid, 'studiensemester_kurzbz' => $anrechnung->studiensemester_kurzbz, 'uebernahmedatum' => (new DateTime())->format('Y-m-d H:m:i'), 'benotungsdatum' => (new DateTime())->format('Y-m-d H:m:i'), 'note' => 6, 'insertvon' => $anrechnung->genehmigt_von, 'bemerkung' => 'Digitale Anrechnung' ) ); } } $this->logInfo('End Anrechnung Grades Job', array('Number of Grades added'=>$cnt)); } /** * Deletes Zeugnisnoten 'angerechnet', when Anrechnung is rejected afterwards. * E.g., when STGL first accepts, then withdraws and finally rejects the approvement. */ public function deleteAnrechnungGrades() { $this->logInfo('Start AnrechnungJob to delete Grades'); // Get all Zeungisnoten, // WHERE note is angerechnet // AND Anrechnung was rejected AFTER the Zeugnisnote was created $qry = ' SELECT DISTINCT ON (status.anrechnung_id) anrechnung_id, status.status_kurzbz AS "last_anrechnungstatus", status.insertamum AS "last_anrechnungstatus_insertamum", zeugnisnote.insertamum AS "zeugnisdatum_insertamum", student.student_uid, zeugnisnote.lehrveranstaltung_id, zeugnisnote.studiensemester_kurzbz, note FROM lehre.tbl_zeugnisnote zeugnisnote JOIN public.tbl_student student USING (student_uid) JOIN lehre.tbl_anrechnung anrechnung ON (zeugnisnote.lehrveranstaltung_id = anrechnung.lehrveranstaltung_id) AND (student.prestudent_id = anrechnung.prestudent_id) AND (zeugnisnote.studiensemester_kurzbz = anrechnung.studiensemester_kurzbz) JOIN lehre.tbl_anrechnung_anrechnungstatus status USING (anrechnung_id) WHERE note = 6 AND status.insertamum > zeugnisnote.insertamum AND status.status_kurzbz = '. $this->db->escape(self::ANRECHNUNGSTATUS_REJECTED). ' ORDER BY status.anrechnung_id, status.insertamum DESC '; $db = new DB_Model(); $result = $db->execReadOnlyQuery($qry); $cnt = 0; if (hasData($result)) { $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); foreach (getData($result) as $row) { // Delete Zeugnisnote $this->ZeugnisnoteModel->delete(array( 'lehrveranstaltung_id' => $row->lehrveranstaltung_id, 'student_uid' => $row->student_uid, 'studiensemester_kurzbz' => $row->studiensemester_kurzbz )); // Count up $cnt++; } } $this->logInfo('End AnrechnungJob to delete Grades', array('Number of Grades deleted: ' => $cnt)); } // Send Sancho mail to STGL with yesterdays new Anrechnungen public function sendMailToSTGL() { $this->logInfo('Start AnrechnungJob to send emails to STGL about yesterdays new Anrechnungen.'); // Get all yesterdays Anrechnungen, that did not process further than first status // (If Anrechnung is new, but STGL already started the process yesterday, // he does not need to be informed about this new Anrechnung anymore) $this->AnrechnungModel->addSelect('anrechnung_id, studiensemester_kurzbz, lv.studiengang_kz, lv.bezeichnung, vorname, nachname'); $this->AnrechnungModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); $this->AnrechnungModel->addJoin('public.tbl_student student', 'prestudent_id'); $this->AnrechnungModel->addJoin('public.tbl_benutzer benutzer', 'ON (benutzer.uid = student.student_uid)'); $this->AnrechnungModel->addJoin('public.tbl_person person', 'person_id'); $this->AnrechnungModel->addOrder('lv.studiengang_kz, lv.bezeichnung'); $result = $this->AnrechnungModel->loadWhere( '(lehre.tbl_anrechnung.insertamum)::date = (NOW() - INTERVAL \'24 HOURS\')::DATE AND 1 = (SELECT COUNT(*) FROM lehre.tbl_anrechnung_anrechnungstatus status WHERE status.anrechnung_id = tbl_anrechnung.anrechnung_id)' ); // Exit if there are no Anrechnungen if (!$anrechnungen = getData($result)) { $this->logInfo('ABORTED: Sending emails to STGL about yesterdays new Anrechnungen aborted - No new Anrechnungen found.'); exit; } $unique_studiengang_kz_arr = array_unique(array_column($anrechnungen, 'studiengang_kz')); foreach ($unique_studiengang_kz_arr as $studiengang_kz) { // Get STG bezeichnung $this->StudiengangModel->addSelect('UPPER( typ || kurzbz ) AS "stg_bezeichnung"'); $studiengang_bezeichnung = $this->StudiengangModel->load($studiengang_kz)->retval[0]->stg_bezeichnung; // Get STGL mail address $stglMailReceiver_arr = self::_getSTGLMailAddress($studiengang_kz); // Get HTML table with new Anrechnungen of that STG plus amount of them list ($anrechnungen_amount, $anrechnungen_table) = self::_getSTGLMailDataTable($studiengang_kz, $anrechnungen); // Link to Antrag genehmigen dashboard $url = CIS_ROOT. 'cis/index.php?menu='. CIS_ROOT. 'cis/menu.php?content_id=&content='. CIS_ROOT. index_page(). self::APPROVE_ANRECHNUNG_URI; foreach ($stglMailReceiver_arr as $stgl) { // Prepare mail content $body_fields = array( 'vorname' => $stgl['vorname'], 'studiengang' => $studiengang_bezeichnung, 'anzahl' => $anrechnungen_amount, 'datentabelle' => $anrechnungen_table, 'link' => anchor($url, 'Anrechnungsanträge Übersicht') ); // Send mail sendSanchoMail( 'AnrechnungAntragStellen', $body_fields, $stgl['to'], 'Anerkennung nachgewiesener Kenntnisse: Neuer Antrag wurde gestellt' ); } } $this->logInfo('SUCCEDED: Sending emails to STGL about yesterdays new Anrechnungen succeded.'); } // Send Sancho mail to LV-Leitung (fallback Lectors) that were requested for recommendation yesterday. public function sendMailRecommendationRequests(){ $this->logInfo('Start AnrechnungJob sendMailRecommendationRequests to inform lecturers about yesterdays requests for recommendation.'); // Get Anrechnungen, für die gestern eine Empfehlung angefragt worden ist $this->AnrechnungModel->addSelect('astat.anrechnung_id, astat.datum, astat.insertamum'); $this->AnrechnungModel->addDistinct('astat.anrechnung_id'); $this->AnrechnungModel->addJoin('lehre.tbl_anrechnung_anrechnungstatus astat', 'anrechnung_id'); $result = $this->AnrechnungModel->loadWhere(' studiensemester_kurzbz = (SELECT studiensemester_kurzbz FROM tbl_studiensemester WHERE now()::date BETWEEN start AND ende) AND genehmigt_von IS NULL AND empfehlung_anrechnung IS NULL AND status_kurzbz = '. $this->db->escape(self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR) .' -- in Bearbeitung durch Lektor AND NOW()::date = (astat.datum + interval \'1 day\') -- nur gestrige Empfehlungsanfrage ORDER BY astat.anrechnung_id, astat.datum DESC, astat.insertamum DESC -- nur letzten status dabei prüfen '); // Exit, wenn es gestern keine Empfehlungsanfragen gab if (!hasData($result)) { $this->logInfo('End AnrechnungJob sendMailRecommendationRequests, because no recommendations were requested yesterday.'); exit; } $anrechnung_id_arr = array_column(getData($result), 'anrechnung_id'); $arr_lvLector_arr = array(); foreach ($anrechnung_id_arr as $anrechnung_id) { // Get full name of Fachbereichsleitung or LV Leitung. if($this->config->item('fbl') === TRUE) { $arr_lvLector_arr[] = $this->anrechnunglib->getLeitungOfLvOe($anrechnung_id); } else { $arr_lvLector_arr[] = $this->anrechnunglib->getLectors($anrechnung_id); // Returns LV Leitung. If not present, then all lectors of LV. } } // Unique lector array to send only one mail per lector $arr_lvLector_arr = array_unique($arr_lvLector_arr, SORT_REGULAR); // Link to 'Anrechnungen prüfen' dashboard $url = CIS_ROOT. 'cis/index.php?menu='. CIS_ROOT. 'cis/menu.php?content_id=&content='. CIS_ROOT. index_page(). self::REVIEW_ANRECHNUNG_URI; foreach ($arr_lvLector_arr as $lvLector_arr) { foreach ($lvLector_arr as $lector) { // Prepare mail content $fields = array( 'vorname' => $lector->vorname, 'stgl_name' => 'Die Studiengangsleitung', 'link' => anchor($url, 'Anrechnungsanträge Übersicht') ); // Send mail sendSanchoMail( 'AnrechnungEmpfehlungAnfordern', $fields, $lector->uid. '@'. DOMAIN, 'Deine Empfehlung wird benötigt zur Anerkennung nachgewiesener Kenntnisse' ); } } $this->logInfo('SUCCEDED AnrechnungJob sendMailRecommendationRequests'); } /** * Send Sancho mail to students, whose Anrechnungen were approved 24 hours ago. */ public function sendMailApproved(){ $this->logInfo('Start AnrechnungJob to send emails to students, whose Anrechnungen were approved.'); // Get all yesterdays approvements $this->AnrechnungModel->addSelect('student.student_uid, vorname, nachname, geschlecht, lv.bezeichnung'); $this->AnrechnungModel->addJoin('lehre.tbl_anrechnung_anrechnungstatus status', 'anrechnung_id'); $this->AnrechnungModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); $this->AnrechnungModel->addJoin('public.tbl_student student', 'prestudent_id'); $this->AnrechnungModel->addJoin('public.tbl_benutzer benutzer', 'ON (benutzer.uid = student.student_uid)'); $this->AnrechnungModel->addJoin('public.tbl_person person', 'person_id'); $result = $this->AnrechnungModel->loadWhere( '(status.insertamum)::date = (NOW() - INTERVAL \'24 HOURS\')::DATE AND status.status_kurzbz = '. $this->db->escape(self::ANRECHNUNGSTATUS_APPROVED) ); // Exit if there are no approved Anrechnungen if (!hasData($result)) { $this->logInfo('ABORTED sending emails to students, whose Anrechnungen were approved. No new approvements found.'); exit; } // Loop through students foreach ($result->retval as $student) { $to = $student->student_uid. '@'. DOMAIN; $anrede = $student->geschlecht == 'w' ? 'Sehr geehrte Frau ' : 'Sehr geehrter Herr '; $text = 'Ihrem Antrag auf Anerkennung nachgewiesener Kenntnisse der Lehrveranstaltung "'. $student->bezeichnung. '" wurde stattgegeben.'; // Prepare mail content $body_fields = array( 'anrede_name' => $anrede. $student->vorname. ' '. $student->nachname, 'text' => $text ); // Send mail sendSanchoMail( 'AnrechnungGenehmigen', $body_fields, $to, 'Anerkennung nachgewiesener Kenntnisse: Ihr Antrag ist abgeschlossen' ); } } /** * Send Sancho mail to students, whose Anrechnungen were rejected 24 hours ago. */ public function sendMailRejected(){ $this->logInfo('Start AnrechnungJob to send emails to students, whose Anrechnungen were rejected.'); $qry = ' SELECT student.student_uid, vorname, nachname, geschlecht, lv.bezeichnung, (SELECT text FROM public.tbl_notizzuordnung JOIN public.tbl_notiz USING(notiz_id) WHERE tbl_notizzuordnung.anrechnung_id=tbl_anrechnung.anrechnung_id AND tbl_notiz.titel='. $this->db->escape(self::ANRECHNUNG_NOTIZTITEL_NOTIZ_BY_STGL).' ORDER BY tbl_notiz.insertamum DESC LIMIT 1) as text FROM lehre.tbl_anrechnung JOIN lehre.tbl_lehrveranstaltung lv USING(lehrveranstaltung_id) JOIN public.tbl_student student USING(prestudent_id) JOIN public.tbl_benutzer benutzer ON (benutzer.uid = student.student_uid) JOIN public.tbl_person person USING(person_id) WHERE EXISTS(SELECT 1 FROM lehre.tbl_anrechnung_anrechnungstatus status WHERE anrechnung_id=tbl_anrechnung.anrechnung_id AND (status.insertamum)::date = (NOW() - INTERVAL \'24 HOURS\')::DATE AND status_kurzbz = '. $this->db->escape(self::ANRECHNUNGSTATUS_REJECTED). ') '; $db = new DB_Model(); $result = $db->execReadOnlyQuery($qry); // Exit if there are no rejected Anrechnungen if (!hasData($result)) { $this->logInfo('ABORTED sending emails to students, whose Anrechnungen were rejected. No new rejectments found.'); exit; } // Loop through students foreach ($result->retval as $student) { $to = $student->student_uid. '@'. DOMAIN; $anrede = $student->geschlecht == 'w' ? 'Sehr geehrte Frau ' : 'Sehr geehrter Herr '; $text = <<bezeichnung" leider nicht anrechnen, weil die Gleichwertigkeit nicht festgestellt werden konnte.

Begründung: $student->text html; // Prepare mail content $body_fields = array( 'anrede_name' => $anrede. $student->vorname. ' '. $student->nachname, 'text' => $text ); // Send mail sendSanchoMail( 'AnrechnungGenehmigen', $body_fields, $to, 'Anerkennung nachgewiesener Kenntnisse: Ihr Antrag ist abgeschlossen' ); } } /** * Send Sancho mail to remind lecturers to provide their recommendation if not done until one week after request. */ public function sendMailRemindRecommendation(){ $this->logInfo('Start AnrechnungJob sendMailRemindRecommendation to remind lecturers to provide their recommendation.'); // Get Anrechnungen with pending recommendations, that were requested 1 week before today. // Restrict query for Anrechnungen of actual semester. $this->AnrechnungModel->addSelect('astat.anrechnung_id, astat.datum, astat.insertamum'); $this->AnrechnungModel->addDistinct('astat.anrechnung_id'); $this->AnrechnungModel->addJoin('lehre.tbl_anrechnung_anrechnungstatus astat', 'anrechnung_id'); $result = $this->AnrechnungModel->loadWhere(' studiensemester_kurzbz = ( SELECT studiensemester_kurzbz FROM tbl_studiensemester WHERE now()::date BETWEEN start AND ende ) AND genehmigt_von IS NULL AND empfehlung_anrechnung IS NULL AND status_kurzbz = '. $this->db->escape(self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR) .' -- in Bearbeitung durch Lektor AND NOW()::date = (astat.datum + interval \'1 week\') -- eine Woche nach Empfehlungsanfrage ORDER BY astat.anrechnung_id, astat.datum DESC, astat.insertamum DESC -- nur letzten status dabei prüfen '); // Exit if there are no pending recommendations if (!hasData($result)) { $this->logInfo('End AnrechnungJob sendMailRemindRecommendation, because no recommendations to be done.'); exit; } $anrechnung_id_arr = array_column(getData($result), 'anrechnung_id'); $arr_lvLector_arr = array(); foreach ($anrechnung_id_arr as $anrechnung_id) { $arr_lvLector_arr[]= $this->anrechnunglib->getLectors($anrechnung_id); // Returns LV Leitung. If not present, then all lectors of LV. } // Unique lector array to send only one mail per lector $arr_lvLector_arr = array_unique($arr_lvLector_arr, SORT_REGULAR); // Link to 'Anrechnungen prüfen' dashboard $url = CIS_ROOT. 'cis/index.php?menu='. CIS_ROOT. 'cis/menu.php?content_id=&content='. CIS_ROOT. index_page(). self::REVIEW_ANRECHNUNG_URI; foreach ($arr_lvLector_arr as $lvLector_arr) { foreach ($lvLector_arr as $lector) { // Prepare mail content $fields = array( 'vorname' => $lector->vorname, 'stgl_name' => 'Die Studiengangsleitung', 'link' => anchor($url, 'Anrechnungsanträge Übersicht') ); // Send mail sendSanchoMail( 'AnrechnungEmpfehlungAnfordern', $fields, $lector->uid. '@'. DOMAIN, 'Erinnerung: Deine Empfehlung wird benötigt zur Anerkennung nachgewiesener Kenntnisse' ); } } $this->logInfo('SUCCEDED AnrechnungJob sendMailRemindRecommendation'); } // Get STGL mail address private function _getSTGLMailAddress($studiengang_kz) { $stglMailAdress_arr = array(); $result = $this->StudiengangModel->getLeitung($studiengang_kz); // Get STGL mail address if (hasData($result)) { foreach (getData($result) as $stgl) { $stglMailAdress_arr[]= array( 'to' => $stgl->uid. '@'. DOMAIN, 'vorname' => $stgl->vorname ); } return $stglMailAdress_arr; } // If not available, get assistance mail address else { $result = $this->StudiengangModel->load($studiengang_kz); if (hasData($result)) { return array( $result->retval[0]->email, '' ); } } } // Build HTML table with yesterdays new Anrechnungen of the given STG private function _getSTGLMailDataTable($studiengang_kz, $anrechnungen) { $html = ''; $lv_bezeichnung = ''; // Filter Anrechnungen of given STG $anrechnungen = array_filter( $anrechnungen, function ($anrechnung) use (&$studiengang_kz) { return $anrechnung->studiengang_kz == $studiengang_kz; }); // Amount of Anrechnungen $amount = count($anrechnungen); // HTML table body $html .= ' '; foreach ($anrechnungen as $anrechnung) { // Head line for each LV bezeichnung if ($anrechnung->bezeichnung != $lv_bezeichnung) { $html .= ''; } $lv_bezeichnung = $anrechnung->bezeichnung; // Row for each Anrechnung / student $html .= ''; } $html .= '
' . $anrechnung->bezeichnung . '
'. $anrechnung->vorname. ' '. $anrechnung->nachname. '
'; return array($amount, $html); } }