From 558a3fbdb189d64e2dbaf43581e6972b91bb8d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Mon, 22 Oct 2018 11:50:50 +0200 Subject: [PATCH 01/58] =?UTF-8?q?Abh=C3=A4ngigkeit=20von=20Tabelle=20Fachb?= =?UTF-8?q?ereich=20entfernt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vilesci/personen/institutsliste.php | 144 ++++++++++++++++------------ 1 file changed, 81 insertions(+), 63 deletions(-) diff --git a/vilesci/personen/institutsliste.php b/vilesci/personen/institutsliste.php index fdeb1ffeb..326b6ab48 100644 --- a/vilesci/personen/institutsliste.php +++ b/vilesci/personen/institutsliste.php @@ -24,7 +24,7 @@ require_once('../../config/vilesci.config.inc.php'); require_once('../../include/functions.inc.php'); require_once('../../include/studiengang.class.php'); -require_once('../../include/fachbereich.class.php'); +require_once('../../include/organisationseinheit.class.php'); require_once('../../include/studiensemester.class.php'); require_once('../../include/benutzerberechtigung.class.php'); @@ -34,8 +34,15 @@ if (!$db = new basis_db()) $stg_obj = new studiengang(); $stg_obj->getAll('typ, kurzbz', false); -$fb_obj = new fachbereich(); -$fb_obj->getAll(); +$oe_typ = new organisationseinheit(); +$oe_typ->getTypen(); +foreach($oe_typ->result as $row) + $oe_typ_arr[$row->organisationseinheittyp_kurzbz]=$row->bezeichnung; +$oe_obj = new organisationseinheit(); +$oe_obj->getAll(); + +foreach($oe_obj->result as $row) + $oe_arr[$row->oe_kurzbz] = $oe_typ_arr[$row->organisationseinheittyp_kurzbz].' '.$row->bezeichnung; $rechte = new benutzerberechtigung(); $rechte->getBerechtigungen(get_uid()); @@ -55,26 +62,26 @@ echo ' -

Liste der MitarbeiterInnen der Institute

'; +

Liste der MitarbeiterInnen der Abteilungen

'; $stsem = new studiensemester(); if(isset($_GET['ws']) && check_stsem($_GET['ws'])) $ws = $_GET['ws']; else $ws = $stsem->getNearest(1); - + if(isset($_GET['ss']) && check_stsem($_GET['ss'])) $ss = $_GET['ss']; else @@ -82,49 +89,55 @@ else if($rechte->isBerechtigt('admin', 0) || $rechte->isBerechtigt('mitarbeiter', 0)) $where = ''; -else +else { - $fb = $rechte->getFbKz(); - if(count($fb)>0) + $oe = $rechte->getOEkurzbz('assistenz'); + if(count($oe)>0) { - $where = " AND EXISTS (SELECT * FROM lehre.tbl_lehreinheitmitarbeiter JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) JOIN lehre.tbl_lehrveranstaltung lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id) JOIN public.tbl_fachbereich ON(lehrfach.oe_kurzbz=tbl_fachbereich.oe_kurzbz) WHERE - tbl_lehreinheit.studiensemester_kurzbz in(".$db->db_add_param($ws).",".$db->db_add_param($ss).") AND mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid AND - fachbereich_kurzbz IN("; - foreach ($fb as $fachbereich_kurzbz) + $where = " AND EXISTS ( + SELECT * FROM + lehre.tbl_lehreinheitmitarbeiter + JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id) + WHERE + tbl_lehreinheit.studiensemester_kurzbz in(".$db->db_add_param($ws).",".$db->db_add_param($ss).") + AND mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid + AND lehrfach.oe_kurzbz IN("; + foreach ($oe as $oe_kurzbz) { - $where.=$db->db_add_param($fachbereich_kurzbz).","; + $where.=$db->db_add_param($oe_kurzbz).","; } $where.="''))"; } - else + else die('Sie haben keine Berechtigung fuer diese Seite'); } //Alle aktiven Mitarbeiter holen mit den ALVS-Stunden und der Hauptinstitutszuteilung -$qry = "SELECT - personalnummer, vorname, nachname, fixangestellt, mitarbeiter_uid, kompetenzen, +$qry = "SELECT + personalnummer, vorname, nachname, fixangestellt, mitarbeiter_uid, kompetenzen, ( - SELECT - sum(semesterstunden) - FROM + SELECT + sum(semesterstunden) + FROM lehre.tbl_lehreinheitmitarbeiter JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) - WHERE - mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid AND + WHERE + mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid AND studiensemester_kurzbz=".$db->db_add_param($ws)." ) as lvs_wintersemester, ( - SELECT - sum(semesterstunden) - FROM + SELECT + sum(semesterstunden) + FROM lehre.tbl_lehreinheitmitarbeiter JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) - WHERE - mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid AND + WHERE + mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid AND studiensemester_kurzbz=".$db->db_add_param($ss)." ) as lvs_sommersemester, ( - SELECT - tbl_organisationseinheit.bezeichnung - FROM + SELECT + tbl_organisationseinheit.oe_kurzbz + FROM public.tbl_benutzerfunktion JOIN public.tbl_organisationseinheit USING(oe_kurzbz) WHERE uid=tbl_mitarbeiter.mitarbeiter_uid AND @@ -133,9 +146,9 @@ $qry = "SELECT AND (datum_bis>=now() OR datum_bis is null) LIMIT 1 ) as hauptzuteilung - FROM - public.tbl_mitarbeiter JOIN public.tbl_benutzer ON(uid=mitarbeiter_uid) - JOIN public.tbl_person USING(person_id) + FROM + public.tbl_mitarbeiter JOIN public.tbl_benutzer ON(uid=mitarbeiter_uid) + JOIN public.tbl_person USING(person_id) WHERE tbl_benutzer.aktiv $where"; if($result = $db->db_query($qry)) @@ -149,12 +162,11 @@ if($result = $db->db_query($qry)) Nachname Vorname Fix / Frei - Kompetenzen ALVS
".$db->convert_html_chars($ws)." ALVS
".$db->convert_html_chars($ss)." Studiengang - Institut Hauptzuteilung - Sonstige Institutszuteilungen + Disziplinäre Zuordnung + Zuteilungen laut Lehrauträge "; @@ -166,46 +178,52 @@ if($result = $db->db_query($qry)) echo "".$db->convert_html_chars($row->nachname).""; echo "".$db->convert_html_chars($row->vorname).""; echo "".($row->fixangestellt=='t'?'fix':'frei').""; - echo "".$db->convert_html_chars($row->kompetenzen).""; echo "$row->lvs_wintersemester"; echo "$row->lvs_sommersemester"; echo ''; $qry = " - SELECT - distinct studiengang_kz - FROM - lehre.tbl_lehreinheitmitarbeiter - JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) - JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) - WHERE - mitarbeiter_uid=".$db->db_add_param($row->mitarbeiter_uid)." + SELECT + distinct studiengang_kz + FROM + lehre.tbl_lehreinheitmitarbeiter + JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + WHERE + mitarbeiter_uid=".$db->db_add_param($row->mitarbeiter_uid)." AND studiensemester_kurzbz in(".$db->db_add_param($ss).", ".$db->db_add_param($ws).")"; - + $text=''; + if($row->hauptzuteilung!='') + $abteilung = $oe_arr[$row->hauptzuteilung]; + else + $abteilung = ''; + if($result_stg = $db->db_query($qry)) while($row_stg = $db->db_fetch_object($result_stg)) $text.= $stg_obj->kuerzel_arr[$row_stg->studiengang_kz].', '; echo mb_substr($text, 0, mb_strlen($text)-2); echo ''; - echo "".$db->convert_html_chars($row->hauptzuteilung).""; + echo "".$db->convert_html_chars($abteilung).""; echo ""; $qry = " - SELECT - distinct fachbereich_kurzbz - FROM - lehre.tbl_lehreinheitmitarbeiter - JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) - JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) - JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id) - JOIN public.tbl_fachbereich ON(lehrfach.oe_kurzbz=tbl_fachbereich.oe_kurzbz) - WHERE - mitarbeiter_uid=".$db->db_add_param($row->mitarbeiter_uid)." + SELECT + distinct lehrfach.oe_kurzbz + FROM + lehre.tbl_lehreinheitmitarbeiter + JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id) + WHERE + mitarbeiter_uid=".$db->db_add_param($row->mitarbeiter_uid)." AND studiensemester_kurzbz in(".$db->db_add_param($ss).", ".$db->db_add_param($ws).")"; - + $text=''; - if($result_fb = $db->db_query($qry)) - while($row_fb = $db->db_fetch_object($result_fb)) - $text.= $fb_obj->bezeichnung_arr[$row_fb->fachbereich_kurzbz].', '; + if($result_oe = $db->db_query($qry)) + while($row_oe = $db->db_fetch_object($result_oe)) + { + if($row_oe->oe_kurzbz!='') + $text.= $oe_arr[$row_oe->oe_kurzbz].', '; + } echo mb_substr($text, 0, mb_strlen($text)-2); echo ""; echo ''; From 5ea0621a7810b9f51136334734f7b4efb757ea1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Mon, 22 Oct 2018 12:08:21 +0200 Subject: [PATCH 02/58] =?UTF-8?q?Abh=C3=A4ngigkeit=20von=20Fachbereich=20f?= =?UTF-8?q?=C3=BCr=20Auswertungen=20entfernt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/statistik/alvsstatistik.php | 216 ++++++++++++------------ content/statistik/lvplanung.php | 21 ++- content/statistik/lvplanung.xls.php | 245 ++++++++++++---------------- 3 files changed, 218 insertions(+), 264 deletions(-) diff --git a/content/statistik/alvsstatistik.php b/content/statistik/alvsstatistik.php index e1b851654..982427c9a 100644 --- a/content/statistik/alvsstatistik.php +++ b/content/statistik/alvsstatistik.php @@ -22,7 +22,6 @@ require_once('../../config/vilesci.config.inc.php'); require_once('../../include/functions.inc.php'); require_once('../../include/studiengang.class.php'); -require_once('../../include/fachbereich.class.php'); require_once('../../include/Excel/excel.php'); require_once('../../include/benutzerberechtigung.class.php'); @@ -45,24 +44,31 @@ $stg_arr = array(); foreach ($studiengang->result as $row) $stg_arr[$row->studiengang_kz] = $row->kuerzel.' ('.$row->kurzbzlang.')'; -$fachbereich = new fachbereich(); -$fachbereich->getAll(); +$oe_obj = new organisationseinheit(); +$oe_obj->getTypen(); +foreach($oe_obj->result as $row) +{ + $oetyp_arr[$row->organisationseinheittyp_kurzbz] = $row->bezeichnung; +} -$fb_arr = array(); -foreach ($fachbereich->result as $row) - $fb_arr[$row->fachbereich_kurzbz]=$row->bezeichnung; +$oe_obj = new organisationseinheit(); +$oe_obj->getAll(); + +$oe_arr = array(); +$oe_arr['']='Nicht Zugewiesen'; +foreach ($oe_obj->result as $row) + $oe_arr[$row->oe_kurzbz]=$oetyp_arr[$row->organisationseinheittyp_kurzbz].' '.$row->bezeichnung; $db = new basis_db(); -// ALVS pro Fachbereich +// ALVS pro OE $qry = " SELECT * FROM ( SELECT - fachbereich_kurzbz, tbl_lehrveranstaltung.studiengang_kz, geschlecht,sum(tbl_lehreinheitmitarbeiter.semesterstunden) as semesterstunden + lehrfach.oe_kurzbz as lehrfach_oe_kurzbz, tbl_lehrveranstaltung.studiengang_kz, geschlecht,sum(tbl_lehreinheitmitarbeiter.semesterstunden) as semesterstunden FROM lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, lehre.tbl_lehrveranstaltung as lehrfach, - public.tbl_fachbereich, lehre.tbl_lehreinheitmitarbeiter, public.tbl_benutzer, public.tbl_person @@ -73,28 +79,27 @@ SELECT * FROM ( tbl_lehreinheitmitarbeiter.mitarbeiter_uid = tbl_benutzer.uid AND tbl_benutzer.person_id = tbl_person.person_id AND tbl_lehreinheitmitarbeiter.semesterstunden<>0 AND - tbl_fachbereich.oe_kurzbz=lehrfach.oe_kurzbz AND faktor<>0 AND stundensatz<>0 AND tbl_lehreinheitmitarbeiter.lehreinheit_id=tbl_lehreinheit.lehreinheit_id - GROUP BY fachbereich_kurzbz, geschlecht, tbl_lehrveranstaltung.studiengang_kz + GROUP BY lehrfach.oe_kurzbz, geschlecht, tbl_lehrveranstaltung.studiengang_kz ) as a JOIN public.tbl_studiengang USING(studiengang_kz) -ORDER BY typ, tbl_studiengang.kurzbz, fachbereich_kurzbz +ORDER BY typ, tbl_studiengang.kurzbz, lehrfach_oe_kurzbz "; if(!$db->db_query($qry)) die('Fehler bei Datenbankabfrage'); -$fachbereiche = array(); +$organisationseinheiten = array(); while($row = $db->db_fetch_object()) { - if(!in_array($row->fachbereich_kurzbz, $fachbereiche)) - $fachbereiche[] = $row->fachbereich_kurzbz; - $data[$row->studiengang_kz][$row->fachbereich_kurzbz][$row->geschlecht]=$row->semesterstunden; + if(!in_array($row->lehrfach_oe_kurzbz, $organisationseinheiten)) + $organisationseinheiten[] = $row->lehrfach_oe_kurzbz; + $data[$row->studiengang_kz][$row->lehrfach_oe_kurzbz][$row->geschlecht]=$row->semesterstunden; } -sort($fachbereiche); +sort($organisationseinheiten); //Betreuerstunden $qry = " @@ -138,7 +143,6 @@ if($format=='xls') //Formate Definieren $format_bold =& $workbook->addFormat(); $format_bold->setBold(); - //$format_bold->setBorder(1); $format_border =& $workbook->addFormat(); $format_border->setBorder(1); @@ -147,19 +151,19 @@ if($format=='xls') $format_rotate->setTextRotation(270); $format_rotate->setAlign("center"); $format_rotate->setBold(); - + $format_m_w =& $workbook->addFormat(); $format_m_w->setAlign("center"); $format_m_w->setBold(); - + $format_data =& $workbook->addFormat(); $format_data->setNumFormat("0.00"); - + $format_bold_data =& $workbook->addFormat(); $format_bold_data->setBold(); $format_bold_data->setNumFormat("0.00"); $format_bold_data->setVAlign("vcenter"); - + $format_bold_center_data =& $workbook->addFormat(); $format_bold_center_data->setBold(); $format_bold_center_data->setNumFormat("0.00"); @@ -168,59 +172,45 @@ if($format=='xls') $spalte=0; $zeile=0; - $worksheet->write($zeile,$spalte,$stsem, $format_bold); $maxlength[$spalte]=13; - $summe_fb = array(); - foreach ($fachbereiche as $fb) + $summe_oe = array(); + foreach ($organisationseinheiten as $oe) { $zeile=0; - $worksheet->write($zeile,++$spalte,$fb_arr[$fb], $format_rotate); + $worksheet->write($zeile,++$spalte,$oe_arr[$oe], $format_rotate); $worksheet->mergeCells($zeile,$spalte,0,$spalte+1); - $fachbereiche[$fb]=$spalte; - + $organisationseinheiten_idx[$oe]=$spalte; + $worksheet->write(++$zeile,$spalte,'m',$format_m_w); $worksheet->write($zeile,++$spalte,'w',$format_m_w); - - //$fachbereiche[$fb]=$spalte; - $summe_fb[$fb]=array(); - //++$spalte; + + $summe_oe[$oe]=array(); + $maxlength[$spalte]=7; $maxlength[$spalte-1]=7; } $zeile=0; $worksheet->write($zeile,++$spalte,'Betreuungen', $format_rotate); $worksheet->mergeCells($zeile,$spalte,0,$spalte+1); - + $worksheet->write(++$zeile,$spalte,'m',$format_m_w); $worksheet->write($zeile,++$spalte,'w',$format_m_w); - + $maxlength[$spalte]=7; $maxlength[$spalte-1]=7; - - $fachbereiche['betreuungen']=$spalte-1; - //$maxlength[$spalte]=3; - $summe_fb['betreuungen']=array(); - //++$spalte; - + + $organisationseinheiten_idx['betreuungen']=$spalte-1; + $summe_oe['betreuungen']=array(); + $zeile=0; $worksheet->write($zeile,++$spalte,'Summe', $format_rotate); $worksheet->mergeCells($zeile,$spalte,0,$spalte+2); $worksheet->write(++$zeile,$spalte,'m',$format_m_w); $worksheet->write($zeile,++$spalte,'w',$format_m_w); $worksheet->write($zeile,++$spalte,'Gesamt',$format_m_w); - + $maxspalten=$spalte; - - /*++$zeile; - $spalte=0; - foreach ($fachbereiche as $fb) - { - $worksheet->write($zeile,++$spalte,'m'); - $worksheet->write($zeile,++$spalte,'w'); - //$fachbereiche[$fb]=$spalte; - //++$spalte; - }*/ if(isset($data)) { @@ -231,27 +221,23 @@ if($format=='xls') $worksheet->write($zeile,$spalte,$stg_arr[$key], $format_bold); $summe_m=0; $summe_w=0; - foreach ($data[$key] as $fb=>$stunden) + foreach ($data[$key] as $oe=>$stunden) { if(!isset($stunden['m'])) $stunden['m']=0; $summe_m+=$stunden['m']; - if(!isset($summe_fb[$fb]['m'])) - $summe_fb[$fb]['m']=0; - $summe_fb[$fb]['m']+=$stunden['m']; - $worksheet->write($zeile,$fachbereiche[$fb],$stunden['m'],$format_data); - //if($maxlength[$fachbereiche[$fb]]write($zeile,$organisationseinheiten_idx[$oe],$stunden['m'],$format_data); + if(!isset($stunden['w'])) $stunden['w']=0; $summe_w+=$stunden['w']; - if(!isset($summe_fb[$fb]['w'])) - $summe_fb[$fb]['w']=0; - $summe_fb[$fb]['w']+=$stunden['w']; - $worksheet->write($zeile,$fachbereiche[$fb]+1,$stunden['w'],$format_data); - //if($maxlength[$fachbereiche[$fb]]write($zeile,$organisationseinheiten_idx[$oe]+1,$stunden['w'],$format_data); } $worksheet->write($zeile,$maxspalten-2,number_format($summe_m,2,'.',''), $format_bold_data); $worksheet->write($zeile,$maxspalten-1,number_format($summe_w,2,'.',''), $format_bold_data); @@ -264,20 +250,20 @@ if($format=='xls') $zeile++; $worksheet->write($zeile,0,'Summe', $format_bold_data); $worksheet->mergeCells($zeile,0,$zeile+1,0); - //foreach ($summe_fb as $fb=>$summe) - foreach ($summe_fb as $fb=>$summe) + + foreach ($summe_oe as $oe=>$summe) { if(!isset($summe['m'])) $summe['m']=0; if(!isset($summe['w'])) $summe['w']=0; - - if(isset($fachbereiche[$fb])) - $worksheet->write($zeile,$fachbereiche[$fb],number_format($summe['m'],2,'.',''), $format_bold_center_data); - $worksheet->write($zeile,$fachbereiche[$fb]+1,number_format($summe['w'],2,'.',''), $format_bold_center_data); + + if(isset($organisationseinheiten_idx[$oe])) + $worksheet->write($zeile,$organisationseinheiten_idx[$oe],number_format($summe['m'],2,'.',''), $format_bold_center_data); + $worksheet->write($zeile,$organisationseinheiten_idx[$oe]+1,number_format($summe['w'],2,'.',''), $format_bold_center_data); $gesamt = $summe['m']+$summe['w']; - $worksheet->write(++$zeile,$fachbereiche[$fb],number_format($gesamt,2,'.',''), $format_bold_center_data); - $worksheet->mergeCells($zeile,$fachbereiche[$fb],$zeile,$fachbereiche[$fb]+1); + $worksheet->write(++$zeile,$organisationseinheiten_idx[$oe],number_format($gesamt,2,'.',''), $format_bold_center_data); + $worksheet->mergeCells($zeile,$organisationseinheiten_idx[$oe],$zeile,$organisationseinheiten_idx[$oe]+1); --$zeile; } @@ -303,72 +289,70 @@ else } td { - + } '; - - echo "

ALVS $stsem

"; echo ''; echo ''; - $summe_fb = array(); + $summe_oe = array(); - foreach ($fachbereiche as $fb) + foreach ($organisationseinheiten as $oe) { - echo ""; - $summe_fb[$fb]=array(); + echo ""; + $summe_oe[$oe]=array(); } echo ""; - $summe_fb['betreuungen']=array(); + $summe_oe['betreuungen']=array(); echo ""; echo ""; // Spalten m/w echo ''; - foreach ($fachbereiche as $fb) + foreach ($organisationseinheiten as $oe) { echo ""; } echo ""; echo ""; - //$summe_fb['betreuungen']=0; + echo ""; echo ""; echo ""; echo ""; - // Für jeden Fachbereich eine Variable definieren - foreach ($fachbereiche as $fb) + // Für jede OE eine Variable definieren + foreach ($organisationseinheiten as $oe) { - $summe_fb[$fb]["m"] = 0; - $summe_fb[$fb]["w"] = 0; + $summe_oe[$oe]["m"] = 0; + $summe_oe[$oe]["w"] = 0; } - $summe_fb['betreuungen']['m'] = 0; - $summe_fb['betreuungen']['w'] = 0; + $summe_oe['betreuungen']['m'] = 0; + $summe_oe['betreuungen']['w'] = 0; foreach ($data as $key=>$val) { echo ""; echo ""; $summe_m =0; $summe_w =0; - foreach ($fachbereiche as $fb) + foreach ($organisationseinheiten as $oe) { - if(isset($data[$key][$fb]["m"])) + if(isset($data[$key][$oe]["m"])) { - $summe_m+=$data[$key][$fb]["m"]; - $summe_fb[$fb]["m"]+=$data[$key][$fb]["m"]; - echo ""; + $summe_m+=$data[$key][$oe]["m"]; + $summe_oe[$oe]["m"]+=$data[$key][$oe]["m"]; + echo ""; } else echo ""; - if(isset($data[$key][$fb]["w"])) + if(isset($data[$key][$oe]["w"])) { - $summe_w+=$data[$key][$fb]["w"]; - $summe_fb[$fb]["w"]+=$data[$key][$fb]["w"]; - echo ""; + $summe_w+=$data[$key][$oe]["w"]; + $summe_oe[$oe]["w"]+=$data[$key][$oe]["w"]; + echo ""; } else echo ""; @@ -376,7 +360,7 @@ else if(isset($data[$key]['betreuungen']['m'])) { echo ""; - $summe_fb['betreuungen']['m']+=$data[$key]['betreuungen']['m']; + $summe_oe['betreuungen']['m']+=$data[$key]['betreuungen']['m']; $summe_m+=$data[$key]['betreuungen']['m']; } else @@ -384,7 +368,7 @@ else if(isset($data[$key]['betreuungen']['w'])) { echo ""; - $summe_fb['betreuungen']['w']+=$data[$key]['betreuungen']['w']; + $summe_oe['betreuungen']['w']+=$data[$key]['betreuungen']['w']; $summe_w+=$data[$key]['betreuungen']['w']; } else @@ -398,44 +382,44 @@ else echo ""; echo ""; - foreach ($fachbereiche as $fb) + foreach ($organisationseinheiten as $oe) { - if(isset($summe_fb[$fb]["m"])) - echo ""; + if(isset($summe_oe[$oe]["m"])) + echo ""; else echo ""; - if(isset($summe_fb[$fb]["w"])) - echo ""; + if(isset($summe_oe[$oe]["w"])) + echo ""; else echo ""; } - if(isset($summe_fb['betreuungen']['m'])) - echo ""; + if(isset($summe_oe['betreuungen']['m'])) + echo ""; else echo ""; - if(isset($summe_fb['betreuungen']['w'])) - echo ""; + if(isset($summe_oe['betreuungen']['w'])) + echo ""; else echo ""; echo ""; echo ""; - + echo ""; //echo ""; - foreach ($fachbereiche as $fb) + foreach ($organisationseinheiten as $oe) { - if(isset($summe_fb[$fb]["m"]) || isset($summe_fb[$fb]["w"])) - echo ""; + if(isset($summe_oe[$oe]["m"]) || isset($summe_oe[$oe]["w"])) + echo ""; else echo ""; } - if(isset($summe_fb['betreuungen']['m']) || isset($summe_fb['betreuungen']['w'])) - echo ""; + if(isset($summe_oe['betreuungen']['m']) || isset($summe_oe['betreuungen']['w'])) + echo ""; else echo ""; echo ""; echo ""; - + echo '
'.$stsem.'".$fb_arr[$fb]."".$oe_arr[$oe]."BetreuungenSumme
 mwmwmwGesamt
".$stg_arr[$key]."".$data[$key][$fb]["m"]."".$data[$key][$oe]["m"]." ".$data[$key][$fb]["w"]."".$data[$key][$oe]["w"]." ".number_format($data[$key]['betreuungen']['m'],2)."".number_format($data[$key]['betreuungen']['w'],2)."
Summe".$summe_fb[$fb]["m"]."".$summe_oe[$oe]["m"]." ".$summe_fb[$fb]["w"]."".$summe_oe[$oe]["w"]." ".number_format($summe_fb['betreuungen']['m'],2)."".number_format($summe_oe['betreuungen']['m'],2)." ".number_format($summe_fb['betreuungen']['w'],2)."".number_format($summe_oe['betreuungen']['w'],2)."  
".($summe_fb[$fb]["m"] + $summe_fb[$fb]["w"])."".($summe_oe[$oe]["m"] + $summe_oe[$oe]["w"])." ".number_format(($summe_fb['betreuungen']['m'] + $summe_fb['betreuungen']['w']),2)."".number_format(($summe_oe['betreuungen']['m'] + $summe_oe['betreuungen']['w']),2)."  
'; echo ' '; diff --git a/content/statistik/lvplanung.php b/content/statistik/lvplanung.php index bff0417d5..be06f5c12 100644 --- a/content/statistik/lvplanung.php +++ b/content/statistik/lvplanung.php @@ -25,6 +25,7 @@ require_once('../../include/lehrveranstaltung.class.php'); require_once('../../include/studiengang.class.php'); require_once('../../include/person.class.php'); require_once('../../include/benutzer.class.php'); +require_once('../../include/benutzerberechtigung.class.php'); if(isset($_GET['studiengang_kz'])) $studiengang_kz = $_GET['studiengang_kz']; @@ -43,12 +44,18 @@ else if(isset($_GET['oe_kurzbz'])) $oe_kurzbz = $_GET['oe_kurzbz']; -else +else $oe_kurzbz = ''; $user = get_uid(); loadVariables($user); +$rechte = new benutzerberechtigung(); +$rechte->getBerechtigungen($user); + +if(!$rechte->isBerechtigt('assistenz', null, 's')) + die($rechte->errormsg); + $db = new basis_db(); $stg_arr = array(); @@ -62,6 +69,10 @@ if($studiengang_kz!='') { $studiengang = new studiengang(); $studiengang->load($studiengang_kz); + + if(!$rechte->isBerechtigt('assistenz', $studiengang->oe_kurzbz, 's')) + die($rechte->errormsg); + } if($mitarbeiter_uid!='') @@ -159,9 +170,9 @@ $qry = "SELECT tbl_person.person_id=tbl_benutzer.person_id AND lehrfach.oe_kurzbz=".$db->db_add_param($oe_kurzbz)." AND tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell); - $qry.=" ORDER BY tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.semester, tbl_lehrveranstaltung.bezeichnung, tbl_lehrveranstaltung.lehrveranstaltung_id, tbl_lehreinheit.lehreinheit_id"; + $qry.=" ORDER BY tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.semester, tbl_lehrveranstaltung.bezeichnung, tbl_lehrveranstaltung.lehrveranstaltung_id, tbl_lehreinheit.lehreinheit_id"; } -else +else die('Fehlerhafte Parameteruebergabe'); echo ''; @@ -309,7 +320,7 @@ elseif($oe_kurzbz!='') (tbl_projektbetreuer.faktor*tbl_projektbetreuer.stundensatz*tbl_projektbetreuer.stunden)>0 "; } -else +else die('Something unexpected happend'); if($result = $db->db_query($qry)) @@ -329,7 +340,7 @@ if($result = $db->db_query($qry)) echo ""; echo ''; echo ''; - + $gesamtkosten_betreuung=0; $stunden_betreuung=0; while($row = $db->db_fetch_object($result)) diff --git a/content/statistik/lvplanung.xls.php b/content/statistik/lvplanung.xls.php index 237fbe703..c46f695dc 100644 --- a/content/statistik/lvplanung.xls.php +++ b/content/statistik/lvplanung.xls.php @@ -27,6 +27,8 @@ require_once('../../include/Excel/excel.php'); require_once('../../include/person.class.php'); require_once('../../include/benutzer.class.php'); require_once('../../include/mitarbeiter.class.php'); +require_once('../../include/organisationseinheit.class.php'); +require_once('../../include/benutzerberechtigung.class.php'); $user = get_uid(); @@ -36,119 +38,114 @@ if(isset($_GET['studiensemester_kurzbz'])) $studiensemester_kurzbz = $_GET['studiensemester_kurzbz']; else if(isset($_POST['studiensemester_kurzbz'])) $studiensemester_kurzbz = $_POST['studiensemester_kurzbz']; -else +else die('studiensemester_kurzbz muss uebergeben werden'); - + if(isset($_GET['studiengang_kz'])) $studiengang_kz = $_GET['studiengang_kz']; -else +else $studiengang_kz=''; - + if(isset($_GET['semester'])) $semester = $_GET['semester']; -else +else $semester=''; if(isset($_GET['oe_kurzbz'])) $oe_kurzbz = $_GET['oe_kurzbz']; -else +else $oe_kurzbz = ''; - + if(isset($_GET['uid'])) $uid = $_GET['uid']; -else +else $uid = ''; - + $db = new basis_db(); +$rechte = new benutzerberechtigung(); +$rechte->getBerechtigungen($user); + +if($studiengang_kz != '') +{ + if(!$rechte->isBerechtigt('assistenz', $studiengang_kz, 's')) + die($rechte->errormsg); +} +elseif($oe_kurzbz!='') +{ + if(!$rechte->isBerechtigt('assistenz', $oe_kurzbz, 's')) + die($rechte->errormsg); +} +else +{ + if(!$rechte->isBerechtigt('assistenz', null, 's')) + die($rechte->errormsg); +} + +$oetyp = new organisationseinheit(); +$oetyp->getTypen(); + +foreach($oetyp->result as $row) +{ + $oetyp_arr[$row->organisationseinheittyp_kurzbz] = $row->bezeichnung; +} + +$oe = new organisationseinheit(); +$oe->getAll(); + +foreach($oe->result as $row) +{ + $oe_arr[$row->oe_kurzbz] = $oetyp_arr[$row->organisationseinheittyp_kurzbz].' '.$row->bezeichnung; +} + $stg_obj = new studiengang(); $stg_obj->getAll('typ, kurzbz', false); $qry = " -SELECT (SELECT nachname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) - WHERE uid=COALESCE(tbl_lehrveranstaltung.koordinator, (SELECT uid FROM public.tbl_benutzerfunktion - WHERE fachbereich_kurzbz=tbl_fachbereich.fachbereich_kurzbz AND - tbl_lehrveranstaltung.studiengang_kz=(SELECT studiengang_kz FROM public.tbl_studiengang WHERE oe_kurzbz=tbl_benutzerfunktion.oe_kurzbz LIMIT 1) AND - funktion_kurzbz='fbk' AND - (tbl_benutzerfunktion.datum_von is null OR tbl_benutzerfunktion.datum_von<=now()) AND - (tbl_benutzerfunktion.datum_bis is null OR tbl_benutzerfunktion.datum_bis>=now()) - LIMIT 1 - ) - ) - ) as koordinator, - (SELECT vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) - WHERE uid=COALESCE(tbl_lehrveranstaltung.koordinator, (SELECT uid FROM public.tbl_benutzerfunktion - WHERE fachbereich_kurzbz=tbl_fachbereich.fachbereich_kurzbz AND - tbl_lehrveranstaltung.studiengang_kz=(SELECT studiengang_kz FROM public.tbl_studiengang WHERE oe_kurzbz=tbl_benutzerfunktion.oe_kurzbz LIMIT 1) AND - funktion_kurzbz='fbk' AND - (tbl_benutzerfunktion.datum_von is null OR tbl_benutzerfunktion.datum_von<=now()) AND - (tbl_benutzerfunktion.datum_bis is null OR tbl_benutzerfunktion.datum_bis>=now()) - LIMIT 1 - ) - ) - ) as vorname, - - lehrfach.bezeichnung as lf_bezeichnung, tbl_lehrveranstaltung.studiengang_kz, - tbl_fachbereich.fachbereich_kurzbz as fachbereich_kurzbz, tbl_lehreinheitmitarbeiter.mitarbeiter_uid, +SELECT + lehrfach.bezeichnung as lf_bezeichnung, tbl_lehrveranstaltung.studiengang_kz, lehrfach.oe_kurzbz as lehrfach_oe_kurzbz, + tbl_lehreinheitmitarbeiter.mitarbeiter_uid, tbl_lehrveranstaltung.semester as lv_semester, tbl_lehreinheit.lehreinheit_id, tbl_lehreinheitmitarbeiter.faktor, - tbl_lehreinheitmitarbeiter.stundensatz, + tbl_lehreinheitmitarbeiter.stundensatz, tbl_lehreinheitmitarbeiter.semesterstunden lemss, tbl_lehreinheitmitarbeiter.planstunden, tbl_lehreinheit.stundenblockung, tbl_lehreinheit.wochenrythmus, tbl_lehreinheit.raumtyp, tbl_lehreinheit.raumtypalternativ, tbl_lehreinheitmitarbeiter.anmerkung ,tbl_lehreinheit.studiensemester_kurzbz ,tbl_lehrveranstaltung.ects - ,tbl_lehrveranstaltung.semesterstunden + ,tbl_lehrveranstaltung.semesterstunden ,tbl_lehrveranstaltung.semesterstunden as sws ,tbl_lehrveranstaltung.lehrform_kurzbz ,tbl_lehrveranstaltung.lehrveranstaltung_id - ,(SELECT nachname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) + ,(SELECT nachname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=(SELECT mitarbeiter_uid FROM lehre.tbl_lehreinheitmitarbeiter WHERE lehre.tbl_lehreinheitmitarbeiter.lehreinheit_id=lehre.tbl_lehreinheit.lehreinheit_id and lehre.tbl_lehreinheitmitarbeiter.lehrfunktion_kurzbz='LV-Leitung' LIMIT 1) - )as lv_leitung - ,(SELECT vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) + )as lv_leitung + ,(SELECT vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=(SELECT mitarbeiter_uid FROM lehre.tbl_lehreinheitmitarbeiter WHERE lehre.tbl_lehreinheitmitarbeiter.lehreinheit_id=lehre.tbl_lehreinheit.lehreinheit_id and lehre.tbl_lehreinheitmitarbeiter.lehrfunktion_kurzbz='LV-Leitung' LIMIT 1) - )as lv_leitung_vorname + )as lv_leitung_vorname ,(SELECT bezeichnung FROM lehre.tbl_lehrform WHERE lehre.tbl_lehrform.lehrform_kurzbz=tbl_lehrveranstaltung.lehrform_kurzbz LIMIT 1) as lv_type ,tbl_lehrveranstaltung.lehrform_kurzbz -FROM - lehre.tbl_lehrveranstaltung - JOIN lehre.tbl_lehreinheit USING(lehrveranstaltung_id) - JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id) +FROM + lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_lehreinheit USING(lehrveranstaltung_id) + JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id) JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id) - LEFT JOIN public.tbl_fachbereich ON(lehrfach.oe_kurzbz=tbl_fachbereich.oe_kurzbz) -WHERE - tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($studiensemester_kurzbz); +WHERE + tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($studiensemester_kurzbz); -# ,(SELECT lv_semesterstunden FROM campus.vw_lehreinheit WHERE lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id and lehreinheit_id=lehre.tbl_lehreinheit.lehreinheit_id and studiensemester_kurzbz='".addslashes($studiensemester_kurzbz)."' LIMIT 1) as sws - if($studiengang_kz!='') $qry.=" AND tbl_lehrveranstaltung.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER); - + if($oe_kurzbz!='') - $qry.=" AND tbl_fachbereich.oe_kurzbz=".$db->db_add_param($oe_kurzbz); + $qry.=" AND lehrfach.oe_kurzbz=".$db->db_add_param($oe_kurzbz); if($semester!='') $qry.=" AND tbl_lehrveranstaltung.semester=".$db->db_add_param($semester, FHC_INTEGER); - + if($uid!='') $qry.=" AND tbl_lehreinheitmitarbeiter.mitarbeiter_uid=".$db->db_add_param($uid); $qry.=" ORDER BY tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.semester, tbl_lehrveranstaltung.bezeichnung"; -/* -// exit($qry); -if($result = $db->db_query($qry)) -{ - $row = $db->db_fetch_object($result); - var_dump($row); -} -else - echo 'nix
'; -var_dump($stg_obj); -exit; -*/ - - - // Creating a workbook $workbook = new Spreadsheet_Excel_Writer(); @@ -174,10 +171,8 @@ $zeile=0; $spalte=0; $worksheet->write($zeile,$spalte,"Studiengang", $format_bold); $maxlength[$spalte]=11; -$worksheet->write($zeile,++$spalte,"Institut", $format_bold); +$worksheet->write($zeile,++$spalte,"Organisationseinheit", $format_bold); $maxlength[$spalte]=8; -$worksheet->write($zeile,++$spalte,"Koordinator", $format_bold); -$maxlength[$spalte]=11; $worksheet->write($zeile,++$spalte,"Lektor", $format_bold); $maxlength[$spalte]=6; $worksheet->write($zeile,++$spalte,"Lehrfach", $format_bold); @@ -227,22 +222,20 @@ if($result = $db->db_query($qry)) $spalte=0; $zeile++; - + $mitarbeiter = new mitarbeiter(); $mitarbeiter->load($row->mitarbeiter_uid); - + //Studiengang $worksheet->write($zeile,$spalte,$stg_obj->kuerzel_arr[$row->studiengang_kz]); if($maxlength[$spalte]kuerzel_arr[$row->studiengang_kz])) $maxlength[$spalte]=mb_strlen($stg_obj->kuerzel_arr[$row->studiengang_kz]); - //Fachbereich - $worksheet->write($zeile,++$spalte,$row->fachbereich_kurzbz); - if($maxlength[$spalte]fachbereich_kurzbz)) - $maxlength[$spalte]=mb_strlen($row->fachbereich_kurzbz); - //Koordinator - $worksheet->write($zeile,++$spalte,$row->koordinator.' '.$row->vorname); - if($maxlength[$spalte]koordinator.' '.$row->vorname)) - $maxlength[$spalte]=mb_strlen($row->koordinator.' '.$row->vorname); + + //Organisationseinheit + $worksheet->write($zeile,++$spalte,$oe_arr[$row->lehrfach_oe_kurzbz]); + if($maxlength[$spalte]lehrfach_oe_kurzbz])) + $maxlength[$spalte]=mb_strlen($oe_arr[$row->lehrfach_oe_kurzbz]); + //Lektor $worksheet->write($zeile,++$spalte,$mitarbeiter->nachname.' '.$mitarbeiter->vorname); if($maxlength[$spalte]nachname.' '.$mitarbeiter->vorname)) @@ -255,7 +248,7 @@ if($result = $db->db_query($qry)) $worksheet->write($zeile,++$spalte,$row->lv_semester); if($maxlength[$spalte]lv_semester)) $maxlength[$spalte]=mb_strlen($row->lv_semester); - + $qry = "SELECT * FROM lehre.tbl_lehreinheitgruppe WHERE lehreinheit_id=".$db->db_add_param($row->lehreinheit_id, FHC_INTEGER); $result_gruppe = $db->db_query($qry); $gruppe = ''; @@ -265,10 +258,10 @@ if($result = $db->db_query($qry)) $gruppe.=', '; if($row_gruppe->gruppe_kurzbz!='') $gruppe.=$row_gruppe->gruppe_kurzbz; - else + else $gruppe.=trim($stg_obj->kuerzel_arr[$row_gruppe->studiengang_kz].'-'.$row_gruppe->semester.$row_gruppe->verband.$row_gruppe->gruppe); } - + //Gruppen $worksheet->write($zeile,++$spalte,$gruppe); if($maxlength[$spalte]db_query($qry)) $worksheet->write($zeile,++$spalte,$row->lemss); if($maxlength[$spalte]lemss)) $maxlength[$spalte]=mb_strlen($row->lemss); - + $kosten = ($row->stundensatz*$row->lemss*$row->faktor); - + //Kosten $worksheet->write($zeile,++$spalte,$kosten); if($maxlength[$spalte]db_query($qry)) $worksheet->write($zeile,++$spalte,$row->anmerkung); if($maxlength[$spalte]anmerkung)) $maxlength[$spalte]=mb_strlen($row->anmerkung); - -// Neu 13.11.2009 sequens + //LV-Leitung $worksheet->write($zeile,++$spalte,$row->lv_leitung.' '.$row->lv_leitung_vorname); if($maxlength[$spalte]lv_leitung.' '.$row->lv_leitung_vorname)) @@ -320,22 +312,15 @@ if($result = $db->db_query($qry)) if($maxlength[$spalte]lehrveranstaltung_id)) $maxlength[$spalte]=mb_strlen($row->lehrveranstaltung_id); - //SWS - - -/* $worksheet->write($zeile,++$spalte,$row->sws); - if($maxlength[$spalte]sws)) - $maxlength[$spalte]=mb_strlen($row->sws); -*/ + //Semesterstunden $semesterstunden = $row->semesterstunden; if ($row->stundensatz==0 || $row->lemss==0 || $row->faktor==0) $semesterstunden = 0; - + $worksheet->write($zeile,++$spalte,$semesterstunden); if($maxlength[$spalte]write($zeile,++$spalte,$row->ects); if($maxlength[$spalte]ects)) @@ -347,51 +332,28 @@ if($result = $db->db_query($qry)) $worksheet->write($zeile,++$spalte,$row->lv_type); if($maxlength[$spalte]lv_type)) $maxlength[$spalte]=mb_strlen($row->lv_type); - + } - + //Betreuungen $qry = "SELECT - tbl_lehrveranstaltung.studiengang_kz, fachbereich_kurzbz, - (SELECT nachname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) - WHERE uid=COALESCE(tbl_lehrveranstaltung.koordinator, (SELECT uid FROM public.tbl_benutzerfunktion - WHERE fachbereich_kurzbz=tbl_fachbereich.fachbereich_kurzbz AND - tbl_lehrveranstaltung.studiengang_kz=(SELECT studiengang_kz FROM public.tbl_studiengang WHERE oe_kurzbz=tbl_benutzerfunktion.oe_kurzbz LIMIT 1) AND - funktion_kurzbz='fbk' AND - (tbl_benutzerfunktion.datum_von is null OR tbl_benutzerfunktion.datum_von<=now()) AND - (tbl_benutzerfunktion.datum_bis is null OR tbl_benutzerfunktion.datum_bis>=now()) - LIMIT 1 - ) - ) - ) as koordinator, - (SELECT vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) - WHERE uid=COALESCE(tbl_lehrveranstaltung.koordinator, (SELECT uid FROM public.tbl_benutzerfunktion - WHERE fachbereich_kurzbz=tbl_fachbereich.fachbereich_kurzbz AND - tbl_lehrveranstaltung.studiengang_kz=(SELECT studiengang_kz FROM public.tbl_studiengang WHERE oe_kurzbz=tbl_benutzerfunktion.oe_kurzbz LIMIT 1) AND - funktion_kurzbz='fbk' AND - (tbl_benutzerfunktion.datum_von is null OR tbl_benutzerfunktion.datum_von<=now()) AND - (tbl_benutzerfunktion.datum_bis is null OR tbl_benutzerfunktion.datum_bis>=now()) - LIMIT 1 - ) - ) - ) as koordinator_vorname, nachname, vorname, lehrfach.bezeichnung, - tbl_lehrveranstaltung.semester, student_uid, stunden, tbl_projektbetreuer.stundensatz, + tbl_lehrveranstaltung.studiengang_kz, lehrfach.oe_kurzbz as lehrfach_oe_kurzbz, + nachname, vorname, lehrfach.bezeichnung, + tbl_lehrveranstaltung.semester, student_uid, stunden, tbl_projektbetreuer.stundensatz, tbl_projektbetreuer.faktor FROM - lehre.tbl_projektarbeit, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, - lehre.tbl_projektbetreuer, public.tbl_person, lehre.tbl_lehrveranstaltung as lehrfach, public.tbl_fachbereich + lehre.tbl_projektarbeit, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, + lehre.tbl_projektbetreuer, public.tbl_person, lehre.tbl_lehrveranstaltung as lehrfach WHERE tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id AND tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id AND - lehrfach.oe_kurzbz=tbl_fachbereich.oe_kurzbz AND tbl_person.person_id=tbl_projektbetreuer.person_id AND tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($studiensemester_kurzbz)." AND (tbl_projektbetreuer.faktor*tbl_projektbetreuer.stundensatz*tbl_projektbetreuer.stunden)>0 "; - if($uid!=='') { $mitarbeiter = new mitarbeiter($uid); @@ -399,11 +361,11 @@ if($result = $db->db_query($qry)) } if($oe_kurzbz!='') - $qry.=" AND tbl_fachbereich.oe_kurzbz=".$db->db_add_param($oe_kurzbz); - + $qry.=" AND lehrfach.oe_kurzbz=".$db->db_add_param($oe_kurzbz); + if($studiengang_kz!='') $qry.=" AND tbl_lehrveranstaltung.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER); - + if($result = $db->db_query($qry)) { $spalte=0; @@ -415,20 +377,17 @@ if($result = $db->db_query($qry)) { $spalte=0; $zeile++; - + //Studiengang $worksheet->write($zeile,$spalte,$stg_obj->kuerzel_arr[$row->studiengang_kz]); if($maxlength[$spalte]kuerzel_arr[$row->studiengang_kz])) $maxlength[$spalte]=mb_strlen($stg_obj->kuerzel_arr[$row->studiengang_kz]); - - //Fachbereich - $worksheet->write($zeile,++$spalte,$row->fachbereich_kurzbz); - if($maxlength[$spalte]fachbereich_kurzbz)) - $maxlength[$spalte]=mb_strlen($row->fachbereich_kurzbz); - //Koordinator - $worksheet->write($zeile,++$spalte,$row->koordinator.' '.$row->koordinator_vorname); - if($maxlength[$spalte]koordinator.' '.$row->koordinator_vorname)) - $maxlength[$spalte]=mb_strlen($row->koordinator.' '.$row->koordinator_vorname); + + //Organisationseinheit + $worksheet->write($zeile,++$spalte,$oe_arr[$row->lehrfach_oe_kurzbz]); + if($maxlength[$spalte]lehrfach_oe_kurzbz])) + $maxlength[$spalte]=mb_strlen($oe_arr[$row->lehrfach_oe_kurzbz]); + //Lektor $worksheet->write($zeile,++$spalte,$row->nachname.' '.$row->vorname); if($maxlength[$spalte]nachname.' '.$row->vorname)) @@ -441,7 +400,7 @@ if($result = $db->db_query($qry)) $worksheet->write($zeile,++$spalte,$row->semester); if($maxlength[$spalte]semester)) $maxlength[$spalte]=mb_strlen($row->semester); - + $benutzer = new benutzer(); $benutzer->load($row->student_uid); //Student @@ -456,10 +415,10 @@ if($result = $db->db_query($qry)) $worksheet->write($zeile,++$spalte,$row->stunden*$row->stundensatz*$row->faktor); if($maxlength[$spalte]stunden*$row->stundensatz*$row->faktor)) $maxlength[$spalte]=mb_strlen($row->stunden*$row->stundensatz*$row->faktor); - + } } - + //Die Breite der Spalten setzen foreach($maxlength as $i=>$breite) $worksheet->setColumn($i, $i, $breite+2); From 57166136d07f31abe0af506a9f4d54eb0c96bbbc Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 22 Oct 2018 14:59:29 +0200 Subject: [PATCH 03/58] Added Sancho Helper: send mail in Sancho design & Sancho pics . sancho.inc.php added function to send mail in Sancho design. . added 2 new jpg-Sancho-header-images --- include/sancho.inc.php | 214 ++++++++++++++++++ skin/images/sancho/sancho_header_DEFAULT.jpg | Bin 0 -> 41909 bytes .../sancho_header_confirm_timesheet.jpg | Bin 0 -> 97212 bytes 3 files changed, 214 insertions(+) create mode 100644 include/sancho.inc.php create mode 100644 skin/images/sancho/sancho_header_DEFAULT.jpg create mode 100644 skin/images/sancho/sancho_header_confirm_timesheet.jpg diff --git a/include/sancho.inc.php b/include/sancho.inc.php new file mode 100644 index 000000000..a57bc8428 --- /dev/null +++ b/include/sancho.inc.php @@ -0,0 +1,214 @@ + + */ +require_once(dirname(__FILE__).'/basis_db.class.php'); +require_once(dirname(__FILE__).'/mail.class.php'); +require_once(dirname(__FILE__).'/vorlage.class.php'); + +const DEFAULT_SANCHO_HEADER_IMG = 'sancho_header_DEFAULT.jpg'; + +/** + * Send single Mail with Sancho Design and Layout. + * @param string $vorlage_kurzbz Name of the template for specific mail content. + * @param array $vorlage_data Associative array with specific mail content varibales + * to be replaced in the content template. + * @param string $to Email-adress. + * @param string $subject Subject of mail. + * @param string $headerImg Filename of the specific Sancho header image. + * @return boolean True, if succeeded. + */ +function sendSanchoMail($vorlage_kurzbz, $vorlage_data, $to, $subject, $headerImg = DEFAULT_SANCHO_HEADER_IMG) +{ + $from = 'sancho@'. DOMAIN; + $sanchoHeader_img = dirname(__FILE__). '/../skin/images/sancho/'. $headerImg; + $sanchoFooter_img = dirname(__FILE__). '/../skin/images/sancho/sancho_footer.jpg'; + + // Set unique content id for embedding header and footer image + $cid_header = uniqid(); + $cid_footer = uniqid(); + + // Set specific mail content into specific content template + $content = parseMailContent($vorlage_kurzbz, $vorlage_data); + + // Create data array with specific content and image content ids + $layout = array( + 'CID_header' => $cid_header, + 'CID_footer' => $cid_footer, + 'content' => $content + ); + + // Set the data array into overall sancho mail template + $body = parseMailContent('Sancho_Mail_Template', $layout); + + // Send mail + $mail = new Mail($to, $from, $subject, $body); + + // * embed the images + $mail->addEmbeddedImage($sanchoHeader_img, 'image/jpg', '', $cid_header); + $mail->addEmbeddedImage($sanchoFooter_img, 'image/jpg', '', $cid_footer); + + // * embed the html content + $mail->setHTMLContent($body); + + return $mail->send(); +} + + +// ******************************************* HELPER FUNCTIONS +/** + * Replace variables in the mail content template with specific mail content data. + * @param string $vorlage_kurzbz Name of the template for specific mail content. + * @param array $vorlage_data Associative array with specific mail content varibales + * to be replaced in the content template. + * @return string + */ +function parseMailContent($vorlage_kurzbz, $vorlage_data) +{ + $vorlage = new Vorlage(); + $vorlage->getAktuelleVorlage('etw', $vorlage_kurzbz); + + // If the text and the subject of the template are not empty + if (!empty($vorlage->text)) + { + // Parses template text + $parsedText = parseVorlagetext($vorlage->text, $vorlage_data); + + return $parsedText; + } +} + +/** + * parseVorlagetext() - will parse a Vorlagetext. + * + * @param string $text REQUIRED + * @param array $data REQUIRED + * @return string + */ +function parseVorlagetext($text, $data = array()) +{ + if (empty($text)) + return 'Error in parsing Vorlagentext'; + $text = parse_string($text, $data, true); + return $text; +} + +/** + * Parse a String + * + * Parses pseudo-variables contained in the specified string, + * replacing them with the data in the second param + * + * @param string + * @param array + * @param bool + * @return string + */ +function parse_string($template, $data, $return = FALSE) +{ + if ($template === '') + { + return FALSE; + } + + $replace = array(); + foreach ($data as $key => $val) + { + $replace = array_merge( + $replace, + is_array($val) + ? parse_pair($key, $val, $template) + : parse_single($key, (string) $val, $template) + ); + } + + unset($data); + $template = strtr($template, $replace); + + if ($template === FALSE) + { + return false; + } + + return $template; +} + +/** + * Parse a single key/value + * + * @param string + * @param string + * @param string + * @return string + */ +function parse_single($key, $val, $string) +{ + return array('{'. $key. '}' => (string) $val); +} + +/** + * Parse a tag pair + * + * Parses tag pairs: {some_tag} string... {/some_tag} + * + * @param string + * @param array + * @param string + * @return string + */ +function parse_pair($variable, $data, $string) +{ + $replace = array(); + preg_match_all( + '#'.preg_quote('{'. $variable. '}').'(.+?)'.preg_quote('{'.'/'.$variable. '}').'#s', + $string, + $matches, + PREG_SET_ORDER + ); + + foreach ($matches as $match) + { + $str = ''; + foreach ($data as $row) + { + $temp = array(); + foreach ($row as $key => $val) + { + if (is_array($val)) + { + $pair = parse_pair($key, $val, $match[1]); + if ( ! empty($pair)) + { + $temp = array_merge($temp, $pair); + } + + continue; + } + + $temp['{'.$key. '}'] = $val; + } + + $str .= strtr($match[1], $temp); + } + + $replace[$match[0]] = $str; + } + + return $replace; +} diff --git a/skin/images/sancho/sancho_header_DEFAULT.jpg b/skin/images/sancho/sancho_header_DEFAULT.jpg new file mode 100644 index 0000000000000000000000000000000000000000..407583318b387ed3d5e76c92aeb325d67e457881 GIT binary patch literal 41909 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�(Y3DGW^+Dd50li%pc4WdwN^tu2#2AJ~~WA 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 literal 0 HcmV?d00001 diff --git a/skin/images/sancho/sancho_header_confirm_timesheet.jpg b/skin/images/sancho/sancho_header_confirm_timesheet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..de21591fe7c4ef3a419476033b9d8a0e22392a17 GIT binary patch literal 97212 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 b=|fwuT-f*jJpQK+|Bn}eAIm89&D?(hlx`aq literal 0 HcmV?d00001 From 3423830f602a67b4b1cc6d4372701ea1d9ce9ce6 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 22 Oct 2018 15:28:21 +0200 Subject: [PATCH 04/58] - priority display and priority change possible on infocenterdetails page - different sort order of zgvpruefungen (prestudenten) --- .../system/infocenter/InfoCenter.php | 157 ++++++++++-- application/models/crm/Prestudent_model.php | 225 ++++++++++++++++++ .../models/crm/Prestudentstatus_model.php | 3 +- .../system/infocenter/infocenterDetails.php | 4 +- .../views/system/infocenter/zgvpruefungen.php | 67 ++++-- public/css/sbadmin2/admintemplate.css | 26 +- public/js/bootstrapper.js | 8 +- public/js/infocenter/infocenterDetails.js | 211 +++++++++++----- system/phrasesupdate.php | 44 +++- 9 files changed, 630 insertions(+), 115 deletions(-) diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index 4662fbc40..f16c4472e 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -74,6 +74,7 @@ class InfoCenter extends Auth_Controller 'saveFormalGeprueft' => 'infocenter:rw', 'getLastPrestudentWithZgvJson' => 'infocenter:r', 'getZgvInfoForPrestudent' => 'infocenter:r', + 'saveBewPriorisierung' => 'infocenter:rw', 'saveZgvPruefung' => 'infocenter:rw', 'saveAbsage' => 'infocenter:rw', 'saveFreigabe' => 'infocenter:rw', @@ -81,6 +82,7 @@ class InfoCenter extends Auth_Controller 'updateNotiz' => 'infocenter:rw', 'reloadNotizen' => 'infocenter:r', 'reloadLogs' => 'infocenter:r', + 'reloadZgvPruefungen' => 'infocenter:r', 'outputAkteContent' => 'infocenter:r', 'getParkedDate' => 'infocenter:r', 'park' => 'infocenter:rw', @@ -280,6 +282,22 @@ class InfoCenter extends Auth_Controller $this->load->view('system/infocenter/studiengangZgvInfo.php', $data); } + /** + * Saves application priority for a prestudent + */ + public function saveBewPriorisierung() + { + $prestudent_id = $this->input->post('prestudentid'); + $change = $this->input->post('change'); + + if (!is_numeric($change) || !is_numeric($prestudent_id)) + $result = error('Parameteres missing'); + else + $result = $this->PrestudentModel->changePrio($prestudent_id, intval($change)); + + $this->output->set_content_type('application/json')->set_output(json_encode($result)); + } + /** * Saves a ZGV for a prestudent, includes Ort, Datum, Nation for bachelor and master * @param $prestudent_id @@ -543,6 +561,19 @@ class InfoCenter extends Auth_Controller $this->load->view('system/infocenter/logs.php', array('logs' => $logs)); } + /** + * Loads Zgv Prüfung view for a person, helper for reloading after ajax request + * @param $person_id + */ + public function reloadZgvPruefungen($person_id) + { + $prestudentdata = $this->_loadPrestudentData($person_id); + + $prestudentdata[self::FHC_CONTROLLER_ID] = $this->getControllerId(); + + $this->load->view('system/infocenter/zgvpruefungen.php', $prestudentdata); + } + /** * Outputs content of an Akte, sends appropriate headers (so the document can be downloaded) * @param $akte_id @@ -1058,6 +1089,8 @@ class InfoCenter extends Auth_Controller show_error($prestudenten->retval); } + $interessentenCount = array(); + foreach ($prestudenten->retval as $prestudent) { $prestudent = $this->PrestudentModel->getPrestudentWithZgv($prestudent->prestudent_id); @@ -1079,43 +1112,121 @@ class InfoCenter extends Auth_Controller //if prestudent is not interessent or is already bestaetigt, then show only as information, non-editable $zgvpruefung->infoonly = !isset($zgvpruefung->prestudentstatus) || isset($zgvpruefung->prestudentstatus->bestaetigtam) || $zgvpruefung->prestudentstatus->status_kurzbz != 'Interessent'; + //numeric application priority and arrows for changing + $zgvpruefung->changeup = false; + $zgvpruefung->changedown = false; + + if (isset($zgvpruefung->prestudentstatus->status_kurzbz) && $zgvpruefung->prestudentstatus->status_kurzbz == 'Interessent') + { + if (isset($zgvpruefung->prestudentstatus->studiensemester_kurzbz)) + { + $studiensemester = $zgvpruefung->prestudentstatus->studiensemester_kurzbz; + $zgvpruefung->changeup = $this->PrestudentModel->checkPrioChange($zgvpruefung->prestudent_id, $studiensemester, -1); + $zgvpruefung->changedown = $this->PrestudentModel->checkPrioChange($zgvpruefung->prestudent_id, $studiensemester, 1); + if (array_key_exists($studiensemester, $interessentenCount)) + $interessentenCount[$studiensemester]++; + else + $interessentenCount[$studiensemester] = 1; + } + } + $zgvpruefungen[] = $zgvpruefung; } - // Interessenten come first, otherwise by bewerbungsdatum desc, then by prestudent_id desc - usort($zgvpruefungen, function ($a, $b) { - $bewdatesort = isset($a->prestudentstatus) && isset($b->prestudentstatus) ? strcmp($b->prestudentstatus->bewerbung_abgeschicktamum, $a->prestudentstatus->bewerbung_abgeschicktamum) : 0; - $defaultsort = $bewdatesort === 0 ? (int)$b->prestudent_id - (int)$a->prestudent_id : $bewdatesort; - if (!isset($a->prestudentstatus->status_kurzbz) || !isset($b->prestudentstatus->status_kurzbz)) - return $defaultsort; - elseif ($a->prestudentstatus->status_kurzbz === 'Interessent' && $b->prestudentstatus->status_kurzbz === 'Interessent') - { - //infoonly Interessenten come after new Interessenten - if ($a->infoonly === $b->infoonly) - return $defaultsort; - elseif ($a->infoonly) - return 1; - elseif ($b->infoonly) - return -1; - } - elseif ($a->prestudentstatus->status_kurzbz === 'Interessent') - return -1; - elseif ($b->prestudentstatus->status_kurzbz === 'Interessent') - return 1; - else - return $defaultsort; - }); + $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); + + $this->_sortPrestudents($zgvpruefungen); $statusgruende = $this->StatusgrundModel->loadWhere(array('status_kurzbz' => 'Abgewiesener'))->retval; $data = array ( 'zgvpruefungen' => $zgvpruefungen, + 'numberinteressenten' => $interessentenCount, 'statusgruende' => $statusgruende ); return $data; } + /** + * Helper function for sorting prestudents + * @param $zgvpruefungen + */ + private function _sortPrestudents(&$zgvpruefungen) + { + usort($zgvpruefungen, function ($a, $b) { + //sort: + // 1: Studiensemester + if (isset($a->prestudentstatus->studiensemester_kurzbz) || isset($b->prestudentstatus->studiensemester_kurzbz)) + { + if (!isset($a->prestudentstatus->studiensemester_kurzbz)) + return 1; + elseif(!isset($b->prestudentstatus->studiensemester_kurzbz)) + return -1; + + $starta = $this->StudiensemesterModel->load($a->prestudentstatus->studiensemester_kurzbz); + if (!hasData($starta)) + { + show_error($starta->retval); + } + + $startb = $this->StudiensemesterModel->load($b->prestudentstatus->studiensemester_kurzbz); + if (!hasData($startb)) + { + show_error($startb->retval); + } + + $starta = date_format(date_create($starta->retval[0]->start), 'Y-m-d'); + $startb = date_format(date_create($startb->retval[0]->start), 'Y-m-d'); + + if ($starta > $startb) + return -1; + elseif ($starta < $startb) + return 1; + } + // 2: Status + if ($a->prestudentstatus->status_kurzbz !== $b->prestudentstatus->status_kurzbz) + { + if ($a->prestudentstatus->status_kurzbz === 'Interessent') + return -1; + elseif ($b->prestudentstatus->status_kurzbz === 'Interessent') + return 1; + } + + // 3: Priorisierung, Nulls last + if (isset($a->priorisierung) || isset($b->priorisierung)) + { + if (!isset($a->priorisierung)) + return 1; + elseif (!isset($b->priorisierung)) + return -1; + elseif ($a->priorisierung > $b->priorisierung) + return 1; + elseif ($a->priorisierung < $b->priorisierung) + return -1; + } + + // 4: Bewerbungsdatum + $starta = isset($a->prestudentstatus->bewerbung_abgeschicktamum) ? $a->prestudentstatus->bewerbung_abgeschicktamum : null; + $startb = isset($b->prestudentstatus->bewerbung_abgeschicktamum) ? $b->prestudentstatus->bewerbung_abgeschicktamum : null; + + if (isset($starta) || isset($startb)) + { + if (!isset($starta)) + return 1; + elseif(!isset($startb)) + return -1; + elseif ($starta > $startb) + return -1; + elseif ($starta < $startb) + return 1; + } + + // 5: prestudentid + return (int)$b->prestudent_id - (int)$a->prestudent_id; + }); + } + /** * Helper function for redirecting to initial page for person from a prestudent-specific page * @param $prestudent_id diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php index 4cfe08e9a..55215744e 100644 --- a/application/models/crm/Prestudent_model.php +++ b/application/models/crm/Prestudent_model.php @@ -278,4 +278,229 @@ class Prestudent_model extends DB_Model return $this->execQuery($qry, $parametersArray); } + + /** + * Returns a list with Bewerber (applicants) + * @param $person_id person who sent application(s) + * @param string $studiensemester_kurzbz + * @param bool $abgeschickt optional, wether application was filled out and sent + * @param bool $bestaetigt optional, wether application was confirmed by infocenter + * @return array with Bewerber + */ + public function getBewerber($person_id, $studiensemester_kurzbz = null, $abgeschickt = null, $bestaetigt = null) + { + $bewerber = array(); + $prestudents = $this->loadWhere(array('person_id' => $person_id)); + + if (!hasData($prestudents)) + return $bewerber; + + $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); + + foreach ($prestudents->retval as $prestudent) + { + $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent->prestudent_id, $studiensemester_kurzbz); + + if (!hasData($lastStatus)) + continue; + + $lastStatus = $lastStatus->retval[0]; + + if ($lastStatus->status_kurzbz !== 'Interessent') + continue; + + $bewerbung_abgeschicktamum = $lastStatus->bewerbung_abgeschicktamum; + $bestaetigtam = $lastStatus->bestaetigtam; + + $abgeschicktcond = true; + if (($abgeschickt === false && isset($bewerbung_abgeschicktamum)) || ($abgeschickt === true && !isset($bewerbung_abgeschicktamum))) + $abgeschicktcond = false; + + $bestaetigtcond = true; + if (($bestaetigt === false && isset($bestaetigtam)) || ($bestaetigt === true && !isset($bestaetigtam))) + $bestaetigtcond = false; + + if ($bestaetigtcond && $abgeschicktcond) + { + $prestudent->lastStatus = $lastStatus; + $bewerber[] = $prestudent; + } + } + + return $bewerber; + } + + /** + * Checks if application priority can be changed for a prestudent + * @param $prestudent_id + * @param $studiensemester Semester in which Prestudent applied + * @param $change increase priority (< 0) or decrease priority (> 0) + * @return bool wether priority can be changed + */ + public function checkPrioChange($prestudent_id, $studiensemester, $change) + { + if (!is_numeric($change)) + return false; + + $this->addSelect('person_id, priorisierung'); + $prestudent = $this->load($prestudent_id); + + if (!hasData($prestudent)) + return false; + + $person_id = $prestudent->retval[0]->person_id; + + $bewerberarr = $this->getBewerber($person_id, $studiensemester); + + if (count($bewerberarr) <= 1) + return false; + + if (!isset($prestudent->retval[0]->priorisierung)) + { + if ($change < 0) + return true; //null values can be changed to priority numbers, when there are other bewerber + else + return false; + } + + $priomin = 0; + $priomax = PHP_INT_MAX; + $currprio = intval($prestudent->retval[0]->priorisierung); + + foreach ($bewerberarr as $bewerber) + { + if (is_numeric($bewerber->priorisierung)) + { + $bewprio = intval($bewerber->priorisierung); + if ($bewprio < $priomax) + $priomax = $bewprio; + + if ($bewprio > $priomin) + $priomin = $bewprio; + } + } + + if (($currprio === $priomax && $change < 0)|| ($currprio === $priomin && $change > 0)) + { + return false; + } + + return true; + } + + /** + * Changes application priority for a prestudent + * Swaps priorities with nearest neighbour (nearest bewerber/prestudent) + * for the same studiensemester in order to move priority up/down + * @param $prestudent_id + * @param $change increase priority (< 0) or decrease priority (> 0) + * @return bool wether change of priority was sucessfull + */ + public function changePrio($prestudent_id, $change) + { + $this->addSelect('person_id, priorisierung'); + $prestudent = $this->load($prestudent_id); + + if (!hasData($prestudent)) + return false; + + $this->load->model('prestudentstatus_model', 'PrestudentstatusModel'); + $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id, null, 'Interessent'); + + if (!hasData($lastStatus)) + return false; + + $studiensemester_kurzbz = $lastStatus->retval[0]->studiensemester_kurzbz; + + if (!$this->checkPrioChange($prestudent_id, $studiensemester_kurzbz, $change)) + return false; + + $person_id = $prestudent->retval[0]->person_id; + $currprio = intval($prestudent->retval[0]->priorisierung); + + $difftonext = PHP_INT_MAX; + $neighbour = null; + + $bewerberarr = $this->getBewerber($person_id, $studiensemester_kurzbz ); + + foreach ($bewerberarr as $bewerber) + { + if (is_numeric($bewerber->priorisierung)) + { + $bewprio = intval($bewerber->priorisierung); + + $diff = 0; + if ($change < 0 && ($bewprio < $currprio || is_null($prestudent->retval[0]->priorisierung))) //prio up + { + $diff = $currprio - $bewprio; + } + elseif ($change > 0 && $bewprio > $currprio) + { + $diff = $bewprio - $currprio; + } + + if ($diff !== 0 && $diff < $difftonext) + { + $difftonext = $diff; + $neighbour = $bewerber; + } + } + } + + if (is_null($prestudent->retval[0]->priorisierung)) + { + //if null value before, add lowest prio + $newprio = isset($neighbour->priorisierung) ? intval($neighbour->priorisierung) + 1 : 1; + + $result = $this->PrestudentModel->update( + $prestudent_id, + array( + 'priorisierung' => $newprio + ) + ); + + if (isError($result)) + { + return false; + } + else + { + return true; + } + } + else + { + $this->db->trans_start(false); + //prio swap + $resultFirst = $this->PrestudentModel->update( + $prestudent_id, + array( + 'priorisierung' => intval($neighbour->priorisierung) + ) + ); + + + $resultSecond = $this->PrestudentModel->update( + $neighbour->prestudent_id, + array( + 'priorisierung' => $currprio + ) + ); + + // Transaction complete! + $this->db->trans_complete(); + + // Check if everything went ok during the transaction + if ($this->db->trans_status() === false || isError($resultFirst) || isError($resultSecond)) + { + $this->db->trans_rollback(); + return false; + } + else + { + $this->db->trans_commit(); + return true; + } + } + } } diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php index db98ddff6..946fe4e14 100644 --- a/application/models/crm/Prestudentstatus_model.php +++ b/application/models/crm/Prestudentstatus_model.php @@ -37,10 +37,11 @@ class Prestudentstatus_model extends DB_Model array_push($parametersArray, $studiensemester_kurzbz); $query .= ' AND studiensemester_kurzbz = ?'; } + if ($status_kurzbz != '') { array_push($parametersArray, $status_kurzbz); - $query .= ' AND status_kurzbz = ?'; + $query .= ' AND tbl_prestudentstatus.status_kurzbz = ?'; } $query .= ' ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1'; diff --git a/application/views/system/infocenter/infocenterDetails.php b/application/views/system/infocenter/infocenterDetails.php index 2fbfa7987..b4c30c2c5 100755 --- a/application/views/system/infocenter/infocenterDetails.php +++ b/application/views/system/infocenter/infocenterDetails.php @@ -71,6 +71,8 @@  p->t('ui', 'freigeben')) ?> + +   @@ -118,7 +120,7 @@ p->t('infocenter', 'zgv').' - '.ucfirst($this->p->t('lehre', 'pruefung'))?> -
+
load->view('system/infocenter/zgvpruefungen.php'); ?>
diff --git a/application/views/system/infocenter/zgvpruefungen.php b/application/views/system/infocenter/zgvpruefungen.php index b68ac5310..abef7e0be 100644 --- a/application/views/system/infocenter/zgvpruefungen.php +++ b/application/views/system/infocenter/zgvpruefungen.php @@ -1,17 +1,30 @@
infoonly; + $studiensemester = isset($zgvpruefung->prestudentstatus->studiensemester_kurzbz) ? $zgvpruefung->prestudentstatus->studiensemester_kurzbz : ''; //set bootstrap columns for zgv form $columns = array(4, 3, 2, 3); $headercolumns = array(7, 5); if (!$infoonly && isset($zgvpruefung->prestudentstatus->bewerbungsnachfrist) && isset($zgvpruefung->prestudentstatus->bewerbungstermin)) { - $headercolumns[0] = 5; - $headercolumns[1] = 7; + $headercolumns[0] = 4; + $headercolumns[1] = 8; } + + if (!$first) + echo '
'; + + if (!in_array($studiensemester, $unique_studsemester)): + $unique_studsemester[] = $studiensemester; + + if (!$first) + echo '
'; ?> -
+

+
@@ -22,22 +35,33 @@ ?>
- prestudentstatus->status_kurzbz) && $zgvpruefung->prestudentstatus->status_kurzbz === 'Interessent'/* && !$infoonly*/): ?> +
+ prestudentstatus->status_kurzbz) && $zgvpruefung->prestudentstatus->status_kurzbz === 'Interessent'): ?> prestudentstatus->bestaetigtam)): ?> -
p->t('global', 'anStudiengangFreigegeben') ?> -
-
- p->t('infocenter','bewerbung')) . ' ' . $this->p->t('global','abgeschickt') . ': '.(isset($zgvpruefung->prestudentstatus->bewerbung_abgeschicktamum) ? '' : ''); ?> + p->t('infocenter', 'bewerbung')) . ' ' . $this->p->t('global', 'abgeschickt') . ': '.(isset($zgvpruefung->prestudentstatus->bewerbung_abgeschicktamum) ? '' : ''); ?> prestudentstatus->bewerbungsnachfrist) ? ' | ' . $this->p->t('infocenter', 'nachfrist') . ': ' . date_format(date_create($zgvpruefung->prestudentstatus->bewerbungsnachfrist), 'd.m.Y') : ''); ?> prestudentstatus->bewerbungstermin) ? ' | ' . $this->p->t('infocenter', 'bewerbungsfrist') . ': ' . date_format(date_create($zgvpruefung->prestudentstatus->bewerbungstermin), 'd.m.Y') : ''); ?> -
+ changeup) && $zgvpruefung->changeup === true; + $changedown = isset($zgvpruefung->changedown) && $zgvpruefung->changedown === true; + if ($numberinteressenten[$studiensemester] > 1): + echo ' | ' . ucfirst($this->p->t('infocenter', 'priorisierung')) . ': '; + echo isset($zgvpruefung->priorisierung) ? $zgvpruefung->priorisierung : $this->p->t('global', 'nichtvorhanden'); + if ($changeup): ?> + + + + + + +
- + prestudentstatus->status_kurzbz)) { @@ -60,8 +84,8 @@
- - prestudentstatus->studiensemester_kurzbz) ? $zgvpruefung->prestudentstatus->studiensemester_kurzbz : '' ?> + +
@@ -73,7 +97,7 @@
- + prestudentstatus->orgform)) ? ', ' : ''; @@ -114,7 +138,7 @@
- + zgvort); else: @@ -127,7 +151,7 @@
- + zgvdatum) ? "" : date_format(date_create($zgvpruefung->zgvdatum), 'd.m.Y'); if ($infoonly): @@ -143,7 +167,7 @@
- + zgvnation_bez; else @@ -173,7 +197,7 @@
- + zgvmaort; else: @@ -186,7 +210,7 @@
- + zgvmadatum) ? "" : date_format(date_create($zgvpruefung->zgvmadatum), 'd.m.Y'); if ($infoonly): @@ -201,7 +225,7 @@
-
+
zgvmanation_bez; @@ -374,5 +398,8 @@ ?>
- +
diff --git a/public/css/sbadmin2/admintemplate.css b/public/css/sbadmin2/admintemplate.css index a0064e5c2..dfa6e8962 100644 --- a/public/css/sbadmin2/admintemplate.css +++ b/public/css/sbadmin2/admintemplate.css @@ -7,7 +7,31 @@ border-bottom: 1px solid #eee; } -/*change of panel colors (grey) */ +.headerrightform +{ + margin: 28px 0 20px -30px; + padding: 6.4px 0 9px; + border-bottom: 1px solid #eee; +} + +.headerrightform .form-group{ + margin-bottom: 0; + margin-left: 5px; +} + +.headerrightform .form-control{ + height: 32px; + font-size: 13px; +} + +/*heading with colored background*/ +.headercolorbg { + background-color: #dfdfdf; + padding: 3px 0; + border-radius: 5px; +} + +/*change of panel colors (to grey) */ .panel-primary > .panel-heading, .panel-primary > .panel-collapse > .panel-footer, .panel-primary > .panel-footer{ color: black; background-color: #dfdfdf; diff --git a/public/js/bootstrapper.js b/public/js/bootstrapper.js index 290749c11..5d1749e9a 100644 --- a/public/js/bootstrapper.js +++ b/public/js/bootstrapper.js @@ -3,8 +3,14 @@ * NOTE: avoid using this if possible */ $(document).ready(function() { + Bootstrapper.bootstraphtml(); +}); + +var Bootstrapper = { + bootstraphtml: function () + { $("input[type=text], select").addClass("form-control"); $("button, input[type=button]").addClass("btn btn-default"); $("table").addClass("table-condensed"); } -); +}; \ No newline at end of file diff --git a/public/js/infocenter/infocenterDetails.js b/public/js/infocenter/infocenterDetails.js index 64377ae1c..1f81430a1 100644 --- a/public/js/infocenter/infocenterDetails.js +++ b/public/js/infocenter/infocenterDetails.js @@ -16,21 +16,13 @@ $(document).ready(function () InfocenterDetails._formatNotizTable(); InfocenterDetails._formatLogTable(); - //initialise datepicker - $.datepicker.setDefaults($.datepicker.regional['de']); - $(".dateinput").datepicker({ - "dateFormat": "dd.mm.yy" - }); - var personid = $("#hiddenpersonid").val(); //add submit event to message send link - $("#sendmsglink").click( - function () - { - $("#sendmsgform").submit(); - } - ); + $("#sendmsglink").click(function () + { + $("#sendmsgform").submit(); + }); //add click events to "formal geprüft" checkboxes $(".prchbox").click(function () @@ -41,60 +33,8 @@ $(document).ready(function () InfocenterDetails.saveFormalGeprueft(personid, akteid, checked) }); - //zgv übernehmen - $(".zgvUebernehmen").click(function () - { - var btn = $(this); - var prestudentid = this.id.substr(this.id.indexOf("_") + 1); - $('#zgvUebernehmenNotice').remove(); - InfocenterDetails.zgvUebernehmen(personid, prestudentid, btn) - }); - - //zgv speichern - $(".zgvform").on('submit', function (e) - { - e.preventDefault(); - var formdata = $(this).serializeArray(); - - var data = {}; - - for (var i = 0; i < formdata.length; i++) - { - data[formdata[i].name] = formdata[i].value; - } - - InfocenterDetails.saveZgv(data); - } - ); - - //show popup with zgvinfo - $(".zgvinfo").click(function () - { - var prestudentid = this.id.substr(this.id.indexOf("_") + 1); - InfocenterDetails.openZgvInfoForPrestudent(prestudentid); - } - ); - - //prevent opening modal when Statusgrund not chosen - $(".absageModal").on('show.bs.modal', function (e) - { - var id = this.id.substr(this.id.indexOf("_") + 1); - var statusgrvalue = $("#statusgrselect_" + id + " select[name=statusgrund]").val(); - if (statusgrvalue === "null") - { - $("#statusgrselect_" + id).addClass("has-error"); - return e.preventDefault(); - } - } - ); - - //remove red mark when statusgrund is selected again - $("select[name=statusgrund]").change( - function () - { - $(this).parent().removeClass("has-error"); - } - ); + //add click events to zgv Prüfung section + InfocenterDetails._addZgvPruefungEvents(personid); //save notiz $("#notizform").on("submit", function (e) @@ -203,6 +143,26 @@ var InfocenterDetails = { } ); }, + saveBewPriorisierung: function(data) + { + FHC_AjaxClient.ajaxCallPost( + CALLED_PATH + '/saveBewPriorisierung', + data, + { + successCallback: function(data, textStatus, jqXHR) { + if (data === true) + { + InfocenterDetails._refreshZgv(); + } + else + { + alert("error when saving zgv Prio"); + } + }, + veilTimeout: 0 + } + ); + }, zgvUebernehmen: function(personid, prestudentid, btn) { FHC_AjaxClient.ajaxCallGet( @@ -399,6 +359,117 @@ var InfocenterDetails = { // ----------------------------------------------------------------------------------------------------------------- // (private) methods executed after ajax (refreshers) + + //adds JQuery events to ZGVprüfung section + _addZgvPruefungEvents: function(personid) + { + //add bootstrap to forms + Bootstrapper.bootstraphtml(); + + //initialise datepicker + $.datepicker.setDefaults($.datepicker.regional['de']); + $(".dateinput").datepicker({ + "dateFormat": "dd.mm.yy" + }); + + //up/down prioritize Bewerbungen + $(".prioup").click(function () + { + var prestudentid = this.id.substr(this.id.indexOf("_") + 1); + InfocenterDetails._savePrio(prestudentid, -1); + }); + $(".priodown").click(function () + { + var prestudentid = this.id.substr(this.id.indexOf("_") + 1); + InfocenterDetails._savePrio(prestudentid, 1); + }); + + //zgv übernehmen + $(".zgvUebernehmen").click(function () + { + var btn = $(this); + var prestudentid = this.id.substr(this.id.indexOf("_") + 1); + $('#zgvUebernehmenNotice').remove(); + InfocenterDetails.zgvUebernehmen(personid, prestudentid, btn); + }); + + //zgv speichern + $(".zgvform").on('submit', function (e) + { + e.preventDefault(); + var formdata = $(this).serializeArray(); + + var data = {}; + + for (var i = 0; i < formdata.length; i++) + { + data[formdata[i].name] = formdata[i].value; + } + + InfocenterDetails.saveZgv(data); + } + ); + + //show popup with zgvinfo + $(".zgvinfo").click(function () + { + var prestudentid = this.id.substr(this.id.indexOf("_") + 1); + InfocenterDetails.openZgvInfoForPrestudent(prestudentid); + } + ); + + //prevent opening modal when Statusgrund not chosen + $(".absageModal").on('show.bs.modal', function (e) + { + var id = this.id.substr(this.id.indexOf("_") + 1); + var statusgrvalue = $("#statusgrselect_" + id + " select[name=statusgrund]").val(); + if (statusgrvalue === "null") + { + $("#statusgrselect_" + id).addClass("has-error"); + return e.preventDefault(); + } + } + ); + + //remove red mark when statusgrund is selected again + $("select[name=statusgrund]").change( + function () + { + $(this).parent().removeClass("has-error"); + } + ); + + }, + _refreshZgv: function() + { + var personid = $("#hiddenpersonid").val(); + + var collapsed = {}; + + //save if panel is collapsed to preserve collapse state + $("#zgvpruefungen").find(".panel-collapse").each( + function() + { + var collapseid = $(this).prop("id"); + collapsed[collapseid] = !$(this).hasClass('collapse in'); + } + ); + + $("#zgvpruefungen").load( + CONTROLLER_URL + '/reloadZgvPruefungen/' + personid + '?fhc_controller_id=' + FHC_AjaxClient.getUrlParameter('fhc_controller_id'), + function() + { + InfocenterDetails._addZgvPruefungEvents(personid); + for (var i in collapsed) + { + if (collapsed[i]) + $("#"+i).removeClass("in"); + else + $("#"+i).addClass("in"); + } + } + ); + }, _refreshLog: function() { var personid = $("#hiddenpersonid").val(); @@ -491,5 +562,13 @@ var InfocenterDetails = { _errorSaveNotiz: function() { $("#notizmsg").text(FHC_PhrasesLib.t('ui', 'fehlerBeimSpeichern')); + }, + _savePrio: function(prestudentid, change) + { + var data = { + "prestudentid": prestudentid, + "change": change + }; + InfocenterDetails.saveBewPriorisierung(data); } }; diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index ab29ee6e2..37cb8c46b 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -970,8 +970,28 @@ $phrases = array( ) ) ), - - + + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'nichtvorhanden', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'n.v.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'n/a', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + //******************************* CORE/ui array( 'app' => 'core', @@ -2755,6 +2775,26 @@ $phrases = array( ) ) ), + array( + 'app' => 'infocenter', + 'category' => 'infocenter', + 'phrase' => 'priorisierung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'prio', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'prio', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'global', From fd41bc3b4505eda11362a3104965811e03524e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Tue, 23 Oct 2018 09:36:35 +0200 Subject: [PATCH 05/58] Fixed Matrikelnummer import for php<5.6.3 --- system/matrikelnummer_clearing_import.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/system/matrikelnummer_clearing_import.php b/system/matrikelnummer_clearing_import.php index 4ab9d6dea..759ba6600 100644 --- a/system/matrikelnummer_clearing_import.php +++ b/system/matrikelnummer_clearing_import.php @@ -53,28 +53,28 @@ if(isset($_FILES['datei'])) $dom = new DOMDocument(); $dom->load($_FILES['datei']['tmp_name']); $studierende = $dom->getElementsByTagName('studierende'); - if(isset($studierende[0])) + if($studierende->length > 0) { $domnodes_personen = $studierende[0]->getElementsByTagName('personen'); foreach($domnodes_personen as $row_person) { $personid_node = $row_person->getElementsByTagName('personId'); - if(isset($personid_node[0])) + if($personid_node->length > 0) { - $node_bpk = $personid_node[0]->getElementsByTagName('bpk'); - $node_personenkennzeichen = $personid_node[0]->getElementsByTagName('personenkennzeichen'); - $node_matrikelnr = $personid_node[0]->getElementsByTagName('matrikelnummer'); + $node_bpk = $personid_node->item(0)->getElementsByTagName('bpk'); + $node_personenkennzeichen = $personid_node->item(0)->getElementsByTagName('personenkennzeichen'); + $node_matrikelnr = $personid_node->item(0)->getElementsByTagName('matrikelnummer'); $bpk = ''; $personenkennzeichen = ''; $matrikelnr = ''; - if (isset($node_bpk[0])) - $bpk = $node_bpk[0]->textContent; - if (isset($node_personenkennzeichen[0])) - $personenkennzeichen = $node_personenkennzeichen[0]->textContent; - if (isset($node_matrikelnr[0])) - $matrikelnr = $node_matrikelnr[0]->textContent; + if ($node_bpk->length > 0) + $bpk = $node_bpk->item(0)->textContent; + if ($node_personenkennzeichen->length > 0) + $personenkennzeichen = $node_personenkennzeichen->item(0)->textContent; + if ($node_matrikelnr->length > 0) + $matrikelnr = $node_matrikelnr->item(0)->textContent; if($personenkennzeichen != '') { From 42f1479e848b01f95cee36f06725764640af41c6 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 23 Oct 2018 14:27:42 +0200 Subject: [PATCH 06/58] - included 'mobil' kontakte as 'Telefon' - added fallback for non-standard contacts --- application/views/system/infocenter/stammdaten.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/application/views/system/infocenter/stammdaten.php b/application/views/system/infocenter/stammdaten.php index 709370012..cab839bd9 100755 --- a/application/views/system/infocenter/stammdaten.php +++ b/application/views/system/infocenter/stammdaten.php @@ -57,21 +57,23 @@ kontakte as $kontakt): ?>
kontakttyp === 'email'): ?> - - kontakttyp === 'telefon'): ?> - + + kontakttyp === 'telefon' || $kontakt->kontakttyp === 'mobil'): ?> + + + From a0157b26bea849ff717877161c232e2617bc9f25 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 23 Oct 2018 14:29:57 +0200 Subject: [PATCH 07/58] Added permission for managing Casetime timesheets --- system/dbupdate_3.3.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 50f3f2e02..9eecc8155 100755 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -1550,6 +1550,19 @@ if($result = @$db->db_query("SELECT * FROM information_schema.role_table_grants } } +// Add permission for managing Casetime timesheets +if ($result = @$db->db_query("SELECT 1 FROM system.tbl_berechtigung WHERE berechtigung_kurzbz = 'addon/casetime_manageTimesheet';")) +{ + if ($db->db_num_rows($result) == 0) + { + $qry = "INSERT INTO system.tbl_berechtigung (berechtigung_kurzbz, beschreibung) VALUES('addon/casetime_manageTimesheet', 'Managen von Casetime timesheets');"; + if (!$db->db_query($qry)) + echo 'system.tbl_berechtigung '.$db->db_last_error().'
'; + else + echo ' system.tbl_berechtigung: Added permission to manage Casetime timesheets.
'; + } +} + /** * Kommentare fuer Datenbanktabellen */ From 5b191f592deca89e81e2a5ccf1e0df7c3aedc8e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Tue, 23 Oct 2018 14:51:14 +0200 Subject: [PATCH 08/58] Fixed PHP Version issue on import --- system/matrikelnummer_clearing_import.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/matrikelnummer_clearing_import.php b/system/matrikelnummer_clearing_import.php index 759ba6600..fbd166341 100644 --- a/system/matrikelnummer_clearing_import.php +++ b/system/matrikelnummer_clearing_import.php @@ -55,7 +55,7 @@ if(isset($_FILES['datei'])) $studierende = $dom->getElementsByTagName('studierende'); if($studierende->length > 0) { - $domnodes_personen = $studierende[0]->getElementsByTagName('personen'); + $domnodes_personen = $studierende->item(0)->getElementsByTagName('personen'); foreach($domnodes_personen as $row_person) { $personid_node = $row_person->getElementsByTagName('personId'); From e600022672d343f5406ae0c354d0fa53c8b1c9e3 Mon Sep 17 00:00:00 2001 From: Andreas Oesterreicher Date: Tue, 23 Oct 2018 15:56:32 +0200 Subject: [PATCH 09/58] Fehler behoben wodurch die Vergabe der Matrikelnummern nicht korrekt gemeldet werden konnte da das Datumsformat falsch war --- include/dvb.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/dvb.class.php b/include/dvb.class.php index 69b407388..8595ed2f3 100644 --- a/include/dvb.class.php +++ b/include/dvb.class.php @@ -699,13 +699,14 @@ class dvb extends basis_db if (!$this->authenticate()) return false; } + $gebdat = str_replace("-", "", "$person->geburtsdatum"); $data = ' '.$uuid.' '.$bildungseinrichtung.' - '.$person->geburtsdatum.' + '.$gebdat.' '.$person->geschlecht.' '.$person->matrikelnummer.''; if (isset($person->matura) && $person->matura != '') From e00ccee235bebb8f42d672a1a7f182f8434e6fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Tue, 23 Oct 2018 16:54:01 +0200 Subject: [PATCH 10/58] =?UTF-8?q?Beim=20Zusammenlegen=20von=20Personen=20w?= =?UTF-8?q?ird=20das=20bPK=20ber=C3=BCcksichtigt=20und=20das=20zusammenleg?= =?UTF-8?q?en=20ggf=20verhindert=20wenn=20zwei=20unterschiedliche=20bPK=20?= =?UTF-8?q?eingetragen=20sind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vilesci/stammdaten/personen_wartung.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/vilesci/stammdaten/personen_wartung.php b/vilesci/stammdaten/personen_wartung.php index 05c72abfe..8153707e0 100644 --- a/vilesci/stammdaten/personen_wartung.php +++ b/vilesci/stammdaten/personen_wartung.php @@ -159,6 +159,14 @@ if (isset($personToDelete) && isset($personToKeep) && $personToDelete >= 0 && $p $error = true; } + // Wenn beide Personen ein BPK haben, abbrechen + if ($personToDelete_obj->bpk != '' && $personToKeep_obj->bpk != '' && $personToDelete_obj->bpk != $personToKeep_obj->bpk) + { + $msg_error[] = 'Beide Personen haben unterschiedliche BPK und können nicht zusammengelegt werden.
+ Bitte wenden Sie sich an einen Administrator.'; + $error = true; + } + // Wenn zwei gleiche rt_person Einträge vorhanden sind, wird ein Fehler ausgegeben und abgebrochen $reihungstest_personToKeep = new reihungstest(); $reihungstest_personToKeep->getReihungstestPerson($personToKeep); @@ -276,6 +284,16 @@ if (isset($personToDelete) && isset($personToKeep) && $personToDelete >= 0 && $p $matr_nr = $personToKeep_obj->matr_nr; if ($personToKeep_obj->matr_nr == '' && $personToDelete_obj->matr_nr != '') $matr_nr = $personToDelete_obj->matr_nr; + else + $matr_nr = $personToKeep_obj->matr_nr; + + $bpk = ''; + if ($personToDelete_obj->bpk == '' && $personToKeep_obj->bpk != '') + $bpk = $personToKeep_obj->bpk; + if ($personToKeep_obj->bpk == '' && $personToDelete_obj->bpk != '') + $bpk = $personToDelete_obj->bpk; + else + $bpk = $personToKeep_obj->bpk; // Letztbenutzten Zugangscode abfragen und übernehmen $zugangscode = ''; @@ -339,6 +357,9 @@ if (isset($personToDelete) && isset($personToKeep) && $personToDelete >= 0 && $p // Matr_nr erst setzen, wenn nur mehr eine Person vorhanden ist $sql_query_upd1 .= "UPDATE public.tbl_person SET matr_nr=" . $db->db_add_param($matr_nr, FHC_STRING) . " WHERE person_id=" . $db->db_add_param($personToKeep, FHC_INTEGER) . ";"; + // BPK erst setzen, wenn nur mehr eine Person vorhanden ist + $sql_query_upd1 .= "UPDATE public.tbl_person SET bpk=" . $db->db_add_param($bpk, FHC_STRING) . " WHERE person_id=" . $db->db_add_param($personToKeep, FHC_INTEGER) . ";"; + if ($db->db_query($sql_query_upd1)) { $msg_info[] = "Update Query:"; From 33c593c00c95462973b9b11b7c9faec36e9ba5d3 Mon Sep 17 00:00:00 2001 From: Gerald Raab Date: Wed, 24 Oct 2018 15:11:58 +0200 Subject: [PATCH 11/58] =?UTF-8?q?Schriftfarbe=20bei=20belegten=20Terminen?= =?UTF-8?q?=20ge=C3=A4ndert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cis/private/coodle/termin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 cis/private/coodle/termin.php diff --git a/cis/private/coodle/termin.php b/cis/private/coodle/termin.php old mode 100644 new mode 100755 index 93b4233fd..8f0a2cfb7 --- a/cis/private/coodle/termin.php +++ b/cis/private/coodle/termin.php @@ -619,7 +619,7 @@ echo ' }); } }); - + // Autocomplete Feld fuer Ressourcen initialisieren $("#input_ressource").autocomplete({ source: "coodle_autocomplete.php?work=ressource", @@ -708,8 +708,8 @@ echo ' error: function() { alert("Error fetching data for "+typ+" "+id); }, - color:"lightgrey" - //textColor:"black" + color:"lightgrey", + textColor:"#777" }); } From 0d8c65b6d366bd64c228ad261b1e7d950b80cc6e Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 25 Oct 2018 14:56:39 +0200 Subject: [PATCH 12/58] Studiengang name on infocenter details is now retrieved from Studienordnung not from Studiengang --- application/models/crm/Prestudent_model.php | 14 ++++++- .../models/crm/Prestudentstatus_model.php | 37 ++++++++++++++++++- .../views/system/infocenter/zgvpruefungen.php | 8 +++- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php index 55215744e..8b764d9d9 100644 --- a/application/models/crm/Prestudent_model.php +++ b/application/models/crm/Prestudent_model.php @@ -185,7 +185,6 @@ class Prestudent_model extends DB_Model return $this->execQuery(sprintf($query, is_array($prestudent_id) ? 'IN' : '='), array($prestudent_id)); } - /** * gets extended zgv data (with zgv bezeichnung) for a prestudent * includes last status, Studiengang, zgv, zgv master @@ -219,6 +218,17 @@ class Prestudent_model extends DB_Model if (count($lastStatus->retval) > 0) { + // get Studiengangname from Studienlan and -ordnung + $studienordnung = $this->PrestudentstatusModel->getStudienordnungFromPrestudent($prestudent_id); + if ($studienordnung->error) + return error($studienordnung->retval); + + if (count($studienordnung->retval) > 0) + { + $lastStatus->retval[0]->studiengangbezeichnung = $studienordnung->retval[0]->studiengangbezeichnung; + $lastStatus->retval[0]->studiengangbezeichnung_englisch = $studienordnung->retval[0]->studiengangbezeichnung_englisch; + } + $this->load->model('system/sprache_model', 'SpracheModel'); $language = $this->SpracheModel->load($lastStatus->retval[0]->sprache); @@ -380,7 +390,7 @@ class Prestudent_model extends DB_Model } } - if (($currprio === $priomax && $change < 0)|| ($currprio === $priomin && $change > 0)) + if (($currprio === $priomax && $change < 0) || ($currprio === $priomin && $change > 0)) { return false; } diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php index 946fe4e14..fb265edbe 100644 --- a/application/models/crm/Prestudentstatus_model.php +++ b/application/models/crm/Prestudentstatus_model.php @@ -114,6 +114,41 @@ class Prestudentstatus_model extends DB_Model * @param $prestudent_id * @return array */ + public function getStudienordnungFromPrestudent($prestudent_id) + { + $lastStatus = $this->getLastStatus($prestudent_id); + + if ($lastStatus->error) + { + return error($lastStatus->retval); + } + + if (count($lastStatus->retval) > 0) + { + $lastStatus = $lastStatus->retval[0]; + + $this->addJoin('lehre.tbl_studienplan', 'studienplan_id'); + $this->addJoin('lehre.tbl_studienordnung', 'studienordnung_id'); + return $this->loadWhere( + array( + 'public.tbl_prestudentstatus.prestudent_id' => $lastStatus->prestudent_id, + 'public.tbl_prestudentstatus.status_kurzbz' => $lastStatus->status_kurzbz, + 'public.tbl_prestudentstatus.studiensemester_kurzbz' => $lastStatus->studiensemester_kurzbz, + 'public.tbl_prestudentstatus.ausbildungssemester' => $lastStatus->ausbildungssemester + ) + ); + } + else + { + return success(array()); + } + } + + /** + * Gets Studienordnung for last status of Prestudent, including ZGV information text + * @param $prestudent_id + * @return array + */ public function getStudienordnungWithZgvText($prestudent_id) { $lastStatus = $this->getLastStatus($prestudent_id); @@ -141,7 +176,7 @@ class Prestudentstatus_model extends DB_Model } else { - return sucess(array()); + return success(array()); } } } diff --git a/application/views/system/infocenter/zgvpruefungen.php b/application/views/system/infocenter/zgvpruefungen.php index abef7e0be..02fbe974c 100644 --- a/application/views/system/infocenter/zgvpruefungen.php +++ b/application/views/system/infocenter/zgvpruefungen.php @@ -5,6 +5,9 @@ foreach ($zgvpruefungen as $zgvpruefung): $infoonly = $zgvpruefung->infoonly; $studiensemester = isset($zgvpruefung->prestudentstatus->studiensemester_kurzbz) ? $zgvpruefung->prestudentstatus->studiensemester_kurzbz : ''; + $studiengangkurzbz = empty($zgvpruefung->prestudentstatus->studiengangkurzbzlang) ? $zgvpruefung->studiengang : $zgvpruefung->prestudentstatus->studiengangkurzbzlang; + $studiengangbezeichnung = empty($zgvpruefung->prestudentstatus->studiengangbezeichnung) ? $zgvpruefung->studiengangbezeichnung : $zgvpruefung->prestudentstatus->studiengangbezeichnung; + //set bootstrap columns for zgv form $columns = array(4, 3, 2, 3); $headercolumns = array(7, 5); @@ -31,7 +34,8 @@ @@ -125,7 +129,7 @@ $zgvinfocolumns = $infoonly ? 4 : 9; ?> Date: Tue, 30 Oct 2018 11:25:14 +0100 Subject: [PATCH 13/58] if only 1 prestudent with prio null - possible to increase (set) prio to 1 --- application/models/crm/Prestudent_model.php | 9 +++++++-- application/views/system/infocenter/zgvpruefungen.php | 9 ++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php index 8b764d9d9..5afa98efe 100644 --- a/application/models/crm/Prestudent_model.php +++ b/application/models/crm/Prestudent_model.php @@ -362,13 +362,17 @@ class Prestudent_model extends DB_Model $bewerberarr = $this->getBewerber($person_id, $studiensemester); + //Prio can be added when prio is null and there is only one prestudent + if (count($bewerberarr) === 1 && !isset($prestudent->retval[0]->priorisierung) && $change < 0) + return true; + if (count($bewerberarr) <= 1) return false; if (!isset($prestudent->retval[0]->priorisierung)) { if ($change < 0) - return true; //null values can be changed to priority numbers, when there are other bewerber + return true; //null values can be changed to priority numbers (prority increase) else return false; } @@ -390,6 +394,7 @@ class Prestudent_model extends DB_Model } } + //no prio change when prestudent has max or min prio if (($currprio === $priomax && $change < 0) || ($currprio === $priomin && $change > 0)) { return false; @@ -459,7 +464,7 @@ class Prestudent_model extends DB_Model if (is_null($prestudent->retval[0]->priorisierung)) { - //if null value before, add lowest prio + //if null value, add as prio 1 $newprio = isset($neighbour->priorisierung) ? intval($neighbour->priorisierung) + 1 : 1; $result = $this->PrestudentModel->update( diff --git a/application/views/system/infocenter/zgvpruefungen.php b/application/views/system/infocenter/zgvpruefungen.php index 02fbe974c..e3e32483e 100644 --- a/application/views/system/infocenter/zgvpruefungen.php +++ b/application/views/system/infocenter/zgvpruefungen.php @@ -25,8 +25,13 @@ if (!$first) echo '
'; + + if (isEmptyString($studiensemester)): ?> -

+

ohne Semester

+ +

+
@@ -54,7 +59,6 @@ changeup) && $zgvpruefung->changeup === true; $changedown = isset($zgvpruefung->changedown) && $zgvpruefung->changedown === true; - if ($numberinteressenten[$studiensemester] > 1): echo ' | ' . ucfirst($this->p->t('infocenter', 'priorisierung')) . ': '; echo isset($zgvpruefung->priorisierung) ? $zgvpruefung->priorisierung : $this->p->t('global', 'nichtvorhanden'); if ($changeup): ?> @@ -63,7 +67,6 @@ -
From 81ca9ecfb21273ece0162f9dba7b5cde552a1b9d Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 30 Oct 2018 14:48:30 +0100 Subject: [PATCH 14/58] Added matrikelnummer in CIS profile Now the matrikelnummer is shown in CIS profile when user is a student --- cis/private/profile/index.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cis/private/profile/index.php b/cis/private/profile/index.php index d35b53655..4c0c0d024 100755 --- a/cis/private/profile/index.php +++ b/cis/private/profile/index.php @@ -24,6 +24,7 @@ require_once('../../../config/cis.config.inc.php'); require_once('../../../config/global.config.inc.php'); require_once('../../../include/functions.inc.php'); require_once('../../../include/globals.inc.php'); +require_once('../../../include/benutzerberechtigung.class.php'); require_once('../../../include/studiengang.class.php'); require_once('../../../include/studienordnung.class.php'); require_once('../../../include/person.class.php'); @@ -230,7 +231,9 @@ echo '
'; //echo ''; echo ''; @@ -171,8 +171,47 @@ function searchPerson($searchItems) echo ''; //echo ''; echo ''; - echo ''; - echo ''; + echo ''; + // Display phone number + echo ''; echo ''; if($row->alias!='' && !in_array($row->studiengang_kz, $noalias)) $mail = $row->alias.'@'.DOMAIN; @@ -271,9 +310,46 @@ function searchOE($searchItems) echo ''; - - echo ''; + echo ''; + + // Display phone number + echo ''; + echo ''; //if($row->alias!='' && !in_array($row->studiengang_kz, $noalias)) ??? Was macht $noalias? if($person->alias!='') From ddc2f0a4afdf4721e7422658f40f28ca04e10b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Fri, 2 Nov 2018 10:49:49 +0100 Subject: [PATCH 18/58] =?UTF-8?q?Anpassung=20Datenverbund=20Schnittstelle?= =?UTF-8?q?=20-=20BPKs=20werden=20bei=20der=20Vergabemeldung=20automatisch?= =?UTF-8?q?=20=C3=BCbernommen=20-=20BPKs=20werden=20automatisch=20=C3=BCbe?= =?UTF-8?q?rnommen=20wenn=20dieses=20bei=20der=20Suche=20der=20Matrikelnum?= =?UTF-8?q?mer=20mitgeliefert=20wird=20-=20Fehler=20behoben=20bei=20der=20?= =?UTF-8?q?Meldung=20mit=20falschen=20Datumsformat=20-=20Neue=20Funktion?= =?UTF-8?q?=20zur=20Abfrage=20des=20BPK=20in=20Testclient=20hinzugef=C3=BC?= =?UTF-8?q?gt=20-=20Testclient=20=C3=BCbernimmt=20die=20Zugangsdaten=20aus?= =?UTF-8?q?=20dem=20Config=20-=20Automatisierte=20Datenabfrage=20erfolgt?= =?UTF-8?q?=20nur=20f=C3=BCr=20Personen=20mit=20SVNR=20bzw=20Ersatzkennzei?= =?UTF-8?q?chen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/dvb.class.php | 540 ++++++++++++++++++++++----- include/errorhandler.class.php | 91 +++++ soap/datenverbund_client.php | 102 +++-- vilesci/cronjobs/matrikelnummern.php | 13 +- 4 files changed, 617 insertions(+), 129 deletions(-) create mode 100644 include/errorhandler.class.php diff --git a/include/dvb.class.php b/include/dvb.class.php index 8595ed2f3..994896bc6 100644 --- a/include/dvb.class.php +++ b/include/dvb.class.php @@ -29,6 +29,7 @@ require_once(dirname(__FILE__).'/studiensemester.class.php'); require_once(dirname(__FILE__).'/adresse.class.php'); require_once(dirname(__FILE__).'/webservicelog.class.php'); require_once(dirname(__FILE__).'/prestudent.class.php'); +require_once(dirname(__FILE__).'/errorhandler.class.php'); class dvb extends basis_db { @@ -37,6 +38,7 @@ class dvb extends basis_db const DVB_URL_WEBSERVICE_ERSATZKZ = DVB_PORTAL.'/rws/0.2/simpleStudentByErsatzKennzeichen.xml'; const DVB_URL_WEBSERVICE_RESERVIERUNG = DVB_PORTAL.'/dvb/matrikelnummern/1.0/reservierung.xml'; const DVB_URL_WEBSERVICE_MELDUNG = DVB_PORTAL.'/dvb/matrikelnummern/1.0/meldung.xml'; + const DVB_URL_WEBSERVICE_BPK = DVB_PORTAL.'/rws/0.2/pruefeBpk.xml'; public $authentication; private $username; @@ -70,33 +72,51 @@ class dvb extends basis_db if (!$person->load($person_id)) { $this->errormsg = $person->errormsg; - return false; + return ErrorHandler::error(); } + $matrikelnummer = false; + $bpk = false; + if ($person->svnr != '') { - $matrikelnummer = $this->getMatrikelnrBySVNR($person->svnr); + $data = $this->getMatrikelnrBySVNR($person->svnr); - if ($matrikelnummer === false && $this->errormsg != '') + if(ErrorHandler::isSuccess($data)) + { + if(ErrorHandler::hasData($data)) + { + $matrikelnummer = $data->retval->matrikelnummer; + $bpk = $data->retval->bpk; + } + } + else { $this->logRequest($person, 'getMatrikelnrBySVNR', false); - return false; + return ErrorHandler::error(); } } elseif ($person->ersatzkennzeichen != '') { - $matrikelnummer = $this->getMatrikelnrByErsatzkennzeichen($person->ersatzkennzeichen); - - if ($matrikelnummer === false && $this->errormsg != '') + $data = $this->getMatrikelnrByErsatzkennzeichen($person->ersatzkennzeichen); + if(ErrorHandler::isSuccess($data)) + { + if(ErrorHandler::hasData($data)) + { + $matrikelnummer = $data->retval->matrikelnummer; + $bpk = $data->retval->bpk; + } + } + else { $this->logRequest($person, 'getMatrikelnrByErsatzkennzeichen', false); - return false; + return ErrorHandler::error(); } } else { $this->errormsg = 'Person braucht SVNR oder Ersatzkennzeichen'; - return false; + return ErrorHandler::error(); } if ($matrikelnummer !== false && $matrikelnummer != '') @@ -104,10 +124,17 @@ class dvb extends basis_db // Matrikelnummer wurde gefunden // Bei Person speichern $person->matr_nr = $matrikelnummer; + + // Wenn ein bPK gefunden wurde dieses auch speichern + if ($bpk != '') + { + $person->bpk = $bpk; + } + if ($person->save()) { $this->logRequest($person, 'assignExistingMatrikelnummer', true, $matrikelnummer); - return true; + return ErrorHandler::success(); } } else @@ -147,14 +174,14 @@ class dvb extends basis_db { $this->logRequest($person, 'assignNewMatrikelnummer', false); $this->errormsg = 'Fehler beim Ermitteln des Studienjahrs für diese Person'; - return false; + return ErrorHandler::error(); } } else { $this->logRequest($person, 'assignNewMatrikelnummer', false); $this->errormsg = 'Fehler beim Ermitteln des Studienjahrs für diese Person'; - return false; + return ErrorHandler::error(); } $studienjahr = substr($studiensemester_kurzbz, 4); @@ -167,57 +194,69 @@ class dvb extends basis_db $studienjahr = 2018; // Neue Matrikelnummer aus Kontingent anfordern - $kontingent = $this->getKontingent(DVB_BILDUNGSEINRICHTUNG_CODE, $studienjahr); + $data = $this->getKontingent(DVB_BILDUNGSEINRICHTUNG_CODE, $studienjahr); - if ($kontingent !== false && isset($kontingent[0])) + if(ErrorHandler::isSuccess($data) && ErrorHandler::hasdata($data)) { - $person_meldung = new stdClass(); - $person_meldung->matrikelnummer = $kontingent[0]; - $person_meldung->vorname = $person->vorname; - $person_meldung->nachname = $person->nachname; - $person_meldung->geburtsdatum = $person->gebdatum; - $person_meldung->geschlecht = mb_strtoupper($person->geschlecht); - $person_meldung->staat = $person->staatsbuergerschaft; - if ($person->svnr != '') - $person_meldung->svnr = $person->svnr; + $kontingent = $data->retval->kontingent; - // PLZ der Meldeadresse laden - $adresse = new adresse(); - if ($adresse->loadZustellAdresse($person->person_id)) - $person_meldung->plz = $adresse->plz; - - // ZGV Datum laden falls vorhanden - $prestudent = new prestudent(); - if ($prestudent->load($prestudent_id) && $prestudent->zgvdatum != '') + if ($kontingent !== false && isset($kontingent[0])) { - $datum_obj = new datum(); - $person_meldung->matura = $datum_obj->formatDatum($prestudent->zgvdatum, 'Ymd'); - } + $person_meldung = new stdClass(); + $person_meldung->matrikelnummer = $kontingent[0]; + $person_meldung->vorname = $person->vorname; + $person_meldung->nachname = $person->nachname; + $person_meldung->geburtsdatum = $person->gebdatum; + $person_meldung->geschlecht = mb_strtoupper($person->geschlecht); + $person_meldung->staat = $person->staatsbuergerschaft; + if ($person->svnr != '') + $person_meldung->svnr = $person->svnr; - // Meldung der Vergabe der Matrikelnummer - if ($this->setMatrikelnummer(DVB_BILDUNGSEINRICHTUNG_CODE, $person_meldung)) - { - // Matrikelnummer bei Person speichern - $person->matr_nr = $matrikelnummer; - if ($person->save()) + // PLZ der Meldeadresse laden + $adresse = new adresse(); + if ($adresse->loadZustellAdresse($person->person_id)) + $person_meldung->plz = $adresse->plz; + + // ZGV Datum laden falls vorhanden + $prestudent = new prestudent(); + if ($prestudent->load($prestudent_id) && $prestudent->zgvdatum != '') { - $this->logRequest($person, 'assignNewMatrikelnummer', true, $matrikelnummer); - return true; + $datum_obj = new datum(); + $person_meldung->matura = $datum_obj->formatDatum($prestudent->zgvdatum, 'Ymd'); + } + + // Meldung der Vergabe der Matrikelnummer + $data = $this->setMatrikelnummer(DVB_BILDUNGSEINRICHTUNG_CODE, $person_meldung); + if (ErrorHandler::isSuccess($data)) + { + // Matrikelnummer bei Person speichern + $person->matr_nr = $data->retval->matrikelnummer; + + // Wenn ein BPK bei der Meldung ermittelt wurde, dann dieses auch speichern + if(ErrorHandler::hasData($data) && isset($data->retval->bpk) && $data->retval->bpk!='') + { + $person->bpk = $data->retval->bpk; + } + if ($person->save()) + { + $this->logRequest($person, 'assignNewMatrikelnummer', true, $matrikelnummer); + return ErrorHandler::success(); + } + } + else + { + $this->logRequest($person, 'assignNewMatrikelnummer', false, $person_meldung); + $this->errormsg .= 'Vergabe fehlgeschlagen'; + return ErrorHandler::error(); } } else { - $this->logRequest($person, 'assignNewgMatrikelnummer', false, $person_meldung); - $this->errormsg .= 'Vergabe fehlgeschlagen'; - return false; + $this->logRequest($person, 'assignNewMatrikelnummer', false, $studienjahr); + $this->errormsg .= 'Failed to get Kontingent'; + return ErrorHandler::error(); } } - else - { - $this->logRequest($person, 'assignNewgMatrikelnummer', false, $studienjahr); - $this->errormsg .= 'Failed to get Kontingent'; - return false; - } } } @@ -279,13 +318,13 @@ class dvb extends basis_db $this->debug('Access_token:'.$this->authentication->access_token); $this->debug('Scope:'.$this->authentication->scope); - return true; + return ErrorHandler::success(); } else { $this->errormsg = 'Authentication failed with HTTP Code:'.$curl_info['http_code']; $this->errormsg .= ' and Response:'.$json_response; - return false; + return ErrorHandler::error(); } } @@ -316,8 +355,9 @@ class dvb extends basis_db { if ($this->tokenIsExpired()) { - if (!$this->authenticate()) - return false; + $result = $this->authenticate(); + if (ErrorHandler::isError($result)) + return ErrorHandler::error(); } $this->debug('getMatrikelnrBySVNR'); @@ -358,6 +398,7 @@ class dvb extends basis_db 12345678 Max + sdfaASDAFasdfads+asasdffd= Mustermann M 1999-02-19 @@ -369,6 +410,9 @@ class dvb extends basis_db $dom->loadXML($response); $namespace = 'http://www.brz.gv.at/datenverbund-unis'; $domnodes_student = $dom->getElementsByTagNameNS($namespace, 'student'); + $matrikelnr = false; + $bpk = false; + foreach ($domnodes_student as $row_student) { // Wenn nicht gesperrt und fix vergeben @@ -380,19 +424,38 @@ class dvb extends basis_db $domnodes_matrikelnummer = $row_student->getElementsByTagNameNS($namespace, 'matrikelNummer'); foreach ($domnodes_matrikelnummer as $row) { - // Found - return $row->textContent; + // MatrikelNr Found + $matrikelnr = $row->textContent; + break; + } + $domnodes_bpk = $row_student->getElementsByTagNameNS($namespace, 'personenkennzeichen'); + foreach ($domnodes_bpk as $row) + { + // BPK Found + $bpk = $row->textContent; + break; } } } - $this->errormsg = ''; - return false; + if($matrikelnr !== false) + { + $retval = new stdClass(); + $retval->matrikelnummer = $matrikelnr; + $retval->bpk = $bpk; + + return ErrorHandler::success($retval); + } + else + { + $this->errormsg = ''; + return ErrorHandler::success(); + } } else { $this->errormsg = 'Request Failed with HTTP Code:'.$curl_info['http_code'].' and Response:'.$response; - return false; + return ErrorHandler::error(); } } @@ -405,8 +468,9 @@ class dvb extends basis_db { if ($this->tokenIsExpired()) { - if (!$this->authenticate()) - return false; + $result = $this->authenticate(); + if (ErrorHandler::isError($result)) + return ErrorHandler::error(); } $this->debug('getMatrikelnrByErsatzkennzeichen'); @@ -503,6 +567,10 @@ class dvb extends basis_db $dom->loadXML($xml_response); $namespace = 'http://www.brz.gv.at/datenverbund-unis'; $domnodes_student = $dom->getElementsByTagNameNS($namespace, 'student'); + + $matrikelnr = ''; + $bpk = ''; + foreach ($domnodes_student as $row_student) { // Wenn nicht gesperrt und fix vergeben @@ -515,18 +583,36 @@ class dvb extends basis_db foreach ($domnodes_matrikelnummer as $row) { // Found - return $row->textContent; + $matrikelnr = $row->textContent; + } + + $domnodes_bpk = $row_student->getElementsByTagNameNS($namespace, 'personenkennzeichen'); + foreach ($domnodes_bpk as $row) + { + // BPK Found + $bpk = $row->textContent; + break; } } } - $this->errormsg = ''; - return false; + if($matrikelnr != '') + { + $retval = new stdClass(); + $retval->matrikelnummer = $matrikelnr; + $retval->bpk = $bpk; + return ErrorHandler::success($retval); + } + else + { + $this->errormsg = ''; + return ErrorHandler::success(); + } } else { $this->errormsg = 'Request Failed with HTTP Code:'.$curl_info['http_code'].' and Response:'.$xml_response; - return false; + return ErrorHandler::error(); } } @@ -543,8 +629,9 @@ class dvb extends basis_db if ($this->tokenIsExpired()) { - if (!$this->authenticate()) - return false; + $result = $this->authenticate(); + if (ErrorHandler::isError($result)) + return ErrorHandler::error(); } $curl = curl_init(); @@ -597,12 +684,14 @@ class dvb extends basis_db { $reservations[] = $row->textContent; } - return $reservations; + $retval = new stdClass(); + $retval->reservations = $reservations; + return ErrorHandler::success($retval); } else { $this->errormsg = 'Request Failed with HTTP Code:'.$curl_info['http_code'].' and Response:'.$response; - return false; + return ErrorHandler::error(); } } @@ -620,8 +709,9 @@ class dvb extends basis_db if ($this->tokenIsExpired()) { - if (!$this->authenticate()) - return false; + $result = $this->authenticate(); + if (ErrorHandler::isError($result)) + return ErrorHandler::error(); } $data = ' @@ -674,12 +764,15 @@ class dvb extends basis_db { $kontingent[] = $row->textContent; } - return $kontingent; + + $retval = new stdClass(); + $retval->kontingent = $kontingent; + return ErrorHandler::success($retval); } else { $this->errormsg = 'Request Failed with HTTP Code:'.$curl_info['http_code'].' and Response:'.$response; - return false; + return ErrorHandler::error(); } } @@ -696,10 +789,11 @@ class dvb extends basis_db if ($this->tokenIsExpired()) { - if (!$this->authenticate()) - return false; + $result = $this->authenticate(); + if (ErrorHandler::isError($result)) + return ErrorHandler::error(); } - $gebdat = str_replace("-", "", "$person->geburtsdatum"); + $gebdat = str_replace("-", "", $person->geburtsdatum); $data = ' @@ -792,6 +886,18 @@ class dvb extends basis_db Korrektur der Matrikelnummer 12345678 + + ED10065 + E + bPK + fehlt oder anders als im Datenverbund ermittelt(Yl329U/jt7fjoo5p+z4lH37ZKrg=) + + Zurückgemeldete bPK in den lokalen Datenbestand übernehmen. Fallsim Fehlertext keine bPK enthalten ist, + müssen die Personendaten geprüft und ggf. ergänzt werden (Abgleich von Name/Geburtsdatum/Adresse mit dem zentralen + Melderegister) + + Yl329keinEchtesbPK4lH37ZKrg= + */ @@ -808,11 +914,13 @@ class dvb extends basis_db $dom->loadXML($response); $domnodes_fehlerliste = $dom->getElementsByTagName('fehlerliste'); - $fehleranzahl = $domnodes_fehlerliste[0]->getAttribute('fehleranzahl'); + $fehleranzahl = $domnodes_fehlerliste->item(0)->getAttribute('fehleranzahl'); if ($fehleranzahl === '0') { // Keine Fehler -> Meldung erfolgreich - return true; + $retval = new stdClass(); + $retval->matrikelnummer = $person->matrikelnummer; + return ErrorHandler::success($retval); } else { @@ -820,18 +928,278 @@ class dvb extends basis_db $domnodes_fehler = $dom->getElementsByTagName('fehler'); foreach ($domnodes_fehler as $row) { - $datenfeld = $row->getElementsByTagName('datenfeld'); - $fehlertext = $row->getElementsByTagName('fehlertext'); - $this->errormsg .= ' Datenfeld:'.$datenfeld[0]->textContent; - $this->errormsg .= ' Fehlertext:'.$fehlertext[0]->textContent; + $fehlernummer = $row->getElementsByTagName('fehlernummer'); + + /** + * Bei Fehlernummer ED10065 wurde die Matrikelnummer korrekt gesetzt. + * Das BPK wurde vom Datenverbund versucht zu ermitteln und wird in der Fehlermeldung + * zurückgeliefert. Dieses sollte dann gespeichert werden. + */ + if($fehlernummer->length>0 && $fehlernummer->item(0)->textContent == 'ED10065') + { + $this->debug('ED10065 Response'); + $domnodes_feldinhalt = $row->getElementsByTagName('feldinhalt'); + if($domnodes_feldinhalt->length > 0 && $domnodes_feldinhalt->item(0)->textContent!='') + { + $bpk = $domnodes_feldinhalt->item(0)->textContent; + $retval = new stdClass(); + $retval->matrikelnummer = $person->matrikelnummer; + $retval->bpk = $bpk; + $this->errormsg .= 'ED10065 Response'; + $this->debug('BPK:'.$bpk); + return ErrorHandler::success($retval); + } + } + else + { + $datenfeld = $row->getElementsByTagName('datenfeld'); + $fehlertext = $row->getElementsByTagName('fehlertext'); + $this->errormsg .= ' Datenfeld:'.$datenfeld->item(0)->textContent; + $this->errormsg .= ' Fehlertext:'.$fehlertext->item(0)->textContent; + } } - return false; + return ErrorHandler::error(); } } else { $this->errormsg = 'Request Failed with HTTP Code:'.$curl_info['http_code'].' and Response:'.$response; - return false; + return ErrorHandler::error(); + } + } + + /** + * Get BPK from Person + * @param string $person_id ID of the Person. + * @return BPK or false on error. + */ + public function getBPK($person_id) + { + $person = new person(); + if ($person->load($person_id)) + { + if ($person->bpk != '') + { + // BPK exisitert bereits + $retval = new stdClass(); + $retval->bpk = $person->bpk; + return ErrorHandler::success($retval); + } + + if ($person->gebdatum == '') + { + $this->errormsg = 'Geburtsdatum ist nicht gesetzt'; + return ErrorHandler::error(); + } + + if ($person->vorname == '') + { + $this->errormsg = 'Vorname ist nicht gesetzt'; + return ErrorHandler::error(); + } + + if ($person->nachname == '') + { + $this->errormsg = 'Nachname ist nicht gesetzt'; + return ErrorHandler::error(); + } + + $geburtsdatum = str_replace("-", "", $person->gebdatum); + $vorname = $person->vorname; + $nachname = $person->nachname; + $geschlecht = mb_strtoupper($person->geschlecht); + + $adresse = new adresse(); + $adresse->loadZustellAdresse($person_id); + + /** + * Wenn die Person beim Ersten mal nicht eindeutig gefunden wird, + * dann wird nochmal versucht mit Postleitzahl und ggf ein drittes + * mal mit der Strasse der Person + */ + + $try = 1; + $plz = null; + $strasse = null; + + while ($try <= 3) + { + if ($try == 2) + { + $plz = $adresse->plz; + } + elseif ($try == 3) + { + $plz = $adresse->plz; + $strasse = $adresse->strasse; + } + + // Versuchen BPK zu ermitteln + $data = $this->pruefeBPK($geburtsdatum, $vorname, $nachname, $geschlecht, $plz, $strasse); + + if (ErrorHandler::isSuccess($data)) + { + // gefunden + return ErrorHandler::success($data->retval); + } + elseif (!ErrorHandler::hasData($data)) + { + // nicht gefunden + return ErrorHandler::error(); + } + else + { + // mehrere gefunden + if (isset($data->retval->multiple) && $data->retval->multiple === true) + { + // ggf nochmal versuchen mit weiteren Parametern + } + else + { + return ErrorHandler::error(); + } + } + $try++; + } + + // nicht eindeutig auffindbar + return ErrorHandler::error(); + } + else + { + $this->errormsg = $person->errormsg; + return ErrorHandler::error(); + } + } + + /** + * Get BPK from Person + * @param string $geburtsdatum Geburtsdatum der Person im format YYYYMMDD + * @param $vorname Vorname der Person. + * @param $nachname Nachname der Person. + * @param $geschlecht Geschlecht der Person M | W + * @param $plz Postleitzahl der Person (optional). + * @param $strasse Strasse der Person (optional). + * @return BPK or false on error. + */ + private function pruefeBPK($geburtsdatum, $vorname, $nachname, $geschlecht, $plz = null, $strasse = null) + { + if ($this->tokenIsExpired()) + { + $result = $this->authenticate(); + if (ErrorHandler::isError($result)) + return ErrorHandler::error(); + } + + $this->debug('getBPK'); + + $curl = curl_init(); + + $url = self::DVB_URL_WEBSERVICE_BPK; + $url .= '?geburtsDatum='.curl_escape($curl, $geburtsdatum); + $url .= '&vorname='.curl_escape($curl, $vorname); + $url .= '&nachname='.curl_escape($curl, $nachname); + $url .= '&geschlecht='.curl_escape($curl, $geschlecht); + + if(!is_null($plz)) + $url .= '&plz='.curl_escape($curl, $plz); + + if(!is_null($strasse)) + $url .= '&strasse='.curl_escape($curl, $strasse); + + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + + $headers = array( + 'Accept: application/json', + 'Authorization: Bearer '.$this->authentication->access_token, + 'User-Agent: FHComplete', + 'Connection: Keep-Alive', + 'Expect:', + 'Content-Length: 0' + ); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + + $this->debug('Sending Request to '.$url); + + $response = curl_exec($curl); + $curl_info = curl_getinfo($curl); + curl_close($curl); + + $this->debug('ResponseCode: '.$curl_info['http_code']); + $this->debug('ResponseData: '.print_r($response, true)); + + if ($curl_info['http_code'] == '200') + { + /* Example Response: + + + 1234567890ABCDEFGH= + + + Max + Mustermann + M + 19901231 + + + + + + + + Example Error: + + + + + + ED10065 + E + bPK + fehlt oder anders als im Datenverbund ermittelt (keine bPK gefunden) + + Zurückgemeldete bPK in den lokalen Datenbestand übernehmen. + Falls im Fehlertext keine bPK enthalten ist, müssen die Personendaten geprüft und + ggf. ergänzt werden (Abgleich von Name/Geburtsdatum/Adresse + mit dem zentralen Melderegister) + + keine bPK gefunden + + + + + */ + + $dom = new DOMDocument(); + $dom->loadXML($response); + $namespace = 'http://www.brz.gv.at/datenverbund-unis'; + $domnodes_bpk = $dom->getElementsByTagNameNS($namespace, 'personenkennzeichen'); + if($domnodes_bpk->length > 0) + { + $retval = new stdClass(); + $retval->bpk = $domnodes_bpk->item(0)->textContent; + return ErrorHandler::success($retval); + } + else + { + $retval = new stdClass(); + $domnodes_personen = $dom->getElementsByTagNameNS($namespace, 'personInfo'); + if($domnodes_personen->length > 1) + { + $retval = new stdClass(); + $retval->multiple = true; + return ErrorHandler::error($retval); + } + } + return ErrorHandler::error(); + } + else + { + $this->errormsg = 'Request Failed with HTTP Code:'.$curl_info['http_code'].' and Response:'.$response; + return ErrorHandler::error(); } } @@ -856,7 +1224,7 @@ class dvb extends basis_db private function debug($msg) { if ($this->debug) - $this->debug_output .= "\n
".date('Y-m-d H:i:s').': '.htmlentities($msg); + $this->debug_output .= "\n".date('Y-m-d H:i:s').': '.$msg; } /** diff --git a/include/errorhandler.class.php b/include/errorhandler.class.php new file mode 100644 index 000000000..5ba74041b --- /dev/null +++ b/include/errorhandler.class.php @@ -0,0 +1,91 @@ +, + */ + /** + * This class provides static functions for handling Result values + */ + +class ErrorHandler +{ + /** + * Returns a Success Object + * @param $retval object + * @return result object + */ + public static function success($retval = '') + { + $data = new stdClass(); + $data->error = false; + $data->retval = $retval; + return $data; + } + + /** + * Returns an Error Object + * @param $retval object (optional) + * @return result object + */ + public static function error($retval = '') + { + $data = new stdClass(); + $data->error = true; + $data->retval = $retval; + return $data; + } + + /** + * Checks if the Result object is Successfull + * @param result object + * @return boolean + */ + public static function isSuccess($result) + { + if (is_object($result) && isset($result->error) && $result->error === false) + { + return true; + } + + return false; + } + + /** + * Checks if the Result object is an error + * @param result object + * @return boolean + */ + public static function isError($result) + { + return !ErrorHandler::isSuccess($result); + } + + /* + * Checks if the Result object contains additional data + * @param result object + * @return boolean + */ + public static function hasData($result) + { + if (is_object($result) && isset($result->retval) && $result->retval!='') + { + return true; + } + + return false; + } +} diff --git a/soap/datenverbund_client.php b/soap/datenverbund_client.php index 1fbf172f5..384712bce 100644 --- a/soap/datenverbund_client.php +++ b/soap/datenverbund_client.php @@ -25,6 +25,7 @@ require_once('../include/functions.inc.php'); require_once('../include/basis_db.class.php'); require_once('../include/benutzerberechtigung.class.php'); require_once('../include/dvb.class.php'); +require_once('../include/errorhandler.class.php'); $uid = get_uid(); $rechte = new benutzerberechtigung(); @@ -39,9 +40,9 @@ if (isset($_GET['action'])) else $action = 'getBySvnr'; -$username = filter_input(INPUT_POST, 'username'); -$password = filter_input(INPUT_POST, 'password'); -$bildungseinrichtung = filter_input(INPUT_POST, 'bildungseinrichtung'); +$username = DVB_USERNAME; +$password = DVB_PASSWORD; + $studienjahr = filter_input(INPUT_POST, 'studienjahr'); $matrikelnr = filter_input(INPUT_POST, 'matrikelnummer'); $nachname = filter_input(INPUT_POST, 'nachname'); @@ -75,7 +76,12 @@ $person_id = filter_input(INPUT_POST, 'person_id');
  • Matrikelnummer Kontingent anfordern
  • Matrikelnummer Vergabe melden
  • Gesamtprozess (Abfrage, ggf Vergabemeldung, Speichern bei Person)
  • +
  • BPK ermitteln
  • + Portal: ".DVB_PORTAL; + echo "
    Bildungseinrichtung: ".DVB_BILDUNGSEINRICHTUNG_CODE; + ?>

    Kosten 
    p->t('person','email')) ?>p->t('person','telefon')) ?>p->t('person', 'email')) ?>p->t('person', 'telefon')) ?>kontakttyp) ?> kontakttyp.'">';?> kontakttyp === 'email'): ?> - + kontakt; if ($kontakt->kontakttyp === 'email'): ?> - - + + '?> anmerkung; ?>'; echo ' '.($type == "student"?$p->t("profil/student"):$p->t('profil/mitarbeiter')).'

    - '.$p->t('global/username').': '.$user->uid.'
    + '.$p->t('global/username').': '.$user->uid.'
    '; + echo ($type == 'student') ? $p->t('global/matrikelnummer'). ": ". $user->matrikelnr. "
    " : ''; +echo ' '.$p->t('global/anrede').': '.$user->anrede.'
    '.$p->t('global/titel').': '.$user->titelpre.'
    '; From f35becb0b3d70c6fcf1d3e589827039d1757f8a5 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 30 Oct 2018 15:07:24 +0100 Subject: [PATCH 15/58] Moved permission for managing CaseTime timesheets to correct folder Moved to addons/casetime/dbcheck.php --- system/dbupdate_3.3.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 9eecc8155..99fba7203 100755 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -1550,18 +1550,6 @@ if($result = @$db->db_query("SELECT * FROM information_schema.role_table_grants } } -// Add permission for managing Casetime timesheets -if ($result = @$db->db_query("SELECT 1 FROM system.tbl_berechtigung WHERE berechtigung_kurzbz = 'addon/casetime_manageTimesheet';")) -{ - if ($db->db_num_rows($result) == 0) - { - $qry = "INSERT INTO system.tbl_berechtigung (berechtigung_kurzbz, beschreibung) VALUES('addon/casetime_manageTimesheet', 'Managen von Casetime timesheets');"; - if (!$db->db_query($qry)) - echo 'system.tbl_berechtigung '.$db->db_last_error().'
    '; - else - echo ' system.tbl_berechtigung: Added permission to manage Casetime timesheets.
    '; - } -} /** * Kommentare fuer Datenbanktabellen From b1cc42b08ee101c2857638436c141d9d22264833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Tue, 30 Oct 2018 15:52:43 +0100 Subject: [PATCH 16/58] =?UTF-8?q?Hinweistext=20in=20Vorlage=20eingebaut=20?= =?UTF-8?q?wenn=20versucht=20wird=20eine=20Diplomurkunde=20f=C3=BCr=20Bach?= =?UTF-8?q?lorarbeit=20zu=20drucken=20und=20umgekehrt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- system/xsl/bachelorurkundeEng_0.xsl | 45 ++++++++++++------------- system/xsl/bachelorurkunde_0.xsl | 51 +++++++++++++++-------------- system/xsl/diplomurkundeEng_0.xsl | 47 +++++++++++++------------- system/xsl/diplomurkunde_0.xsl | 49 +++++++++++++-------------- 4 files changed, 98 insertions(+), 94 deletions(-) diff --git a/system/xsl/bachelorurkundeEng_0.xsl b/system/xsl/bachelorurkundeEng_0.xsl index eaccc7d4e..7f90e2da1 100644 --- a/system/xsl/bachelorurkundeEng_0.xsl +++ b/system/xsl/bachelorurkundeEng_0.xsl @@ -1,19 +1,19 @@ - @@ -53,7 +53,7 @@ - + @@ -73,6 +73,7 @@ Staatsbürgerschaft nicht angegeben + Prüfungstyp passt nicht zu diesem Dokumenttyp Datum der Abschlussprüfung nicht gesetzt @@ -98,19 +99,19 @@ - born in + born in , , citizen of , - student of the University of Applied Sciences + student of the University of Applied Sciences - Bachelor - Master - Diploma - Course - Short study + Bachelor + Master + Diploma + Course + Short study 's degree program @@ -145,4 +146,4 @@ - \ No newline at end of file + diff --git a/system/xsl/bachelorurkunde_0.xsl b/system/xsl/bachelorurkunde_0.xsl index 917eb7125..447066790 100644 --- a/system/xsl/bachelorurkunde_0.xsl +++ b/system/xsl/bachelorurkunde_0.xsl @@ -1,19 +1,19 @@ - @@ -53,7 +53,7 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - + @@ -68,15 +68,16 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - + Diplom-Urkunde Staatsbürgerschaft nicht angegeben + Prüfungstyp passt nicht zu diesem Dokumenttyp Datum der Abschlussprüfung nicht gesetzt Kein akademischer Grad ausgewählt Sponsionsdatum nicht gesetzt Bundesgesetzblattnummer (BGBl) beim Studiengang ist nicht gesetzt - + @@ -86,7 +87,7 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - geboren am in + geboren am in , @@ -103,15 +104,15 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" die/der - + den - das + das Fachhochschul- - Bachelor - Master - Diplom - Lehrgang - Kurzstudium + Bachelor + Master + Diplom + Lehrgang + Kurzstudium -Studiengang @@ -139,4 +140,4 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - \ No newline at end of file + diff --git a/system/xsl/diplomurkundeEng_0.xsl b/system/xsl/diplomurkundeEng_0.xsl index 3dcbeb634..cf94f8737 100644 --- a/system/xsl/diplomurkundeEng_0.xsl +++ b/system/xsl/diplomurkundeEng_0.xsl @@ -1,19 +1,19 @@ - @@ -53,7 +53,7 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - + @@ -71,11 +71,12 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" Diploma Staatsbürgerschaft nicht angegeben + Prüfungstyp passt nicht zu diesem Dokumenttyp Datum der Abschlussprüfung nicht gesetzt Kein akademischer Grad ausgewählt Sponsionsdatum nicht gesetzt Bundesgesetzblattnummer (BGBl) beim Studiengang ist nicht gesetzt - + @@ -85,19 +86,19 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - born in + born in , , citizen of , - student of the University of Applied Sciences + student of the University of Applied Sciences - Bachelor - Master - Diploma - Course - Short study + Bachelor + Master + Diploma + Course + Short study 's degree program @@ -124,4 +125,4 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - \ No newline at end of file + diff --git a/system/xsl/diplomurkunde_0.xsl b/system/xsl/diplomurkunde_0.xsl index bb7b076c0..2437cc97f 100644 --- a/system/xsl/diplomurkunde_0.xsl +++ b/system/xsl/diplomurkunde_0.xsl @@ -1,19 +1,19 @@ - @@ -53,7 +53,7 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - + @@ -68,15 +68,16 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - + Diplom-Urkunde Staatsbürgerschaft nicht angegeben + Prüfungstyp passt nicht zu diesem Dokumenttyp Datum der Abschlussprüfung nicht gesetzt Kein akademischer Grad ausgewählt Sponsionsdatum nicht gesetzt Bundesgesetzblattnummer (BGBl) beim Studiengang ist nicht gesetzt - + @@ -86,7 +87,7 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - geboren am in + geboren am in , @@ -105,13 +106,13 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" den - das + das Fachhochschul- - Bachelor - Master - Diplom - Lehrgang - Kurzstudium + Bachelor + Master + Diplom + Lehrgang + Kurzstudium -Studiengang @@ -139,4 +140,4 @@ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" - \ No newline at end of file + From d5906fdc38e081d856aa7c9c2184782733f75012 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 30 Oct 2018 17:18:34 +0100 Subject: [PATCH 17/58] Added display of business handy on CIS search Now if the CIS search is used to find a person or an organisational unit, the business handy will be displayed IF . no telefonklappe exists . a business handy nr is provided . Zustellung is true --- cis/private/tools/suche.php | 90 ++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/cis/private/tools/suche.php b/cis/private/tools/suche.php index f9452e114..517f3bde0 100644 --- a/cis/private/tools/suche.php +++ b/cis/private/tools/suche.php @@ -52,7 +52,7 @@ echo ' - '; + '; include('../../../include/meta/jquery.php'); include('../../../include/meta/jquery-tablesorter.php'); @@ -158,7 +158,7 @@ function searchPerson($searchItems) { $bisverwendung = new bisverwendung(); $bisverwendung->getLastAktVerwendung($row->uid); - + echo '
    ',$row->titelpre,'',$row->anrede,'',$row->titelpost,'',($row->studiengang!=''?$row->studiengang:'-'),'',($row->mitarbeiter_uid==NULL?'StudentIn':'MitarbeiterIn'),'',($row->telefonklappe!=''?$row->telefonklappe:'-'),'',($row->mitarbeiter_uid==NULL?'StudentIn':'MitarbeiterIn'),''; + // * if user has telefonklappe, display it + if ($row->telefonklappe != '') + { + echo $row->telefonklappe; + } + // * if user has no telefonklappe, display business handy + else + { + $person = new Person(); + $person->getPersonFromBenutzer($row->uid); + $person_id = $person->person_id; + $kontakt = new Kontakt(); + + if ($kontakt->load_persKontakttyp($person_id, 'firmenhandy')) + { + $is_zugestellt = false; + foreach ($kontakt->result as $kontakt) + { + // display business handy only if zustellung is true + if ($kontakt->zustellung) + { + echo $kontakt->kontakt. "
    "; + $is_zugestellt = true; + } + } + // if zustellung is false display '-' + if (!$is_zugestellt) + { + echo '-'; + } + } + // * if neither telefonklappe nor business handy, display '-' + else + { + echo '-'; + } + } + echo '
    ',($row->raum!=''?$row->raum:'-'),''.$bf->bezeichnung; if($bisverwendung->beschausmasscode=='5') echo ' (karenziert)'; - echo '',($mitarbeiter->telefonklappe!=''?$kontakt->kontakt.'-'.$mitarbeiter->telefonklappe:'-'),''; + // * if user has telefonklappe, display it + if ($mitarbeiter->telefonklappe != '') + { + echo $kontakt->kontakt. '-'. $mitarbeiter->telefonklappe; + } + // * if user has no telefonklappe, display business handy + else + { + $person_id = $person->person_id; + + if ($kontakt->load_persKontakttyp($person_id, 'firmenhandy')) + { + $is_zugestellt = false; + foreach ($kontakt->result as $kontakt) + { + // display business handy only if zustellung is true + if ($kontakt->zustellung) + { + echo $kontakt->kontakt. "
    "; + $is_zugestellt = true; + } + } + // if zustellung is false display '-' + if (!$is_zugestellt) + { + echo '-'; + } + } + // * if neither telefonklappe nor business handy, display '-' + else + { + echo '-'; + } + } + echo '
    ',($mitarbeiter->ort_kurzbz!=''?$mitarbeiter->ort_kurzbz:'-'),'
    @@ -103,9 +109,6 @@ $person_id = filter_input(INPUT_POST, 'person_id'); '; } - printrow('username', 'Username', $username, '', 100); - printrow('password', 'Passwort', $password, '', 100, 'password'); - switch($action) { case 'getOAuth': @@ -121,22 +124,10 @@ $person_id = filter_input(INPUT_POST, 'person_id'); case 'getReservations': case 'getKontingent': - printrow( - 'bildungseinrichtung', - 'Bildungseinrichtung', - $bildungseinrichtung, - 'Kurzzeichen der Bildungseinrichtung' - ); printrow('studienjahr', 'Studienjahr', $studienjahr, 'zB 2016 (für WS2016 und SS2017)', 4); break; case 'setMatrikelnummer': - printrow( - 'bildungseinrichtung', - 'Bildungseinrichtung', - $bildungseinrichtung, - 'Kurzzeichen der Bildungseinrichtung' - ); printrow('matrikelnummer', 'Matrikelnummer', $matrikelnr); printrow('nachname', 'Nachname', $nachname, '', 255); printrow('vorname', 'Vorname', $vorname, '', 30); @@ -152,6 +143,10 @@ $person_id = filter_input(INPUT_POST, 'person_id'); printrow('person_id', 'PersonID', $person_id); break; + case 'getBPK': + printrow('person_id', 'PersonID', $person_id); + break; + default: echo "Unknown action"; break; @@ -180,44 +175,60 @@ if (isset($_REQUEST['submit'])) switch ($action) { case 'getOAuth': - if ($dvb->authenticate()) + $result = $dvb->authenticate(); + if (ErrorHandler::isSuccess($result)) echo '
    OAuth Bearer Token: '.$dvb->authentication->access_token; else echo '
    Failed: '.$dvb->errormsg; break; case 'getBySvnr': - $matrikelnr = $dvb->getMatrikelnrBySVNR($_POST['svnr']); - if ($matrikelnr !== false) - echo '
    Matrikelnummer vorhanden:'.$matrikelnr; + $data = $dvb->getMatrikelnrBySVNR($_POST['svnr']); + + if(ErrorHandler::isSuccess($data)) + { + echo '
    Matrikelnummer vorhanden: '.$data->retval->matrikelnummer; + if(isset($data->retval->bpk) && $data->retval->bpk!='') + echo '
    BPK vorhanden: '.$data->retval->bpk; + } else - echo '
    Matrikelnummer nicht vorhanden:'.$dvb->errormsg; + { + echo '
    Matrikelnummer nicht vorhanden:'.$dvb->errormsg; + } break; case 'getByErsatzkennzeichen': - $matrikelnr = $dvb->getMatrikelnrByErsatzkennzeichen($_POST['ersatzkennzeichen']); - if ($matrikelnr !== false) - echo '
    Matrikelnummer vorhanden:'.$matrikelnr; + $data = $dvb->getMatrikelnrByErsatzkennzeichen($_POST['ersatzkennzeichen']); + + if (ErrorHandler::isSuccess($data)) + echo '
    Matrikelnummer vorhanden:'.$data->retval->matrikelnummer; else echo '
    Matrikelnummer nicht vorhanden:'.$dvb->errormsg; break; case 'getReservations': - $reservierteNummern = $dvb->getReservations($_POST['bildungseinrichtung'], $_POST['studienjahr']); - - if ($reservierteNummern !== false) - echo '
    Reservierte Nummern:'.print_r($reservierteNummern, true); - else - echo '
    Fehlgeschlagen:'.$dvb->errormsg; + $result = $dvb->getReservations(DVB_BILDUNGSEINRICHTUNG_CODE, $_POST['studienjahr']); + if(ErrorHandler::isSuccess($result) && ErrorHandler::hasData($result)) + { + $reservierteNummern = $result->retval->reservations; + if ($reservierteNummern !== false) + echo '
    Reservierte Nummern:'.print_r($reservierteNummern, true); + else + echo '
    Fehlgeschlagen:'.$dvb->errormsg; + } break; case 'getKontingent': - $kontingent = $dvb->getKontingent($_POST['bildungseinrichtung'], $_POST['studienjahr']); + $result = $dvb->getKontingent(DVB_BILDUNGSEINRICHTUNG_CODE, $_POST['studienjahr']); - if ($kontingent !== false) - echo '
    Kontingent:'.print_r($kontingent, true); - else - echo '
    Fehlgeschlagen:'.$dvb->errormsg; + if(ErrorHandler::isSuccess($result) && ErrorHandler::hasData($result)) + { + $kontingent = $result->retval->kontingent; + if ($kontingent !== false) + echo '
    Kontingent:'.print_r($kontingent, true); + else + echo '
    Fehlgeschlagen:'.$dvb->errormsg; + } break; case 'setMatrikelnummer': @@ -232,14 +243,17 @@ if (isset($_REQUEST['submit'])) $person->matura = $matura; // Optional $person->svnr = $svnr; // Optional - if ($dvb->setMatrikelnummer($_POST['bildungseinrichtung'], $person)) + $result = $dvb->setMatrikelnummer(DVB_BILDUNGSEINRICHTUNG_CODE, $person); + + if (ErrorHandler::isSuccess($result)) echo '
    Erfolgreich gemeldet'; else echo '
    Fehlgeschlagen:'.$dvb->errormsg; break; case 'assignMatrikelnummer': - if($dvb->assignMatrikelnummer($person_id)) + $result = $dvb->assignMatrikelnummer($person_id); + if(ErrorHandler::isSuccess($result)) { echo '
    OK'; } @@ -247,6 +261,16 @@ if (isset($_REQUEST['submit'])) echo '
    Fehlgeschlagen:'.$dvb->errormsg; break; + case 'getBPK': + $data = $dvb->getBPK($person_id); + if(ErrorHandler::isSuccess($data)) + { + echo '
    OK BPK: '.$data->retval->bpk; + } + else + echo '
    Fehlgeschlagen:'.$dvb->errormsg; + break; + default: echo "Unknown action"; break; diff --git a/vilesci/cronjobs/matrikelnummern.php b/vilesci/cronjobs/matrikelnummern.php index 669dfb74f..66bec957c 100644 --- a/vilesci/cronjobs/matrikelnummern.php +++ b/vilesci/cronjobs/matrikelnummern.php @@ -26,6 +26,7 @@ require_once(dirname(__FILE__).'/../../include/basis_db.class.php'); require_once(dirname(__FILE__).'/../../include/dvb.class.php'); require_once(dirname(__FILE__).'/../../include/benutzerberechtigung.class.php'); require_once(dirname(__FILE__).'/../../include/datum.class.php'); +require_once(dirname(__FILE__).'/../../include/errorhandler.class.php'); if (!$db = new basis_db()) die('Es konnte keine Verbindung zum Server aufgebaut werden.'); @@ -37,6 +38,7 @@ $debug = false; // Authentifizierung stattfinden if (php_sapi_name() != 'cli') { + $nl = '
    '; // Benutzerdefinierte Variablen laden $user = get_uid(); loadVariables($user); @@ -56,6 +58,7 @@ if (php_sapi_name() != 'cli') } else { + $nl = "\n"; // Commandline Paramter parsen bei Aufruf ueber Cronjob // zb php matrikelnummer.php --limit 100 --debug true $longopt = array( @@ -83,7 +86,8 @@ $qry = " public.tbl_benutzer.aktiv = true AND tbl_person.matr_nr is null AND studiengang_kz<10000 - AND EXISTS(SELECT 1 FROM public.tbl_prestudent WHERE person_id=tbl_person.person_id AND bismelden=true)"; + AND EXISTS(SELECT 1 FROM public.tbl_prestudent WHERE person_id=tbl_person.person_id AND bismelden=true) + AND (svnr is not null OR ersatzkennzeichen is not null)"; if ($limit != '') $qry.=" LIMIT ".$limit; @@ -93,10 +97,11 @@ if ($result = $db->db_query($qry)) { while($row = $db->db_fetch_object($result)) { - if($webservice->assignMatrikelnummer($row->person_id)) - echo "\n
    ".$row->person_id.' OK'; + $data = $webservice->assignMatrikelnummer($row->person_id); + if(ErrorHandler::isSuccess($data)) + echo $nl.$row->person_id.' OK'; else - echo "\n
    ".$row->person_id.' Failed:'.$webservice->errormsg; + echo $nl.$row->person_id.' Failed:'.$webservice->errormsg; } } if($debug) From c4fec4fdcfbebcc489eb38578973d25ea221744b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Fri, 2 Nov 2018 11:36:01 +0100 Subject: [PATCH 19/58] Fehler behoben wodurch nach der Vergabemeldung der falsche Wert in Spalte SVNR angezeigt wurde. --- soap/datenverbund_client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soap/datenverbund_client.php b/soap/datenverbund_client.php index 384712bce..5bcd904e0 100644 --- a/soap/datenverbund_client.php +++ b/soap/datenverbund_client.php @@ -135,7 +135,7 @@ $person_id = filter_input(INPUT_POST, 'person_id'); printrow('geschlecht', 'Geschlecht', $geschlecht, 'Format: M | W', 1); printrow('postleitzahl', 'Postleitzahl', $postleitzahl, '', 10); printrow('staat', 'Staat', $staat, '1-3 Stellen Codex (zb A für Österreich)', 3); - printrow('svnr', 'SVNR', $staat); + printrow('svnr', 'SVNR', $svnr); printrow('matura', 'Maturadatum', $matura, 'Format: YYYYMMDD (optional)', 10); break; From 072a83fd392f7292f4235bf7008049de5e1a5555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Fri, 2 Nov 2018 11:45:42 +0100 Subject: [PATCH 20/58] Formatierung im Debug Output korrigiert Fehlerhaften Returnwert bei nicht gefundener Matrikelnummer korrigiert --- include/dvb.class.php | 4 ++-- soap/datenverbund_client.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/dvb.class.php b/include/dvb.class.php index 994896bc6..7afd30c23 100644 --- a/include/dvb.class.php +++ b/include/dvb.class.php @@ -449,7 +449,7 @@ class dvb extends basis_db else { $this->errormsg = ''; - return ErrorHandler::success(); + return ErrorHandler::error(); } } else @@ -606,7 +606,7 @@ class dvb extends basis_db else { $this->errormsg = ''; - return ErrorHandler::success(); + return ErrorHandler::error(); } } else diff --git a/soap/datenverbund_client.php b/soap/datenverbund_client.php index 5bcd904e0..378ee87b7 100644 --- a/soap/datenverbund_client.php +++ b/soap/datenverbund_client.php @@ -276,7 +276,7 @@ if (isset($_REQUEST['submit'])) break; } if (isset($_POST['debug'])) - echo '
    '.$dvb->debug_output.'
    '; + echo '
    '.nl2br(htmlentities($dvb->debug_output)).'
    '; } ?> From 38d8ea33f74562edef689aaa51d0fa858b93e1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Fri, 2 Nov 2018 11:50:56 +0100 Subject: [PATCH 21/58] Reverted and corrected last Commit --- include/dvb.class.php | 4 ++-- soap/datenverbund_client.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/dvb.class.php b/include/dvb.class.php index 7afd30c23..994896bc6 100644 --- a/include/dvb.class.php +++ b/include/dvb.class.php @@ -449,7 +449,7 @@ class dvb extends basis_db else { $this->errormsg = ''; - return ErrorHandler::error(); + return ErrorHandler::success(); } } else @@ -606,7 +606,7 @@ class dvb extends basis_db else { $this->errormsg = ''; - return ErrorHandler::error(); + return ErrorHandler::success(); } } else diff --git a/soap/datenverbund_client.php b/soap/datenverbund_client.php index 378ee87b7..028637948 100644 --- a/soap/datenverbund_client.php +++ b/soap/datenverbund_client.php @@ -185,7 +185,7 @@ if (isset($_REQUEST['submit'])) case 'getBySvnr': $data = $dvb->getMatrikelnrBySVNR($_POST['svnr']); - if(ErrorHandler::isSuccess($data)) + if(ErrorHandler::isSuccess($data) && ErrorHandler::hasData($data)) { echo '
    Matrikelnummer vorhanden: '.$data->retval->matrikelnummer; if(isset($data->retval->bpk) && $data->retval->bpk!='') @@ -200,7 +200,7 @@ if (isset($_REQUEST['submit'])) case 'getByErsatzkennzeichen': $data = $dvb->getMatrikelnrByErsatzkennzeichen($_POST['ersatzkennzeichen']); - if (ErrorHandler::isSuccess($data)) + if (ErrorHandler::isSuccess($data) && ErrorHandler::hasData($data)) echo '
    Matrikelnummer vorhanden:'.$data->retval->matrikelnummer; else echo '
    Matrikelnummer nicht vorhanden:'.$dvb->errormsg; From 01826bf88abfa630808fbaef49d5d4989b77c4f5 Mon Sep 17 00:00:00 2001 From: Gerald Raab Date: Fri, 2 Nov 2018 15:29:53 +0100 Subject: [PATCH 22/58] show all contacts in profile display type firmenhandy if no extension available added bezeichnung_mehrsprachig to tbl_kontakttyp --- cis/private/profile/index.php | 42 ++++++++++++++++++++++++++++++++--- include/kontakt.class.php | 36 +++++++++++++++++------------- locale/de-AT/profil.php | 2 +- locale/en-US/profil.php | 1 + system/dbupdate_3.3.php | 33 ++++++++++++++++++++++++--- 5 files changed, 91 insertions(+), 23 deletions(-) mode change 100644 => 100755 include/kontakt.class.php mode change 100644 => 100755 locale/de-AT/profil.php mode change 100644 => 100755 locale/en-US/profil.php diff --git a/cis/private/profile/index.php b/cis/private/profile/index.php index 4c0c0d024..6f2848bdf 100755 --- a/cis/private/profile/index.php +++ b/cis/private/profile/index.php @@ -43,6 +43,7 @@ require_once('../../../include/fotostatus.class.php'); require_once('../../../include/addon.class.php'); require_once('../../../include/gruppe.class.php'); require_once('../../../include/adresse.class.php'); +require_once('../../../include/benutzerberechtigung.class.php'); $sprache = getSprache(); $p = new phrasen($sprache); @@ -52,14 +53,21 @@ if (!$db = new basis_db()) $uid = get_uid(); +$rechte = new benutzerberechtigung(); +$rechte->getBerechtigungen($uid); + $datum_obj = new datum(); -$ansicht = false; //Wenn ein anderer User sich das Profil ansieht (Bei Personensuche) -if (isset($_GET['uid'])) +// Wenn ein anderer User sich das Profil ansieht (Bei Personensuche) sollen bestimmte persönliche Daten nicht angezeigt werden +// außer der User selber oder berechtigte Personen +$ansicht = false; +if (isset($_GET['uid']) && $_GET['uid'] != $uid) { $uid = stripslashes($_GET['uid']); $ansicht = true; } +if ($rechte->isBerechtigt('basis/kontakt')) + $ansicht = false; if (!$ansicht && isset($_GET['action'])) { @@ -232,7 +240,8 @@ echo '
    '; echo ' '.($type == "student"?$p->t("profil/student"):$p->t('profil/mitarbeiter')).'

    '.$p->t('global/username').': '.$user->uid.'
    '; - echo ($type == 'student') ? $p->t('global/matrikelnummer'). ": ". $user->matrikelnr. "
    " : ''; +if ($type == 'student' && $person->matr_nr) + echo $p->t('global/matrikelnummer'). ": ". $person->matr_nr. "
    "; echo ' '.$p->t('global/anrede').': '.$user->anrede.'
    '.$p->t('global/titel').': '.$user->titelpre.'
    '; @@ -329,6 +338,16 @@ if ($type == 'mitarbeiter') echo $p->t('profil/telefonTw').": $vorwahl - $user->telefonklappe
    "; //echo $p->t('profil/faxTw').": $vorwahl - 99 $user->telefonklappe
    "; } + else { + $kontakt = new kontakt(); + $kontakt->load_pers($user->person_id); + foreach($kontakt->result as $k) + { + if ($k->kontakttyp == 'firmenhandy') + echo $p->t('profil/telefonTw').': '.$k->kontakt.'
    '; + } + + } if ($user->ort_kurzbz != '') echo $p->t('profil/buero').': '.$user->ort_kurzbz.'
    '; } @@ -403,9 +422,24 @@ if (!$ansicht) $kontakt = new kontakt(); $kontakt->load_pers($user->person_id); usort($kontakt->result, "sortKontakt"); + echo ''; foreach($kontakt->result as $k) { + if ($k->kontakttyp != 'firmenhandy' && $k->kontakttyp != 'hidden') + { + if ($k->zustellung) + $zustellung = '✓'; + else + $zustellung = '✗'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + /* if ($k->zustellung === TRUE) { switch($k->kontakttyp) @@ -423,7 +457,9 @@ if (!$ansicht) break; } } + */ } + echo '
    '.$k->bezeichnung_mehrsprachig[$sprache].''.$k->kontakt.''.$k->anmerkung.''.$zustellung.'
    '; } if ($user->homepage != '') diff --git a/include/kontakt.class.php b/include/kontakt.class.php old mode 100644 new mode 100755 index d3f43e09e..b09bf6683 --- a/include/kontakt.class.php +++ b/include/kontakt.class.php @@ -24,6 +24,7 @@ * @create 20-12-2006 */ require_once(dirname(__FILE__).'/basis_db.class.php'); +require_once(dirname(__FILE__).'/sprache.class.php'); class kontakt extends basis_db { @@ -281,7 +282,7 @@ class kontakt extends basis_db $qry = "SELECT tbl_kontakt.*, tbl_firma.name as firma_name, tbl_firma.firma_id FROM public.tbl_kontakt LEFT JOIN public.tbl_standort USING(standort_id) LEFT JOIN public.tbl_firma USING(firma_id) WHERE person_id=".$this->db_add_param($person_id, FHC_INTEGER)." AND kontakttyp =".$this->db_add_param($kontakttyp, FHC_STRING); - + if ($order != null) $qry .= " ORDER BY ".$order; @@ -332,9 +333,10 @@ class kontakt extends basis_db $this->errormsg = 'Person_id ist ungueltig'; return false; } - - $qry = "SELECT tbl_kontakt.*, tbl_firma.name as firma_name, tbl_firma.firma_id - FROM public.tbl_kontakt LEFT JOIN public.tbl_standort USING(standort_id) LEFT JOIN public.tbl_firma USING(firma_id) WHERE person_id=".$this->db_add_param($person_id, FHC_INTEGER).';'; + $sprache = new sprache(); + $bezeichnung_mehrsprachig = $sprache->getSprachQuery('bezeichnung_mehrsprachig'); + $qry = "SELECT tbl_kontakt.*, tbl_firma.name as firma_name, tbl_firma.firma_id, tbl_kontakttyp.beschreibung as kontakttyp_name, $bezeichnung_mehrsprachig + FROM public.tbl_kontakt JOIN tbl_kontakttyp USING (kontakttyp) LEFT JOIN public.tbl_standort USING(standort_id) LEFT JOIN public.tbl_firma USING(firma_id) WHERE person_id=".$this->db_add_param($person_id, FHC_INTEGER).';'; if($this->db_query($qry)) { @@ -356,6 +358,8 @@ class kontakt extends basis_db $obj->insertamum = $row->insertamum; $obj->insertvon = $row->insertvon; $obj->ext_id = $row->ext_id; + $obj->kontakttyp_name = $row->kontakttyp_name; + $obj->bezeichnung_mehrsprachig = $sprache->parseSprachResult('bezeichnung_mehrsprachig',$row); $this->result[] = $obj; } @@ -512,15 +516,15 @@ class kontakt extends basis_db return false; } } - + /** * Sucht nach Kontaktdaten, die den Suchkriterien entsprechen - * @param string $searchstring String, nach dem gesucht werden soll. + * @param string $searchstring String, nach dem gesucht werden soll. * Wenn $typ = nummer ist, werden eventuelle nicht-numerische Zeichen mit preg_replace entfernt, * und es wird nach den Typen "telefon","mobil","so.tel","firmenhandy" und "notfallkontakt" gesucht * @param string $typ Optional. Kontakttyp. Möglich sind "nummer","telefon","mobil","so.tel","firmenhandy","firmenhandy","email","fax" und "homepage". * Wenn $typ = nummer ist, werden eventuelle nicht-numerische Zeichen mit preg_replace entfernt, - * und es wird nach den Typen "telefon","mobil","so.tel","firmenhandy" und "notfallkontakt" gesucht + * und es wird nach den Typen "telefon","mobil","so.tel","firmenhandy" und "notfallkontakt" gesucht * @return boolean */ public function searchKontakt ($searchstring, $typ = '') @@ -534,18 +538,18 @@ class kontakt extends basis_db return false; } } - $qry = "SELECT + $qry = "SELECT * - FROM + FROM public.tbl_kontakt - WHERE + WHERE 1=1"; - + if ($typ == 'nummer') $qry .= " AND regexp_replace(kontakt , '[^0-9]', '', 'g') LIKE ('%".$this->db_escape($searchstring)."%')"; else $qry .= " AND LOWER (kontakt) LIKE LOWER ('%".$this->db_escape($searchstring)."%')"; - + if ($typ != '' && $typ != 'nummer') $qry .= " AND kontakttyp=".$this->db_add_param($typ); @@ -554,7 +558,7 @@ class kontakt extends basis_db while($row = $this->db_fetch_object()) { $obj = new kontakt(); - + $obj->kontakt_id = $row->kontakt_id; $obj->person_id = $row->person_id; $obj->standort_id = $row->standort_id; @@ -567,10 +571,10 @@ class kontakt extends basis_db $obj->insertamum = $row->insertamum; $obj->insertvon = $row->insertvon; $obj->ext_id = $row->ext_id; - + $this->result[] = $obj; } - + return true; } else @@ -580,4 +584,4 @@ class kontakt extends basis_db } } } -?> \ No newline at end of file +?> diff --git a/locale/de-AT/profil.php b/locale/de-AT/profil.php old mode 100644 new mode 100755 index a761b8764..52f1c439d --- a/locale/de-AT/profil.php +++ b/locale/de-AT/profil.php @@ -5,7 +5,7 @@ $this->phrasen['profil/home']='HOME'; $this->phrasen['profil/meinCis']='Mein CIS'; $this->phrasen['profil/bildHochladen']='Profilfoto hochladen'; $this->phrasen['profil/email']='eMail'; -$this->phrasen['profil/kontaktPrivat']='Privat'; +$this->phrasen['profil/kontaktPrivat']='Private Kontakte'; $this->phrasen['profil/mobil']='Mobil'; $this->phrasen['profil/telefon']='Telefon'; $this->phrasen['profil/intern']='Intern'; diff --git a/locale/en-US/profil.php b/locale/en-US/profil.php old mode 100644 new mode 100755 index 10f490264..30ea23f1a --- a/locale/en-US/profil.php +++ b/locale/en-US/profil.php @@ -5,6 +5,7 @@ $this->phrasen['profil/mitarbeiter']='Employee'; $this->phrasen['profil/meinCis']='My CIS'; $this->phrasen['profil/bildHochladen']='Upload picture'; $this->phrasen['profil/email']='eMail'; +$this->phrasen['profil/kontaktPrivat']='Private Contacts'; $this->phrasen['profil/intern']='Intern'; $this->phrasen['profil/alias']='Alias'; $this->phrasen['profil/homepage']='Homepage'; diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 99fba7203..856a55922 100755 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -1522,6 +1522,33 @@ if (!$result = @$db->db_query("SELECT 1 FROM system.tbl_person_lock LIMIT 1")) echo ' system.tbl_person_lock hinzugefügt
    '; } +// Spalte bezeichnung_mehrsprachig in public.tbl_kontakttyp +if(!$result = @$db->db_query("SELECT bezeichnung_mehrsprachig FROM public.tbl_kontakttyp LIMIT 1")) +{ + $qry = "ALTER TABLE public.tbl_kontakttyp ADD COLUMN bezeichnung_mehrsprachig varchar(128)[];"; + + if(!$db->db_query($qry)) + echo 'public.tbl_kontakttyp '.$db->db_last_error().'
    '; + else + echo 'public.tbl_kontakttyp: Spalte bezeichnung_mehrsprachig hinzugefuegt!
    '; + + // Bezeichnung_mehrsprachig aus existierender Bezeichnung vorausfuellen. Ein Eintrag fuer jede Sprache mit Content aktiv. + $qry_help = "SELECT index FROM public.tbl_sprache WHERE content=TRUE;"; + if(!$result = $db->db_query($qry_help)) + echo 'tbl_kontakttyp bezeichnung_mehrsprachig: Fehler beim ermitteln der Sprachen: '.$db->db_last_error().''; + else + { + $qry=''; + while($row = $db->db_fetch_object($result)) + $qry.= "UPDATE public.tbl_kontakttyp set bezeichnung_mehrsprachig[".$row->index."] = beschreibung;"; + + if(!$db->db_query($qry)) + echo 'Setzen der bezeichnung_mehrsprachig fehlgeschlagen: '.$db->db_last_error().'
    '; + else + echo 'public.tbl_kontakttyp: bezeichnung_mehrprachig automatisch aus existierender Beschreibung uebernommen
    '; + } +} + // INSERT Berechtigungen fuer web User erteilen fuer tbl_msg_status if($result = @$db->db_query("SELECT * FROM information_schema.role_table_grants WHERE table_name='tbl_msg_status' AND table_schema='public' AND grantee='web' AND privilege_type='INSERT'")) { @@ -2456,14 +2483,14 @@ if(!$result = @$db->db_query("SELECT lieferant FROM public.tbl_firma LIMIT 1")) echo '
    public.tbl_firma: Spalte lieferant hinzugefuegt'; } -// INSERT, UPDATE und DELETE Berechtigungen fuer web User erteilen fuer tbl_rt_person und SEQUENCE public.tbl_rt_person_rt_person_id_seq +// INSERT, UPDATE und DELETE Berechtigungen fuer web User erteilen fuer tbl_rt_person und SEQUENCE public.tbl_rt_person_rt_person_id_seq if($result = @$db->db_query("SELECT * FROM information_schema.role_table_grants WHERE table_name='tbl_rt_person' AND table_schema='public' AND grantee='web' AND privilege_type='INSERT'")) { if($db->db_num_rows($result)==0) { $qry = "GRANT SELECT, INSERT, UPDATE, DELETE ON public.tbl_rt_person TO web; GRANT SELECT, UPDATE ON SEQUENCE public.tbl_rt_person_rt_person_id_seq TO web;"; - + if(!$db->db_query($qry)) echo 'public.tbl_rt_person Berechtigungen: '.$db->db_last_error().'
    '; else @@ -2648,7 +2675,7 @@ $tabellen=array( "public.tbl_gruppe" => array("gruppe_kurzbz","studiengang_kz","semester","bezeichnung","beschreibung","sichtbar","lehre","aktiv","sort","mailgrp","generiert","updateamum","updatevon","insertamum","insertvon","ext_id","orgform_kurzbz","gid","content_visible","gesperrt","zutrittssystem","aufnahmegruppe"), "public.tbl_kontakt" => array("kontakt_id","person_id","kontakttyp","anmerkung","kontakt","zustellung","updateamum","updatevon","insertamum","insertvon","ext_id","standort_id"), "public.tbl_kontaktmedium" => array("kontaktmedium_kurzbz","beschreibung"), - "public.tbl_kontakttyp" => array("kontakttyp","beschreibung"), + "public.tbl_kontakttyp" => array("kontakttyp","beschreibung","bezeichnung_mehrsprachig"), "public.tbl_konto" => array("buchungsnr","person_id","studiengang_kz","studiensemester_kurzbz","buchungstyp_kurzbz","buchungsnr_verweis","betrag","buchungsdatum","buchungstext","mahnspanne","updateamum","updatevon","insertamum","insertvon","ext_id","credit_points", "zahlungsreferenz", "anmerkung"), "public.tbl_lehrverband" => array("studiengang_kz","semester","verband","gruppe","aktiv","bezeichnung","ext_id","orgform_kurzbz","gid"), "public.tbl_log" => array("log_id","executetime","mitarbeiter_uid","beschreibung","sql","sqlundo"), From 53684c4d507476cb3846723b87b36dc7231b0c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Fri, 2 Nov 2018 16:44:40 +0100 Subject: [PATCH 23/58] =?UTF-8?q?Datenverbund=20Schnittstelle=20aktualisie?= =?UTF-8?q?rt=20-=20neue=20Option=20f=C3=BCr=20Softrun=20hinzugef=C3=BCgt?= =?UTF-8?q?=20um=20bestehende=20Matrikelnummern=20zu=20importieren=20ohne?= =?UTF-8?q?=20eine=20Vergabemeldung=20durchzuf=C3=BChren.=20-=20Matrikelnu?= =?UTF-8?q?mmernabfrage=20nach=20Nachname=20und=20Geburtsdatum=20hinzugef?= =?UTF-8?q?=C3=BCgt=20-=20Zus=C3=A4tzliche=20Pr=C3=BCfung=20hinzugef=C3=BC?= =?UTF-8?q?gt=20wenn=20die=20Person=20nicht=20nach=20SVNR/Ersatzkennzeiche?= =?UTF-8?q?n=20gefunden=20wird,=20wird=20alternativ=20nach=20Name=20und=20?= =?UTF-8?q?Geburtsdatum=20gesucht.=20Wenn=20hier=20ein=20Eintrag=20gefunde?= =?UTF-8?q?n=20wird,=20erfolgt=20keine=20Vergabemeldung=20da=20hier=20manu?= =?UTF-8?q?ell=20gepr=C3=BCft=20werden=20muss=20ob=20es=20sich=20um=20die?= =?UTF-8?q?=20selbe=20Person=20handelt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/dvb.class.php | 174 ++++++++++++++++++++++++++- soap/datenverbund_client.php | 25 ++++ vilesci/cronjobs/matrikelnummern.php | 14 ++- 3 files changed, 209 insertions(+), 4 deletions(-) diff --git a/include/dvb.class.php b/include/dvb.class.php index 994896bc6..b7d42c684 100644 --- a/include/dvb.class.php +++ b/include/dvb.class.php @@ -36,6 +36,7 @@ class dvb extends basis_db const DVB_URL_WEBSERVICE_OAUTH = DVB_PORTAL.'/dvb/oauth/token'; const DVB_URL_WEBSERVICE_SVNR = DVB_PORTAL.'/rws/0.2/simpleStudentBySozialVersicherungsnummer.xml'; const DVB_URL_WEBSERVICE_ERSATZKZ = DVB_PORTAL.'/rws/0.2/simpleStudentByErsatzKennzeichen.xml'; + const DVB_URL_WEBSERVICE_NACHNAME = DVB_PORTAL.'/rws/0.2/simpleStudentByNachname.xml'; const DVB_URL_WEBSERVICE_RESERVIERUNG = DVB_PORTAL.'/dvb/matrikelnummern/1.0/reservierung.xml'; const DVB_URL_WEBSERVICE_MELDUNG = DVB_PORTAL.'/dvb/matrikelnummern/1.0/meldung.xml'; const DVB_URL_WEBSERVICE_BPK = DVB_PORTAL.'/rws/0.2/pruefeBpk.xml'; @@ -64,9 +65,11 @@ class dvb extends basis_db * Wenn die Person noch keine Matrikelnummer besitzt, wird eine neue Matrikelnummer * angefordert und der Person zugeordnet * @param int $person_id ID der Person. + * @param boolean $softrun Wird dieser Parameter gesetzt, werden nur bestehende Daten abgerufen, + * es werden keine neuen Vergabemeldungen gemacht * @return boolean true wenn Erfolgreich, false im Fehlerfall */ - public function assignMatrikelnummer($person_id) + public function assignMatrikelnummer($person_id, $softrun = false) { $person = new person(); if (!$person->load($person_id)) @@ -139,6 +142,18 @@ class dvb extends basis_db } else { + if($this->existsByName($person_id)) + { + $this->errormsg = 'Namenssuche ergab Treffer -> manuelle Pruefung erforderlich'; + return ErrorHandler::error(); + } + + if($softrun == true) + { + $this->errormsg = 'Nicht gefunden Softrun enabled keine Meldung'; + return ErrorHandler::error(); + } + // Es wurde noch keine Matrikelnummer zu dieser Person zugeordnet // Es wird eine neue Matrikelnummer aus dem Kontingent angefordert // und an die Person vergeben @@ -211,6 +226,8 @@ class dvb extends basis_db $person_meldung->staat = $person->staatsbuergerschaft; if ($person->svnr != '') $person_meldung->svnr = $person->svnr; + else if($person->ersatzkennzeichen != '') + $person_meldung->svnr = $person->ersatzkennzeichen; // PLZ der Meldeadresse laden $adresse = new adresse(); @@ -1203,6 +1220,161 @@ class dvb extends basis_db } } + public function existsByName($person_id) + { + $person = new person(); + if($person->load($person_id)) + { + $result = $this->getMatrikelnrByNachname($person->nachname, $person->gebdatum); + + if(ErrorHandler::isSuccess($result) && ErrorHandler::hasData($result) + && isset($result->retval->data) + && is_array($result->retval->data) + && count($result->retval->data)>0) + { + foreach($result->retval->data as $row) + { + if(isset($row->vorname) && isset($row->nachname)) + { + if(mb_substr(mb_strtolower($row->vorname),0,5) == mb_substr(mb_strtolower($person->vorname),0,5) + && mb_substr(mb_strtolower($row->nachname),0,10) == mb_substr(mb_strtolower($person->nachname),0,10)) + { + return true; + } + } + } + return false; + } + else + { + return false; + } + } + } + + /** + * Get Matrikelnummer by Surname + * @param string $nachname Surname of Person. + * @param string $geburtsdatum Date of Birth + * @return Matrikelnummer or false on error. + */ + public function getMatrikelnrByNachname($nachname, $geburtsdatum) + { + if ($this->tokenIsExpired()) + { + $result = $this->authenticate(); + if (ErrorHandler::isError($result)) + return ErrorHandler::error(); + } + + $this->debug('getMatrikelnrByNachname'); + + $curl = curl_init(); + + $geburtsdatum = str_replace("-", "", $geburtsdatum); + + $url = self::DVB_URL_WEBSERVICE_NACHNAME; + $url .= '?nachName='.curl_escape($curl, $nachname); + $url .= '&geburtsDatum='.curl_escape($curl, $geburtsdatum); + + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + + $headers = array( + 'Accept: application/json', + 'Authorization: Bearer '.$this->authentication->access_token, + 'User-Agent: FHComplete', + 'Connection: Keep-Alive', + 'Expect:', + 'Content-Length: 0' + ); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + + $this->debug('Sending Request to '.$url); + + $response = curl_exec($curl); + $curl_info = curl_getinfo($curl); + curl_close($curl); + + $this->debug('ResponseCode: '.$curl_info['http_code']); + $this->debug('ResponseData: '.print_r($response, true)); + + if ($curl_info['http_code'] == '200') + { + /* Example Response: + + + 12345678 + Max + sdfaASDAFasdfads+asasdffd= + Mustermann + M + 1999-02-19 + A + + + */ + $dom = new DOMDocument(); + $dom->loadXML($response); + $namespace = 'http://www.brz.gv.at/datenverbund-unis'; + $domnodes_student = $dom->getElementsByTagNameNS($namespace, 'student'); + + $retval = new stdClass(); + $retval->data = array(); + + foreach ($domnodes_student as $row_student) + { + // Wenn nicht gesperrt und fix vergeben + $ingesamtpool = $row_student->getAttribute('inGesamtPool'); + $gesperrt = $row_student->getAttribute('gesperrt'); + + if ($ingesamtpool == 'true' && $gesperrt == 'false') + { + $data = new stdClass(); + + $domnodes_matrikelnummer = $row_student->getElementsByTagNameNS($namespace, 'matrikelNummer'); + foreach ($domnodes_matrikelnummer as $row) + { + // MatrikelNr Found + $data->matrikelnr = $row->textContent; + break; + } + $domnodes_bpk = $row_student->getElementsByTagNameNS($namespace, 'personenkennzeichen'); + foreach ($domnodes_bpk as $row) + { + // BPK Found + $data->bpk = $row->textContent; + break; + } + $domnodes = $row_student->getElementsByTagNameNS($namespace, 'vorName'); + if($domnodes->length>0) + $data->vorname = $domnodes->item(0)->textContent; + $domnodes = $row_student->getElementsByTagNameNS($namespace, 'nachName'); + if($domnodes->length>0) + $data->nachname = $domnodes->item(0)->textContent; + $domnodes = $row_student->getElementsByTagNameNS($namespace, 'geschlecht'); + if($domnodes->length>0) + $data->geschlecht = $domnodes->item(0)->textContent; + $domnodes = $row_student->getElementsByTagNameNS($namespace, 'staatsAngehoerigkeit'); + if($domnodes->length>0) + $data->staatsangehoerigkeit = $domnodes->item(0)->textContent; + + $retval->data[] = $data; + } + + } + + return ErrorHandler::success($retval); + } + else + { + $this->errormsg = 'Request Failed with HTTP Code:'.$curl_info['http_code'].' and Response:'.$response; + return ErrorHandler::error(); + } + } + /** * Generiert eine eindeutige UUID * @return uuid diff --git a/soap/datenverbund_client.php b/soap/datenverbund_client.php index 028637948..91245f1a0 100644 --- a/soap/datenverbund_client.php +++ b/soap/datenverbund_client.php @@ -72,6 +72,7 @@ $person_id = filter_input(INPUT_POST, 'person_id'); Matrikelnummer nach Ersatzkennzeichen suchen +
  • Matrikelnummer nach Nachname suchen
  • Matrikelnummer Reservierungen anzeigen
  • Matrikelnummer Kontingent anfordern
  • Matrikelnummer Vergabe melden
  • @@ -121,6 +122,10 @@ $person_id = filter_input(INPUT_POST, 'person_id'); case 'getByErsatzkennzeichen': printrow('ersatzkennzeichen', 'Ersatzkennzeichen', $ersatzkennzeichen); break; + case 'getByNachname': + printrow('nachname', 'Nachname', $nachname); + printrow('geburtsdatum', 'Geburtsdatum', $geburtsdatum, ' (Format: YYYYMMDD)', 8); + break; case 'getReservations': case 'getKontingent': @@ -206,6 +211,26 @@ if (isset($_REQUEST['submit'])) echo '
    Matrikelnummer nicht vorhanden:'.$dvb->errormsg; break; + case 'getByNachname': + $data = $dvb->getMatrikelnrByNachname($_POST['nachname'], $_POST['geburtsdatum']); + + if(ErrorHandler::isSuccess($data) && ErrorHandler::hasData($data)) + { + if(isset($data->retval->data) && is_array($data->retval->data) && count($data->retval->data)>0) + { + echo '
    Daten gefunden: '; + var_dump($data->retval); + } + else + { + echo 'keine Einträge gefunden'; + } + } + else + { + echo '
    Matrikelnummer nicht vorhanden:'.$dvb->errormsg; + } + break; case 'getReservations': $result = $dvb->getReservations(DVB_BILDUNGSEINRICHTUNG_CODE, $_POST['studienjahr']); if(ErrorHandler::isSuccess($result) && ErrorHandler::hasData($result)) diff --git a/vilesci/cronjobs/matrikelnummern.php b/vilesci/cronjobs/matrikelnummern.php index 66bec957c..049ddb6e6 100644 --- a/vilesci/cronjobs/matrikelnummern.php +++ b/vilesci/cronjobs/matrikelnummern.php @@ -33,6 +33,7 @@ if (!$db = new basis_db()) $limit = ''; $debug = false; +$softrun = false; // Wenn das Script nicht ueber Commandline gestartet wird, muss eine // Authentifizierung stattfinden @@ -55,6 +56,9 @@ if (php_sapi_name() != 'cli') if(isset($_GET['limit']) && is_numeric($_GET['limit'])) $limit = $_GET['limit']; + + if(isset($_GET['softrun'])) + $debug = ($_GET['softrun']=='true'?true:false); } else { @@ -63,13 +67,16 @@ else // zb php matrikelnummer.php --limit 100 --debug true $longopt = array( "limit:", - "debug:" + "debug:", + "softrun:" ); $commandlineparams = getopt('', $longopt); if (isset($commandlineparams['limit']) && is_numeric($commandlineparams['limit'])) $limit = $commandlineparams['limit']; if (isset($commandlineparams['debug'])) $debug = ($commandlineparams['debug']=='true'?true:false); + if (isset($commandlineparams['softrun'])) + $softrun = ($commandlineparams['softrun']=='true'?true:false); } $matrikelnummer_added = 0; @@ -77,7 +84,7 @@ $webservice = new dvb(DVB_USERNAME, DVB_PASSWORD, $debug); $qry = " SELECT - distinct person_id + distinct person_id, vorname, nachname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) @@ -97,7 +104,8 @@ if ($result = $db->db_query($qry)) { while($row = $db->db_fetch_object($result)) { - $data = $webservice->assignMatrikelnummer($row->person_id); + echo $nl."Pruefe $row->person_id $row->vorname $row->nachname"; + $data = $webservice->assignMatrikelnummer($row->person_id, $softrun); if(ErrorHandler::isSuccess($data)) echo $nl.$row->person_id.' OK'; else From 2959e60df02ee43024db66b49dd69a9abc6c7742 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 2 Nov 2018 18:22:57 +0100 Subject: [PATCH 24/58] =?UTF-8?q?-=20beautified=20prio=20up/down=20arrows?= =?UTF-8?q?=20in=20infocenter=20-=20infocenter=20freigabe/absage=20works?= =?UTF-8?q?=20with=20ajax=20now=20-=20AjaxLib=20veil=20is=20displayed=20co?= =?UTF-8?q?vering=20the=20whole=20page=20-=20infocenter=20details=20studie?= =?UTF-8?q?ngang=20k=C3=BCrzel=20is=20retrieved=20from=20studienordnung=20?= =?UTF-8?q?(if=20possible)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/infocenter/InfoCenter.php | 161 +++++++++--------- application/models/crm/Prestudent_model.php | 17 +- .../system/infocenter/infocenterDetails.php | 3 +- .../views/system/infocenter/zgvpruefungen.php | 160 +++++++++-------- public/css/AjaxLib.css | 2 +- public/css/infocenter/infocenterDetails.css | 38 +++++ public/css/sbadmin2/admintemplate.css | 4 + public/js/infocenter/infocenterDetails.js | 108 ++++++++++-- system/phrasesupdate.php | 21 +++ 9 files changed, 330 insertions(+), 184 deletions(-) create mode 100644 public/css/infocenter/infocenterDetails.css diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index f16c4472e..89f3a4857 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -356,55 +356,50 @@ class InfoCenter extends Auth_Controller * inserts Studiensemester and Ausbildungssemester for the new Absage of (chronologically) last status. * @param $prestudent_id */ - public function saveAbsage($prestudent_id) + public function saveAbsage() { + $json = null; + $prestudent_id = $this->input->post('prestudent_id'); $statusgrund = $this->input->post('statusgrund'); $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id); - if (isError($lastStatus)) + $this->StatusgrundModel->addSelect('bezeichnung_mehrsprachig'); + $statusgrresult = $this->StatusgrundModel->load($statusgrund); + + if (hasData($lastStatus) && hasData($statusgrresult)) { - show_error($lastStatus->retval); - } - - //check if still Interessent and not freigegeben yet - if (count($lastStatus->retval) > 0 && $lastStatus->retval[0]->status_kurzbz === 'Interessent' && !isset($lastStatus->retval[0]->bestaetigtam)) - { - $result = $this->PrestudentstatusModel->insert( - array( - 'prestudent_id' => $prestudent_id, - 'studiensemester_kurzbz' => $lastStatus->retval[0]->studiensemester_kurzbz, - 'ausbildungssemester' => $lastStatus->retval[0]->ausbildungssemester, - 'datum' => date('Y-m-d'), - 'orgform_kurzbz' => $lastStatus->retval[0]->orgform_kurzbz, - 'studienplan_id' => $lastStatus->retval[0]->studienplan_id, - 'status_kurzbz' => 'Abgewiesener', - 'statusgrund_id' => $statusgrund, - 'insertvon' => $this->_uid, - 'insertamum' => date('Y-m-d H:i:s') - ) - ); - - if (isError($result)) + //check if still Interessent and not freigegeben yet + if ($lastStatus->retval[0]->status_kurzbz === 'Interessent' && !isset($lastStatus->retval[0]->bestaetigtam)) { - show_error($result->retval); + $result = $this->PrestudentstatusModel->insert( + array( + 'prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz' => $lastStatus->retval[0]->studiensemester_kurzbz, + 'ausbildungssemester' => $lastStatus->retval[0]->ausbildungssemester, + 'datum' => date('Y-m-d'), + 'orgform_kurzbz' => $lastStatus->retval[0]->orgform_kurzbz, + 'studienplan_id' => $lastStatus->retval[0]->studienplan_id, + 'status_kurzbz' => 'Abgewiesener', + 'statusgrund_id' => $statusgrund, + 'insertvon' => $this->_uid, + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + + $json = $result; + if (isSuccess($result)) + { + $logdata = $this->_getPersonAndStudiengangFromPrestudent($prestudent_id); + + //statusgrund bezeichnung for logging + $statusgrund_bez = $statusgrresult->retval[0]->bezeichnung_mehrsprachig[1]; + + $this->_log($logdata['person_id'], 'abgewiesen', array($prestudent_id, $logdata['studiengang_kurzbz'], $statusgrund_bez)); + } } - - $logdata = $this->_getPersonAndStudiengangFromPrestudent($prestudent_id); - - //statusgrund bezeichnung for logging - $this->StatusgrundModel->addSelect('bezeichnung_mehrsprachig'); - $result = $this->StatusgrundModel->load($statusgrund); - if (isError($result)) - { - show_error($result->retval); - } - - $statusgrund_bez = $result->retval[0]->bezeichnung_mehrsprachig[1]; - - $this->_log($logdata['person_id'], 'abgewiesen', array($prestudent_id, $logdata['studiengang_kurzbz'], $statusgrund_bez)); } - $this->_redirectToStart($prestudent_id, 'ZgvPruef'); + $this->output->set_content_type('application/json')->set_output(json_encode($json)); } /** @@ -412,16 +407,18 @@ class InfoCenter extends Auth_Controller * updates bestaetigtam and bestaetigtvon fields of the last status * @param $prestudent_id */ - public function saveFreigabe($prestudent_id) + public function saveFreigabe() { + $json = null; + $prestudent_id = $this->input->post('prestudent_id'); + $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id); - if (isError($lastStatus)) - { - show_error($lastStatus->retval); - } + $logdata = $this->_getPersonAndStudiengangFromPrestudent($prestudent_id); - if (count($lastStatus->retval) > 0) + $akteresult = $this->AkteModel->loadWhere(array('person_id' => $logdata['person_id'], 'formal_geprueft_amum !=' => NULL)); + + if (hasData($lastStatus) && isSuccess($akteresult)) { $lastStatus = $lastStatus->retval[0]; @@ -443,45 +440,36 @@ class InfoCenter extends Auth_Controller ) ); - if (isError($result)) + $json = $result; + + if (isSuccess($result)) { - show_error($result->retval); + $this->load->model('crm/dokumentprestudent_model', 'DokumentprestudentModel'); + + //set documents which have been formal geprüft to accepted + $dokument_kurzbzs = array(); + + foreach ($akteresult->retval as $akte) + { + $dokument_kurzbzs[] = $akte->dokument_kurzbz; + } + + $acceptresult = $this->DokumentprestudentModel->setAcceptedDocuments($prestudent_id, $dokument_kurzbzs); + + //returns null if no documents to accept + if ($acceptresult !== null && isError($acceptresult)) + { + $json->error = 2; + } + + $this->_log($logdata['person_id'], 'freigegeben', array($prestudent_id, $logdata['studiengang_kurzbz'])); + + $this->_sendFreigabeMail($prestudent_id); } - - $this->load->model('crm/dokumentprestudent_model', 'DokumentprestudentModel'); - - $logdata = $this->_getPersonAndStudiengangFromPrestudent($prestudent_id); - - //set documents which have been formal geprüft to accepted - $result = $this->AkteModel->loadWhere(array('person_id' => $logdata['person_id'], 'formal_geprueft_amum !=' => NULL)); - - if (isError($result)) - { - show_error($result->retval); - } - - $dokument_kurzbzs = array(); - - foreach ($result->retval as $akte) - { - $dokument_kurzbzs[] = $akte->dokument_kurzbz; - } - - $result = $this->DokumentprestudentModel->setAcceptedDocuments($prestudent_id, $dokument_kurzbzs); - - //returns null if no documents to accept - if ($result !== null && isError($result)) - { - show_error($result->retval); - } - - $this->_sendFreigabeMail($prestudent_id); - - $this->_log($logdata['person_id'], 'freigegeben', array($prestudent_id, $logdata['studiengang_kurzbz'])); } } - $this->_redirectToStart($prestudent_id, 'ZgvPruef'); + $this->output->set_content_type('application/json')->set_output(json_encode($json)); } /** @@ -1185,12 +1173,19 @@ class InfoCenter extends Auth_Controller return 1; } // 2: Status - if ($a->prestudentstatus->status_kurzbz !== $b->prestudentstatus->status_kurzbz) + if (isset($a->prestudentstatus->status_kurzbz) || isset($a->prestudentstatus->status_kurzbz)) { - if ($a->prestudentstatus->status_kurzbz === 'Interessent') + if (!isset($b->prestudentstatus->status_kurzbz)) return -1; - elseif ($b->prestudentstatus->status_kurzbz === 'Interessent') + elseif (!isset ($a->prestudentstatus->status_kurzbz)) return 1; + elseif ($a->prestudentstatus->status_kurzbz !== $b->prestudentstatus->status_kurzbz) + { + if ($a->prestudentstatus->status_kurzbz === 'Interessent') + return -1; + elseif ($b->prestudentstatus->status_kurzbz === 'Interessent') + return 1; + } } // 3: Priorisierung, Nulls last diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php index 5afa98efe..b7e54185e 100644 --- a/application/models/crm/Prestudent_model.php +++ b/application/models/crm/Prestudent_model.php @@ -225,6 +225,7 @@ class Prestudent_model extends DB_Model if (count($studienordnung->retval) > 0) { + $lastStatus->retval[0]->studiengangkurzbzlang = $studienordnung->retval[0]->studiengangkurzbzlang; $lastStatus->retval[0]->studiengangbezeichnung = $studienordnung->retval[0]->studiengangbezeichnung; $lastStatus->retval[0]->studiengangbezeichnung_englisch = $studienordnung->retval[0]->studiengangbezeichnung_englisch; } @@ -290,20 +291,20 @@ class Prestudent_model extends DB_Model } /** - * Returns a list with Bewerber (applicants) + * Returns a list with Bewerbungen (applications) * @param $person_id person who sent application(s) * @param string $studiensemester_kurzbz * @param bool $abgeschickt optional, wether application was filled out and sent * @param bool $bestaetigt optional, wether application was confirmed by infocenter * @return array with Bewerber */ - public function getBewerber($person_id, $studiensemester_kurzbz = null, $abgeschickt = null, $bestaetigt = null) + public function getBewerbungen($person_id, $studiensemester_kurzbz = null, $abgeschickt = null, $bestaetigt = null) { - $bewerber = array(); + $bewerbungen = array(); $prestudents = $this->loadWhere(array('person_id' => $person_id)); if (!hasData($prestudents)) - return $bewerber; + return $bewerbungen; $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); @@ -333,11 +334,11 @@ class Prestudent_model extends DB_Model if ($bestaetigtcond && $abgeschicktcond) { $prestudent->lastStatus = $lastStatus; - $bewerber[] = $prestudent; + $bewerbungen[] = $prestudent; } } - return $bewerber; + return $bewerbungen; } /** @@ -360,7 +361,7 @@ class Prestudent_model extends DB_Model $person_id = $prestudent->retval[0]->person_id; - $bewerberarr = $this->getBewerber($person_id, $studiensemester); + $bewerberarr = $this->getBewerbungen($person_id, $studiensemester); //Prio can be added when prio is null and there is only one prestudent if (count($bewerberarr) === 1 && !isset($prestudent->retval[0]->priorisierung) && $change < 0) @@ -436,7 +437,7 @@ class Prestudent_model extends DB_Model $difftonext = PHP_INT_MAX; $neighbour = null; - $bewerberarr = $this->getBewerber($person_id, $studiensemester_kurzbz ); + $bewerberarr = $this->getBewerbungen($person_id, $studiensemester_kurzbz ); foreach ($bewerberarr as $bewerber) { diff --git a/application/views/system/infocenter/infocenterDetails.php b/application/views/system/infocenter/infocenterDetails.php index b4c30c2c5..9a8a0a35e 100755 --- a/application/views/system/infocenter/infocenterDetails.php +++ b/application/views/system/infocenter/infocenterDetails.php @@ -15,7 +15,8 @@ 'navigationwidget' => true, 'customCSSs' => array( 'public/css/sbadmin2/admintemplate.css', - 'public/css/sbadmin2/tablesort_bootstrap.css' + 'public/css/sbadmin2/tablesort_bootstrap.css', + 'public/css/infocenter/infocenterDetails.css' ), 'customJSs' => array( 'public/js/bootstrapper.js', diff --git a/application/views/system/infocenter/zgvpruefungen.php b/application/views/system/infocenter/zgvpruefungen.php index e3e32483e..8640b70db 100644 --- a/application/views/system/infocenter/zgvpruefungen.php +++ b/application/views/system/infocenter/zgvpruefungen.php @@ -28,7 +28,7 @@ if (isEmptyString($studiensemester)): ?> -

    ohne Semester

    +

    p->t('global', 'ohne').' '.$this->p->t('lehre', 'studiensemester') ?>

    @@ -44,8 +44,13 @@ ?> + changeup) && $zgvpruefung->changeup === true; + $changedown = isset($zgvpruefung->changedown) && $zgvpruefung->changedown === true; + ?>
    prestudentstatus->status_kurzbz) && $zgvpruefung->prestudentstatus->status_kurzbz === 'Interessent'): ?> + > prestudentstatus->bestaetigtam)): ?> @@ -57,16 +62,27 @@ prestudentstatus->bewerbungstermin) ? ' | ' . $this->p->t('infocenter', 'bewerbungsfrist') . ': ' . date_format(date_create($zgvpruefung->prestudentstatus->bewerbungstermin), 'd.m.Y') : ''); ?> changeup) && $zgvpruefung->changeup === true; - $changedown = isset($zgvpruefung->changedown) && $zgvpruefung->changedown === true; - echo ' | ' . ucfirst($this->p->t('infocenter', 'priorisierung')) . ': '; - echo isset($zgvpruefung->priorisierung) ? $zgvpruefung->priorisierung : $this->p->t('global', 'nichtvorhanden'); - if ($changeup): ?> - - - - - + echo ' | ' . ucfirst($this->p->t('infocenter', 'priorisierung')) . ': '; + echo isset($zgvpruefung->priorisierung) ? $zgvpruefung->priorisierung : $this->p->t('global', 'nichtvorhanden'); ?> + + + + + + + + + + +
    @@ -268,69 +284,65 @@ //Prestudenten cannot be abgewiesen or freigegeben if already done if (!$infoonly) : ?> -