diklabu-Webuntis.psm1


<#
.Synopsis
   Anmelden an Webuntis
.DESCRIPTION
   Anmelden an Webuntis
.EXAMPLE
   login-Untis -url https://mmbbs-hannover.webuntis.com/WebUntis/jsonrpc.do?school=mmbbs-hannover -credential (Get-Credential Tuttas)
 
#>

function Login-Untis
{
    [CmdletBinding()]
   
    Param
    (
        # URL des Webuntis Systems
        [Parameter(Position=0)]
        [String]$url,

        # Credentials f. das Moodle Systems
        [Parameter(Position=1)]
        [PSCredential]$credential

    )

    Begin
    {

        if (-not $url -or -not $credential) {
            if ($global:logins.webuntis) {
                $url=$Global:logins.webuntis.location;
                $password = $Global:logins.webuntis.password | ConvertTo-SecureString -Key $global:keys
                $credential = New-Object System.Management.Automation.PsCredential($Global:logins.webuntis.user,$password)
            }
            else {
                Write-Error "Bitte url und credentials angeben!"
                return;
            }
        }
        $base=$url
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=Get-Random
        $data.method="authenticate"
        $data.jsonrpc="2.0"
        $params = "" | Select-Object -Property "user","password","client"
        $params.client="ps"
        $params.user=$credential.UserName;
        $params.password=$credential.GetNetworkCredential().Password         
        $data.params=$params
        $headers=@{}
        $headers["content-Type"]="application/json"
        
        #$data | ConvertTo-Json
        $r=Invoke-RestMethod -Method POST -Uri $url -Body (ConvertTo-Json $data) -Headers $headers -SessionVariable session
        $global:session = $session
        if ($r.error) {
            Write-Verbose "Login fehlgeschlagen"
            Write-Error $r.error.message;
        }
        else {
            Write-Verbose "Login erfolgreich"
            $global:webuntis=$base
            $global:untistoken=$r.result.sessionId
            $r

        }  
        Set-Keystore -key "webuntis" -server $base -credential $credential       
    }
}


<#
.Synopsis
   Abfrage der Räume
.DESCRIPTION
   Abfrage der Räume
.EXAMPLE
   Get-UntisRooms
   Abfrage der Räume
#>

function Get-UntisRooms
{
    [CmdletBinding()]
   
    Param
    (
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=$Global:untistoken
        $data.method="getRooms"
        $params = @{}
        $data.params=$params
        $data.jsonrpc="2.0"

        #ConvertTo-Json $data

        $headers=@{}
        $headers["content-Type"]="application/json"
        $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session 
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.result
        }
        
    }
}

<#
.Synopsis
   Abfrage der Klassen
.DESCRIPTION
   Abfrage der Klassen
.EXAMPLE
   Get-UntisCoures
   Abfrage der Klassen
#>

function Get-UntisCourses
{
    [CmdletBinding()]
   
    Param
    (
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=$Global:untistoken
        $data.method="getKlassen"
        $params = @{}
        $data.params=$params
        $data.jsonrpc="2.0"

        #ConvertTo-Json $data

        $headers=@{}
        $headers["content-Type"]="application/json"
        $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session 
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.result
        }
        
    }
}

<#
.Synopsis
   Abfrage der Lehrer
.DESCRIPTION
   Abfrage der Lehrer
.EXAMPLE
   Get-UntisTeachers
   Abfrage der Lehrer
#>

function Get-UntisTeachers
{
    [CmdletBinding()]
   
    Param
    (
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }


        $headers=@{}
        $headers["content-Type"]="application/json"
        $url=$Global:logins.webuntis.location.Substring(0,$Global:logins.webuntis.location.LastIndexOf("/"))
        $url=$url+"/api/public/timetable/weekly/pageconfig?type=2";
        #Write-Host $url
        $r=Invoke-RestMethod -Method GET -Uri $url -Headers $headers -websession $global:session 
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.data.elements
        }
        
    }
}


<#
.Synopsis
   Abfrage der Schüler
.DESCRIPTION
   Abfrage der Schüler
.EXAMPLE
   Get-UntisStudents
   Abfrage der Schüler
#>

function Get-UntisStudents
{
    [CmdletBinding()]
   
    Param
    (
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=$Global:untistoken
        $data.method="getStudents"
        $params = @{}
        $data.params=$params
        $data.jsonrpc="2.0"

        #ConvertTo-Json $data

        $headers=@{}
        $headers["content-Type"]="application/json"
        $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session 
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.result
        }
        
    }
}

<#
.Synopsis
   Abfrage der Fächer
.DESCRIPTION
   Abfrage der Fächer
.EXAMPLE
   Get-UntisSubjects
   Abfrage der Fächer
#>

function Get-UntisSubjects
{
    [CmdletBinding()]
   
    Param
    (
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=$Global:untistoken
        $data.method="getSubjects"
        $params = @{}
        $data.params=$params
        $data.jsonrpc="2.0"

        #ConvertTo-Json $data

        $headers=@{}
        $headers["content-Type"]="application/json"
        $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session 
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.result
        }
        
    }
}

<#
.Synopsis
   Abfrage der Abteilungen
.DESCRIPTION
   Abfrage der Abteilungen
.EXAMPLE
   Get-UntisDepartments
   Abfrage der Abteilungen
#>

function Get-UntisDepartments
{
    [CmdletBinding()]
   
    Param
    (
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=$Global:untistoken
        $data.method="getDepartments"
        $params = @{}
        $data.params=$params
        $data.jsonrpc="2.0"

        #ConvertTo-Json $data

        $headers=@{}
        $headers["content-Type"]="application/json"
        $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session 
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.result
        }
        
    }
}

<#
.Synopsis
   Abfrage der Belegung einzelnet Elemente
.DESCRIPTION
   Abfrage der Belegung einzelnet Elemente (1 = class, 2 = teacher, 3 = subject, 4 = room, 5 = student)
.EXAMPLE
   Get-UntisTimetable -elementType room -id 424
   Abfrage der Belegung des Raumes mit der ID 424 für den heutigen Tag
.EXAMPLE
   Get-UntisTimetable -elementtype student -id 151 -startDate 20171101 -endDate 20171201
   Abfrage des Stundenplans des Schülers mit der id 151 für den gewählten Zeitbereich
.EXAMPLE
   151,152 | Get-UntisTimetable -elementtype student -startDate 20171101 -endDate 20171201
   Abfrage des Stundenplans der Schülers mit den id's 151 und 152 für den gewählten Zeitbereich
#>

function Get-UntisTimetable
{
    [CmdletBinding()]
   
    Param
    (
        # Elementtype
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [ValidateSet('class','teacher','subject','room','student')]
        [String]$elementtype,

        # ID
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   ValueFromPipeline=$true,
                   Position=1)]
        [int]$id ,
        # Start Datum YYYYMMDD (wenn nicht gesetzt, dann wird das aktuelle Datum genommen)
        [String]$startDate,
        # Ende Datum YYYYMMDD (wenn nicht gesetzt, dann wird das aktuelle Datum genommen)
        [String]$endDate
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }
    }
    Process {
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=$Global:untistoken
        $data.method="getTimetable"
        $params = "" | Select-Object -Property "options"
        $options = "" | Select-Object -Property "element","showBooking","showInfo","showSubsText","showLsText","showLsNumber","showStudentgroup","klasseFields","roomFields","subjectFields","teacherFields"
        #$options = "" | Select-Object -Property "element","showBooking","showInfo","showSubsText","showLsText","showLsNumber","showStudentgroup"
        $element = "" | Select-Object -Property "id","type"
        if ($startDate) {
            $options | Add-Member -MemberType NoteProperty -Name "startDate" -Value $startDate
            $options | Add-Member -MemberType NoteProperty -Name "endDate" -Value $startDate
        }
        if ($endDate) {
            $options | Add-Member -MemberType NoteProperty -Name "endDate" -Value $endDate -force
        }
        $element.id=$id
        if ($elementtype -eq "class") {
            $element.type="1"
        }
        if ($elementtype -eq "teacher") {
            $element.type="2"
        }
        if ($elementtype -eq "subject") {
            $element.type="3"
        }
        if ($elementtype -eq "room") {
            $element.type="4"
        }
        if ($elementtype -eq "student") {
            $element.type="5"
        }
        $options.element=$element;
        
        $options.showBooking=$true
        $options.showInfo=$true
        $options.showSubsText=$true
        $options.showLsText=$true
        $options.showLsNumber=$true
        $options.showStudentgroup=$true
        $itemArray = @("id", "name", "longname", "externalkey")
        #$itemArray
        $options.klasseFields=$itemArray
        $options.roomFields=$itemArray
        $options.subjectFields=$itemArray
        $options.teacherFields=$itemArray


        $params.options=$options
        $data.params=$params
        $data.jsonrpc="2.0"

        #ConvertTo-Json $data -Depth 3
                
        $headers=@{}
        $headers["content-Type"]="application/json"
        $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data -Depth 3) -Headers $headers -websession $global:session 
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.result
        } 
        
    }
}

<#
.Synopsis
   Suchen eines Schülers oder Lehrers
.DESCRIPTION
   Suchen eines Schülers oder Lehrers
.EXAMPLE
   tisPerson -elementType stunden -sn Tuttas -fn Jörg
   Sucht die ID des Schülers Jörg Tuttas
#>

function Find-UntisPerson
{
    [CmdletBinding()]
   
    Param
    (
        # Elementtype
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [ValidateSet('teacher','student')]
        [String]$elementtype,

        # Surname
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=1)]
        [String]$sn ,
        # Forename
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=2)]
        [String]$fn,
        # Geburtstag
        [Parameter(ValueFromPipelineByPropertyName=$true,
                   Position=3)]
        [int]$dob=0
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }
    }
    Process {
        $data=echo "" | Select-Object -Property "id","method","jsonrpc","params"
        $data.id=$Global:untistoken
        $data.method="getPersonId"
        $params = "" | Select-Object -Property "type","sn","fn","dob"
        if ($elementtype -eq "teacher") {
            $params.type="2"
        }
        if ($elementtype -eq "student") {
            $params.type="5"
        }
        $params.sn= $sn
        $params.fn= $fn
        $params.dob=$dob
        $data.params=$params
        $data.jsonrpc="2.0"

        #ConvertTo-Json $data -Depth 3
                
        $headers=@{}
        $headers["content-Type"]="application/json;charset=UTF-8"
        $body = ConvertTo-Json $data -Depth 3
        $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body $body -Headers $headers -websession $global:session -ContentType "application/json;charset=UTF-8"
        #$r
        if ($r.error) {
            Write-Error $r.error.message
        }
        else {
            $r.result
        } 
        
    }
}


<#
.Synopsis
   Mitglieder einer Klasse anzeigen
.DESCRIPTION
   Mitglieder einer Klasse anzeigen
.EXAMPLE
   Get-UntisCoursemember -id 171 -startDate "2018-10-22" -type class
   Sucht Schüler der Klasse mit der ID 171 am 22.10.2018
.EXAMPLE
   Get-UntisCoursemember -id 125 -startDate "2018-10-25" -type subject
   Sucht Schüler des Kurses mit der ID 171 am 25.10.2018
.EXAMPLE
   Get-UntisCoursemember -id 125 -startDate "2018-10-25","2018-10-18","2018-11-08" -type subject
   Sucht Schüler des Kurses mit der ID 171 am 25.10.2018 (Do. block rot), 18.10.2018 (Do. block gelb) und 8.11.2018 (Do. block blau)
.EXAMPLE
   Get-UntisCourses | Where-Object {$_ -match "FIAE18"} | Get-UntisCoursemember -startDate "2018-10-22","2018-10-15","2018-11-05" -type class
   Listet alle Schüler des Jahrgangs FIAE18 auf
.EXAMPLE
   Get-UntisSubjects | Where-Object {$_.name -match "-TU"} | Get-UntisCoursemember -startDate "2018-10-25","2018-10-18","2018-11-08" -type subject
   Listet alle Schüler aus dem WPK-TU auf
#>

function Get-UntisCoursemember
{
    [CmdletBinding()]
   
    Param
    (
        # ID
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [int]$id,
        # Date
        [Parameter(Mandatory=$true,
                   Position=1)]
        [String[]]$startDate,
        # Type
        [Parameter(Mandatory=$true,
                   Position=2)]
        [ValidateSet('class','subject')]
        [String]$type
    )

    Begin
    {
        if (-not $global:untistoken) {
            Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis"
            return
        }

    }
    Process {
        #ConvertTo-Json $data -Depth 3
        Write-Verbose "---- Process ID($id) type($type) ----"
        $startDate | ForEach-Object {   
            $dateNumber=[int]$_.replace("-","")    
            Write-Verbose "Date = $_"
            $headers=@{}
            $headers["content-Type"]="application/json"
            $url=$Global:logins.webuntis.location.Substring(0,$Global:logins.webuntis.location.LastIndexOf("/"))
            if ($type -eq "class") {
                $reg1=$url+"/api/public/timetable/weekly/data?elementType=1&elementId=$id&date=$_&formatId=3"
            }
            if ($type -eq "subject") {
                $reg1=$url+"/api/public/timetable/weekly/data?elementType=3&elementId=$id&date=$_&formatId=3"

            }
            #$reg1
            try {
                $r=Invoke-WebRequest -Uri $reg1 -websession $global:session 
            }
            catch {
                Login-Untis
                $r=Invoke-WebRequest -Uri $reg1 -websession $global:session 
            }
            Write-Verbose "Status Code is $($r.StatusCode)"
            $obj=ConvertFrom-Json $r.content
            
            if ($obj.isSessionTimeout -eq $true) {
                Write-Error "Session timed out, please login again"
                break;
            }

            $array = $obj.data.result.data.elementPeriods."$id"    
            $matchingLessons=@{}
            foreach ($entry in $array) {
                Write-Verbose "Date is $($entry.date) Studen-Group $($entry.studenGroup)"
                
                if ($entry.date -eq $dateNumber -and $entry.studentGroup) {
                    
                    if ($type -eq "subject") {
                        
                        $matchingLessons[$($entry.studentGroup)]=$entry                        
                    }
                    if ($type -eq "class") {
                        if (-not $entry.studentGroup -and -not $entry.hasPeriodText) {
                            $matchingLessons["$id"]=$entry
                            break;
                        }
                        else {
                            if ($entry.hasPeriodText) {
                                Write-Warning "Klasse mit ID $id am $_ mit Kommentar $($entry.periodText)"
                            }
                            Write-Verbose "Found Stundent Group $($entry.studentGroup) -> skipped!";
                        }
                    }
                }
            }
            
            
            if ($matchingLessons.Count -eq 0) {
                Write-Warning "No matching lesson found!"
            }
            else {
                foreach ($lesson in $matchingLessons.GetEnumerator()) {
                    $lessonID=$lesson.Value.lessonId;
                    $periodID=$lesson.Value.id
                    Write-Verbose "Found LessonID $lessonID and PeriodID $periodID"
                    $url=$Global:logins.webuntis.location.Substring(0,$Global:logins.webuntis.location.LastIndexOf("/"))
                    $url=$url+"/lessonstudentlist.do?lsid="+$lessonID+"&periodId="+$periodID;
                    #$url

                    $r=Invoke-WebRequest $url -websession $global:session 
       
                    if ($r.error) {
                        Write-Error $r.error.message
                    }
                    else {
            
                        ## Extract the tables out of the web request
                        $tables = @($r.ParsedHtml.getElementById("lessonStudentListForm.assignedStudents"))   
                        if ($tables) {
                            $table = $tables[0]
                            $titles = @()
                            $rows = @($table.Rows)
                            $titles += "studentGroup"
                            ## Go through all of the rows in the table
                            foreach($row in $rows)
                            {
                                $cells = @($row.Cells)

                                ## If we've found a table header, remember its titles
                                if($cells[0].tagName -eq "TH")
                                {
                                    $titles = @($cells | % { ("" + $_.InnerText).Trim() })
                                    continue
                                }

                                ## If we haven't found any table headers, make up names "P1", "P2", etc.
                                if(-not $titles)
                                {
                                    $titles = @(1..($cells.Count + 2) | % { "P$_" })
                                }

                                ## Now go through the cells in the the row. For each, try to find the
                                ## title that represents that column and create a hashtable mapping those
                                ## titles to content

                                $resultObject = [Ordered] @{}

                                for($counter = 0; $counter -lt $cells.Count; $counter++)
                                {
                                    $title = $titles[$counter]
                                    if(-not $title) { continue }
                                    $resultObject[$title] = ("" + $cells[$counter].InnerText).Trim()
                                    $resultObject["stundentGroup"]=$lesson.Name
                                }

                                ## And finally cast that hashtable to a PSCustomObject
                                [PSCustomObject] $resultObject
                            }
                        }
                    }
                }
            }
        }        
    }       
}
### get-sjNds ###
##### JoKe 2025-01-11 ###################################################
<#
.Synopsis
   Gibt Anfangsdatum und Endedatum des im Parameter übergebenen Schuljahres im Format "yyyyMMdd" zurück
.DESCRIPTION
   Gibt Anfangsdatum und Endedatum des im Parameter übergebenen Schuljahres im Format "yyyyMMdd" zurück
   Parameter ist irgendein Datum innerhalb des gesuchten Schuljahres, Parameter hat ebenfalls das Format "yyyyMMdd"
   Falls kein Parameter angegeben wurde, wird das aktuelle Tagesdatum benutzt
   Basisdaten stammen vom 21.8.2023 von https://www.schulferien.org/deutschland/ferien/niedersachsen/
.EXAMPLE
   get-sjNds
.EXAMPLE
   get-sjNds "20250407"
#>

function get-sjNds {
    Param(
        [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)]
        [String]$sj = (get-date -Format "yyyyMMdd") # Format "yyyyMMdd"
    )
    Begin{
        # start and end school day of the term
        $sjs = @{
            SJ2324 = @{
                startdate="20230817"
                enddate="20240621"
            }
            SJ2425 = @{
                startdate="20240805"
                enddate="20250702"
            }
            SJ2526 = @{
                startdate="20250813"
                enddate="20260701"
            }
            SJ2627 = @{
                startdate="20260813"
                enddate="20270707"
            }
            SJ2728 = @{
                startdate="20270819"
                enddate="20280719"
            }        
        } # end of schoolterm list
    }
    Process{
        $start ="00000000"
        $end = "00000000"
        foreach ($entry in $sjs.GetEnumerator()){
            if ($sj -in $entry.value['startdate']..$entry.value['enddate']){
                $start = $entry.value['startdate']
                $end = $entry.value['enddate']
            }
        }
        $dates=@{}
        $dates.startdate=$start
        $dates.enddate=$end
        return $dates
    }
}
### add-untisDay ###
##### JoKe 2025-01-11 ######################################################
<#
.Synopsis
   Addiert einen Tag zum Datum im Übergabeformat yyyyMMdd
.DESCRIPTION
   Addiert einen Tag zum Datum im Übergabeformat yyyyMMdd
   Beispielsweise wird aus "20233112" --> "20240101"
.EXAMPLE
   add-untisDay "20233112"
#>

function add-untisDay {
    Param
    (
        [Parameter(Mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$true)]        
        [String]$datestring # Date in diklabu datestring format yyyyMMdd
    )
    $d=[DateTime]::ParseExact($datestring,"yyyyMMdd",$Null)
    $d=$d.AddDays(1)
    return $d.tostring("yyyyMMdd")
} # end function add-untisDay
####################################### ende add-untisDay ##############################################

##### get-untisClassTeacherTeams #####
##### JoKe 2025-01-11 ##################################################################################
<#
.Synopsis
   Baut eine Hashliste mit der Zuordnung Klasse zu Lehrkräfteteam
.DESCRIPTION
   Baut eine Hashliste mit der Zuordnung Klasse zu Lehrkräfteteam mit Daten aus dem aktuellen Webuntis
   Key: Klassenname, Value: Komma separierte Liste mit Lehrkräftekürzeln, z.B. FISI24D: "KE,LE,WE"
   Wenn $checkHashlistClassesTeachers $true gesetzt wird (default ist $false),
   wird nach einer vorher abgespeicherten Version der Hashliste geschaut und, falls diese vorhanden UND TAGESAKTUELL ist,
   diese verwendet anstelle der Webuntisdaten. Dieses Verfahren bietet Geschwindigkeitsvorteile
   gegenüber der Abfrage in Webuntis, nutzt aber evtl. nicht die aktuellen Daten
.EXAMPLE
   get-untisClassTeacherTeams
.EXAMPLE
   get-untisClassTeacherTeams $true
#>

function get-untisClassTeacherTeams {
    Param(
        [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)]
            [Boolean]$checkHashlistClassesTeachers = $false,
        [Parameter(Mandatory=$true)]
            [string]$WUlocationClassTeachers, 
        [Parameter(Mandatory=$true)]
            [string]$WUclassesTeachersDelimiter,
        [Parameter(Mandatory=$true)]
            [System.Management.Automation.PSCredential]$WUcreds
    )
    Begin {
        $funcName = $MyInvocation.InvocationName
    }
    Process {
        if ($checkHashlistClassesTeachers -and (Test-Path ($WUlocationClassTeachers)) -and ((Get-Item ($WUlocationClassTeachers)).LastWriteTime.Date -eq (Get-Date).Date)) {
            $hashClassesTeachers = @{}
            $f = Import-Csv $WUlocationClassTeachers -Delimiter ","
            foreach ($row in $f) { $hashClassesTeachers[$row.Name] = $row.Value }
            return $hashClassesTeachers
        }
        else {
            $feedbacklogin = login-untis -url "https://mmbbs-hannover.webuntis.com/WebUntis/jsonrpc.do?school=mmbbs-hannover" -credential $WUcreds
            $alleLuL = Get-UntisTeachers
            $classesTeachers = @{} 

            $today = Get-Date -Format "yyyyMMdd"
            $term = get-sjNds -sj $today
            
            Write-Host "$funcName : Verarbeite $($alleLuL.Count) Lehrkräfte für Zeitraum $($term.startDate) bis $($term.endDate)..."

            foreach ($LoL in $alleLuL) {
                $plan = Get-UntisTimetable -elementtype teacher -id $LoL.id -startDate $term.startDate -endDate $term.endDate
                if ($plan) {
                    foreach ($stunde in $plan) {
                        foreach ($klasse in $stunde.kl) {
                            $kName = $klasse.name
                            if (-not $classesTeachers.ContainsKey($kName)) {
                                $classesTeachers[$kName] = New-Object System.Collections.Generic.HashSet[string]
                            }
                            foreach ($lehrer in $stunde.te) {
                                [void]$classesTeachers[$kName].Add($lehrer.name)
                            }
                        }
                    }
                }
                Start-Sleep -Milliseconds 50
            }

            $finalExport = foreach ($key in $classesTeachers.Keys) {
                [PSCustomObject]@{
                    Name  = $key
                    Key   = $key
                    Value = ($classesTeachers[$key] -join $WUclassesTeachersDelimiter)
                }
            }

            if ($finalExport) {
                $finalExport | Export-Csv -Path $WUlocationClassTeachers -NoTypeInformation -Encoding UTF8 -Delimiter ","
                Write-Host "$funcName : CSV-Datei erfolgreich erstellt unter $WUlocationClassTeachers"
            }

            $hashClassesTeachers = @{}
            foreach ($item in $finalExport) { $hashClassesTeachers[$item.Name] = $item.Value }
            
            Write-Host "$funcName : Hashtabelle fertig erstellt!"
            return $hashClassesTeachers        
        }
    } # end process
} # end function get-untisClassTeacherTeams