ConvertTo-Txt.ps1

<#
.SYNOPSIS
Prints a Report created by createSupportReport.ps1
 
.DESCRIPTION
Allows to show a human readable textreport of a json supportReport
 
.PARAMETER raw
    The Json containing the SupportReport
 
.EXAMPLE
    Creates a Report based on a json report
     
    .\createSupportReport.ps1 -tcCustomerNames "Opticon" -to 2020-01-31 | .\ConvertTo-Txt.ps1
#>

[CmdletBinding(SupportsShouldProcess=$true)]
param(
    [Parameter(ValueFromPipeline)]
    [string] $raw
)

$data = $raw | ConvertFrom-Json
$customers = $data | Sort-Object -Property @{Expression = "isClosed"; Descending = $True}, @{Expression = "type"; Descending = $False}, @{Expression = "categoryNumber"; Descending = $False} | Group-Object -Property customerCode

foreach($customer in $customers) 
{
    Write-Output "Details zu $($customer.Name)";

    $items = $customer.Group | Group-Object -Property subType
    foreach($subType in $items) 
    {
        $totalHours = $($subType.Group | Measure-Object -Property durationBilled -Sum).Sum
        $totalAmount = $($subType.Group | Measure-Object -Property amountBilled -Sum).Sum
        Write-Output "### $($subType.Count) $($subType.Name) - $($totalHours.ToString('0.##'))h - EUR $($totalAmount.ToString('0.##')) ### ";
        foreach($item in $subType.Group) 
        {
            $duration = $Null;
            $start = [datetime]$item.beginDate;
            $end = [datetime]$item.endDate;
            if($start.Date -eq $end.Date) { $duration = "am $($start.ToString('dd.MM.yyyy'))"; }
            else { $duration = "im Zeitraum $($start.ToString('dd.MM.yyyy'))-$($end.ToString('dd.MM.yyyy'))"; }
            
            if($item.isClosed) 
            {
                if($item.durationBilled -gt 0)
                {
                    $unbilledInfo = ""
                    if($item.durationUnbilled -gt 0) { $unbilledInfo = "(+$($item.durationUnbilled)h nicht verrechnet) " }
                    Write-Output " geschlossen : $($item.categoryName) $($item.taskCode) ($($item.taskDescription)) - $duration $($item.durationBilled.ToString('0.##'))h ${unbilledInfo}zu Euro $($item.hourlyRate)/h = Euro $($item.amountBilled.ToString('0.##'))";
                }
                else
                {
                    Write-Output " geschlossen : $($item.categoryName) $($item.taskCode) ($($item.taskDescription)) - $duration $($item.durationUnbilled.ToString('0.##'))h (nicht verrechnet) = Euro 0.00";
                }
            }
            else
            {
                Write-Output " noch offen : $($item.categoryName) $($item.taskCode) ($($item.taskDescription)) - $duration $($item.durationBilled.ToString('0.##'))h zu Euro $($item.hourlyRate)/h = Euro $($item.amountBilled.ToString('0.##'))";
            }
            if($item.type -eq "Ticket" -and ($item.firstResponseSLAViolation -or $item.resolutionSLAViolation)) 
            { 
                Write-Host " SLA : First Response SLA violation: $($item.firstResponseSLAViolation), Resolution SLA violation: $($item.resolutionSLAViolation) " -fore yellow
            }
            foreach($booking in $item.bookings) 
            {
                Write-Output " : $($booking.beginTime) - $($booking.endTime) : $($booking.Description) : $($booking.user)" 
            }
        }
    }
}