Benutzer-Werkzeuge

Webseiten-Werkzeuge


skripte:rsk_erinnerung_und_pruefen_manuell

RSK_Erinnerung_und_prüfen (Manuelle Version)

Nutzen: Dieses Skript automatisiert das komplette monatliche Meldeverfahren für RSK-Daten. Es ist für die manuelle Ausführung durch einen Anwender konzipiert.

Funktion:

Liest eine Stammdaten-Datei, um alle meldepflichtigen Mandanten zu ermitteln.

Führt eine zentrale Melde-Historie in einer Excel-Datei. Eine einmal erfolgte Meldung ('1') wird für den Monat nicht mehr überschrieben.

Verarbeitet eingehende Melde-Dateien, prüft sie auf Korrektheit und verschiebt sie.

Generiert am Ende drei separate Textdateien mit E-Mail-Adressen für Feedback, Erinnerungen und (nach 3 fehlenden Meldungen) Eskalationen.

Protokolliert alle Aktionen in einem Logfile.

--- KONFIGURATION: Pfade und Dateinamen ---
$basePath = "PATH"
$spoolerPath = Join-Path $basePath "SpoolerRSK"
$inputFolder = Join-Path $spoolerPath "EMAIL-ANHANG-ZIEL"
$stammdatenPath = Join-Path $basePath "Stammdaten\StammdatenMandanten.xlsx"
$meldeDatenPath = Join-Path $basePath "Stammdaten\Meldungen.xlsx"
$zielOrdnerArchiv = $spoolerPath
$feedbackMailFileBase = Join-Path $spoolerPath "E-Mail-Feedback"
$erinnerungsMailFile = Join-Path $spoolerPath "E-Mail-Erinnerung.txt"
$eskalationsMailFile = Join-Path $spoolerPath "E-Mail-Eskalation.txt"
$logfilePath = Join-Path $spoolerPath "Logfile.txt"
$cell_MandantenNummer = "E1"
$cell_Datum = "F1"
 
--- FUNKTION: Protokollierung ---
$logFileOverwritten = $false
function Write-Log($message) {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "$timestamp - $message"
if (-not $script:logFileOverwritten) {
$logEntry | Out-File -FilePath $logfilePath -Encoding UTF8
$script:logFileOverwritten = $true
} else {
$logEntry | Out-File -FilePath $logfilePath -Append -Encoding UTF8
}
Write-Host $logEntry
}
 
--- FUNKTION: Dateisperre prüfen ---
function Test-FileLock {
param ([string]$Path)
try {
$stream = [System.IO.File]::Open($Path, 'Open', 'Read', 'Write')
if ($stream) { $stream.Close() }; return true
} catch {
Write-Log "FEHLER: Datei '(Split-Path $Path -Leaf)' ist gesperrt und kann nicht verarbeitet werden."
return $false
}
}
 
--- Skriptstart ---
Write-Log "========== Skript 'RSK_Erinnerung_und_prüfen' gestartet =========="
$heutigesDatum = Get-Date
$zielMonatJahr = $heutigesDatum.ToString("MM.yyyy")
$spaltenHeaderMonat = $heutigesDatum.ToString("yyyy-MM")
Write-Log "Aktueller Prüfungsmonat: $zielMonatJahr (Spalten-Header: $spaltenHeaderMonat)"
 
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$excel.DisplayAlerts = $false
 
try {
Write-Log "Lese Stammdaten..."
if (-not (Test-Path $stammdatenPath)) { throw "Stammdaten-Datei nicht gefunden!" }
if (-not (Test-FileLock -Path $stammdatenPath)) { throw "Stammdaten-Datei ist gesperrt." }
$stammdatenWorkbook = $excel.Workbooks.Open($stammdatenPath, $true)
$stammdatenSheet = $stammdatenWorkbook.Worksheets.Item(1)
$stammdatenRange = $stammdatenSheet.UsedRange
$alleMandanten = @{}
for ($i = 2; $i -le $stammdatenRange.Rows.Count; $i++) {
$rskKreis = $stammdatenRange.Cells.Item($i, 4).Text
if ($rskKreis) {
$mandantNr = $stammdatenRange.Cells.Item($i, 1).Text
if ($mandantNr) {
$alleMandanten[$mandantNr] = @{
Name = $stammdatenRange.Cells.Item($i, 2).Text; RSKKreis = $rskKreis
Mail1 = $stammdatenRange.Cells.Item($i, 23).Text; Mail2 = $stammdatenRange.Cells.Item($i, 24).Text
Eskalation = $stammdatenRange.Cells.Item($i, 25).Text
}
}
}
}
stammdatenWorkbook.Close()Write−Log"($alleMandanten.Count) meldepflichtige Mandanten geladen."
 
Write-Log "Initialisiere Melde-Historie..."
if (-not (Test-Path $meldeDatenPath)) {
    Write-Log "Melde-Datei existiert nicht, wird neu erstellt."
    $meldeWorkbook = $excel.Workbooks.Add(); $meldeSheet = $meldeWorkbook.Worksheets.Item(1)
    $meldeSheet.Cells.Item(1, 1).Value2 = "Mandantennummer"
} else {
    if (-not (Test-FileLock -Path $meldeDatenPath)) { throw "Melde-Datei ist gesperrt."}
    $meldeWorkbook = $excel.Workbooks.Open($meldeDatenPath); $meldeSheet = $meldeWorkbook.Worksheets.Item(1)
}
$headerRange = $meldeSheet.Rows.Item(1); $spaltenIndex = 0
for ($j = 1; $j -le $meldeSheet.UsedRange.Columns.Count; $j++) {
    if (($headerRange.Cells.Item(1, $j).Text).Trim() -eq $spaltenHeaderMonat) { $spaltenIndex = $j; break }
}
if ($spaltenIndex -eq 0) {
    $spaltenIndex = $meldeSheet.UsedRange.Columns.Count + 1
    $meldeSheet.Cells.Item(1, $spaltenIndex).Value2 = $spaltenHeaderMonat
    Write-Log "Neue Spalte '$spaltenHeaderMonat' in Melde-Historie erstellt."
}
foreach ($mandantNr in $alleMandanten.Keys) {
    $findMandant = $meldeSheet.Columns.Item(1).Find($mandantNr)
    $zeilenIndex = if ($null -ne $findMandant) { $findMandant.Row } else { $meldeSheet.UsedRange.Rows.Count + 1 }
    if ($null -eq $findMandant) { $meldeSheet.Cells.Item($zeilenIndex, 1).Value2 = $mandantNr }
    if ($null -eq $meldeSheet.Cells.Item($zeilenIndex, $spaltenIndex).Value2) { $meldeSheet.Cells.Item($zeilenIndex, $spaltenIndex).Value2 = 0 }
}
$meldeWorkbook.Save(); $meldeWorkbook.Close()
Write-Log "Melde-Historie für '$spaltenHeaderMonat' initialisiert."
 
Write-Log "Beginne mit der Verarbeitung von Eingangsdateien..."
$inputFiles = Get-ChildItem -Path $inputFolder -Filter "*.xlsx"
if ($inputFiles.Count -eq 0) { Write-Log "Keine Dateien zur Verarbeitung gefunden." } else {
    if (-not (Test-FileLock -Path $meldeDatenPath)) { throw "Melde-Datei ist für Updates gesperrt." }
    $meldeWorkbook = $excel.Workbooks.Open($meldeDatenPath); $meldeSheet = $meldeWorkbook.Worksheets.Item(1)
    foreach ($file in $inputFiles) {
        try { $stream = [System.IO.File]::Open($file.FullName, 'Open', 'Read', 'Write'); $stream.Close() } catch { Write-Log "WARNUNG: Datei '$($file.Name)' ist gesperrt und wird übersprungen."; continue }
        $inputWorkbook = $excel.Workbooks.Open($file.FullName, $true); $inputSheet = $inputWorkbook.Worksheets.Item(1)
        $geleseneNummer = $inputSheet.Range($cell_MandantenNummer).Text
        $gelesenesDatum = $inputSheet.Range($cell_Datum).Text; $inputWorkbook.Close()
        if (-not $alleMandanten.ContainsKey($geleseneNummer)) { Write-Log "FEHLER: Mandant '$geleseneNummer' aus '$($file.Name)' ist unbekannt."; continue }
        if ($gelesenesDatum -notlike "*$zielMonatJahr*") { Write-Log "FEHLER: Datum '$gelesenesDatum' in '$($file.Name)' stimmt nicht."; continue }
        Write-Log "ERFOLG: Datei '$($file.Name)' für Mandant $($alleMandanten[$geleseneNummer].Name) ist gültig."
        $findMandant = $meldeSheet.Columns.Item(1).Find($geleseneNummer)
        if ($null -ne $findMandant) {
            $meldeSheet.Cells.Item($findMandant.Row, $spaltenIndex).Value2 = 1
            Write-Log "INFO: Status für '$geleseneNummer' auf '1' (gemeldet) gesetzt."
        }
        $neuerDateiname = "$($heutigesDatum.ToString('yyyy-MM'))_RSK_$geleseneNummer.xlsx"
        $zielPfad = Join-Path $zielOrdnerArchiv $neuerDateiname
        Move-Item -Path $file.FullName -Destination $zielPfad -Force
        Write-Log "INFO: Datei '$($file.Name)' nach '$zielPfad' verschoben."
    }
    $meldeWorkbook.Save(); $meldeWorkbook.Close()
}
 
Write-Log "Generiere E-Mail-Listen basierend auf finaler Melde-Historie..."
$feedbackMailsGruppiert = @{}; $erinnerungsMails = [System.Collections.Generic.List[string]]::new(); $eskalationsMails = [System.Collections.Generic.List[string]]::new()
if (-not (Test-FileLock -Path $meldeDatenPath)) { throw "Melde-Datei für E-Mail-Listen gesperrt." }
$meldeWorkbook = $excel.Workbooks.Open($meldeDatenPath, $true); $meldeSheet = $meldeWorkbook.Worksheets.Item(1)
 
$headerAktuell = $heutigesDatum.ToString("yyyy-MM"); $headerVormonat1 = ($heutigesDatum.AddMonths(-1)).ToString("yyyy-MM"); $headerVormonat2 = ($heutigesDatum.AddMonths(-2)).ToString("yyyy-MM")
$colIdxAktuell = 0; $colIdxVormonat1 = 0; $colIdxVormonat2 = 0
$headerRange = $meldeSheet.Rows.Item(1)
for ($j = 1; $j -le $meldeSheet.UsedRange.Columns.Count; $j++) {
    $headerText = ($headerRange.Cells.Item(1, $j).Text).Trim()
    if ($headerText -eq $headerAktuell) { $colIdxAktuell = $j }
    if ($headerText -eq $headerVormonat1) { $colIdxVormonat1 = $j }
    if ($headerText -eq $headerVormonat2) { $colIdxVormonat2 = $j }
}
 
foreach ($mandantNr in $alleMandanten.Keys) {
    $findMandant = $meldeSheet.Columns.Item(1).Find($mandantNr)
    if ($null -ne $findMandant) {
        $mandantInfo = $alleMandanten[$mandantNr]
        $statusAktuell = $meldeSheet.Cells.Item($findMandant.Row, $colIdxAktuell).Value2
        if ($statusAktuell -eq 1) { 
            $rskKreis = $mandantInfo.RSKKreis
            if (-not $feedbackMailsGruppiert.ContainsKey($rskKreis)) { $feedbackMailsGruppiert[$rskKreis] = [System.Collections.Generic.List[string]]::new() }
            if ($mandantInfo.Mail1) { $feedbackMailsGruppiert[$rskKreis].Add($mandantInfo.Mail1) }
            if ($mandantInfo.Mail2) { $feedbackMailsGruppiert[$rskKreis].Add($mandantInfo.Mail2) }
        } else { 
            if ($mandantInfo.Mail1) { $erinnerungsMails.Add($mandantInfo.Mail1) }
            if ($mandantInfo.Mail2) { $erinnerungsMails.Add($mandantInfo.Mail2) }
            $eskaliere = $false
            if ($colIdxAktuell -ne 0 -and $colIdxVormonat1 -ne 0 -and $colIdxVormonat2 -ne 0) {
                $statusVormonat1 = $meldeSheet.Cells.Item($findMandant.Row, $colIdxVormonat1).Value2
                $statusVormonat2 = $meldeSheet.Cells.Item($findMandant.Row, $colIdxVormonat2).Value2
                if (($statusAktuell -ne 1) -and ($statusVormonat1 -ne 1) -and ($statusVormonat2 -ne 1)) { $eskaliere = $true }
            }
            if ($eskaliere) {
                Write-Log "INFO: Mandant '$mandantNr' hat 3 Monate in Folge nicht gemeldet. Eskalation wird ausgelöst."
                if ($mandantInfo.Eskalation) { $eskalationsMails.Add($mandantInfo.Eskalation) }
            }
        }
    }
}
$meldeWorkbook.Close()
 
foreach ($kreis in $feedbackMailsGruppiert.Keys) { ($feedbackMailsGruppiert[$kreis] | Get-Unique) -join ";" | Out-File "$($feedbackMailFileBase)-$($kreis).txt" -Encoding UTF8BOM }
($erinnerungsMails | Get-Unique) -join ";" | Out-File $erinnerungsMailFile -Encoding UTF8BOM
($eskalationsMails | Get-Unique) -join ";" | Out-File $eskalationsMailFile -Encoding UTF8BOM
Write-Log "E-Mail-Listen wurden erfolgreich erstellt."
 
} catch { Write-Log "FATALER FEHLER: Skript wurde abgebrochen. Grund: (_.Exception.Message)" } finally { if ($excel) { $excel.Quit() [System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel) | Out-Null Remove-Variable excel -ErrorAction SilentlyContinue } Write-Log "========== Skript 'RSK_Erinnerung_und_prüfen' beendet ==========" }
//Author: Stefan Agethen //Letzte Bearbeitung: 2025//
skripte/rsk_erinnerung_und_pruefen_manuell.txt · Zuletzt geändert: von Stefan Agethen

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki