Functions/Public/Get-TogglUtilizationReport.ps1
<# .Synopsis Calculate a utilization report for all pay periods in the specified date range. .Description This cmdlet uses Toggl's tag functionality to classify time entries. The following tags are used: Billable Holiday Non-Billable PTO Training Utilized .Example Get-TogglUtilizationReport Generate a utilization report for the current pay period .Example Get-TogglUtilizationReport -From (Get-Date).AddMonths(-12) -ExcludeCurrentPeriod | Export-Csv -NoTypeInformation 'c:\temp\TogglUtilizationReport.csv' Generate a utilization report for the past year, excluding the current pay period, and outputs to a CSV file .Example Get-TogglUtilizationReport -From (Get-Date).AddMonths(-12) -ExcludeCurrentPeriod | Out-GridView Generate a utilization report for the past year, excluding the current pay period, and outputs to grid view .Link https://github.com/Dapacruz/Toggl.Functions #> function Get-TogglUtilizationReport { [CmdletBinding()] Param ( [Parameter(Position=0)] [datetime]$From, [Parameter(Position=1)] [datetime]$To, [switch]$ExcludeCurrentPeriod ) $work_days = 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' $report = @() # Normalize $From if (-not $From) { $From = Get-Date -Day 1 } if ($ExcludeCurrentPeriod) { $To = (Get-Date -Day 1).AddDays(-1) } elseif (-not $To) { $To = Get-Date } while ($From -le $To) { $month_first_day = Get-Date $From -Day 1 $month_last_day = $month_first_day.AddMonths(1).AddDays(-1) $normal_hours = 0 $total_hours = 0 $billable_hours = 0 $utilized_hours = 0 $training_hours = 0 $pto_hours = 0 $holiday_hours = 0 $non_billable_hours = 0 $overtime_hours = 0 # Determine period start and end $period_start = $From.Day if ($To -lt $month_last_day) { $period_end = $To.Day } else { $period_end = $month_last_day.Day } # Calculate normal working hours for the specified pay period for ($x=$period_start; $x -le $period_end; $x++) { $day = '{0:yyyy-MM}-{1}' -f $From, $x $day_of_week = (Get-Date $day).DayOfWeek if ($day_of_week -in $work_days) { $normal_hours += 8 } } [system.array]$detailed_report = Get-TogglDetailedReport -From ('{0:yyyy-MM}-{1}' -f $From, $period_start) -To ('{0:yyyy-MM}-{1}' -f $From, $period_end) $total_hours = ($detailed_report | Measure-Object -Property 'Duration(Hrs)' -Sum).Sum if ($total_hours -eq $null) { $total_hours = 0 } $billable_hours = ($detailed_report.Where{$_.WorkType -eq 'Billable'} | Measure-Object -Property 'Duration(Hrs)' -Sum).Sum if ($billable_hours -eq $null) { $billable_hours = 0 } $utilized_hours = ($detailed_report.Where{$_.WorkType -eq 'Utilized'} | Measure-Object -Property 'Duration(Hrs)' -Sum).Sum if ($utilized_hours -eq $null) { $utilized_hours = 0 } $training_hours = ($detailed_report.Where{$_.WorkType -eq 'Training'} | Measure-Object -Property 'Duration(Hrs)' -Sum).Sum if ($training_hours -eq $null) { $training_hours = 0 } $pto_hours = ($detailed_report.Where{$_.WorkType -eq 'PTO'} | Measure-Object -Property 'Duration(Hrs)' -Sum).Sum if ($pto_hours -eq $null) { $pto_hours = 0 } $holiday_hours = ($detailed_report.Where{$_.WorkType -eq 'Holiday'} | Measure-Object -Property 'Duration(Hrs)' -Sum).Sum if ($holiday_hours -eq $null) { $holiday_hours = 0 } $non_billable_hours = ($detailed_report.Where{$_.WorkType -eq 'Non-Billable'} | Measure-Object -Property 'Duration(Hrs)' -Sum).Sum if ($non_billable_hours -eq $null) { $non_billable_hours = 0 } $overtime_hours = $total_hours-$normal_hours if ($overtime_hours -lt 0) { $overtime_hours = 0 } if ($normal_hours -gt 0) { $percent_billable = ($billable_hours/($normal_hours-$pto_hours-$holiday_hours-$training_hours))*100 $percent_utilized = (($billable_hours+$utilized_hours)/($normal_hours-$pto_hours-$holiday_hours-$training_hours))*100 } else { $percent_billable = 0 $percent_utilized = 0 } # Output summary totals $obj = New-Object -TypeName PSObject # Insert custom TypeName (defined in $PSScriptRoot\format.ps1xml) to control default display $obj.PSTypeNames.Insert(0,'Toggl.Report.Utilization') Add-Member -InputObject $obj -MemberType NoteProperty -Name PeriodStart -Value ('{0:yyyy-MM-dd}' -f (Get-Date $From -Day $period_start)) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Total(hrs)' -Value ('{0:N2}' -f $total_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Normal(hrs)' -Value ('{0:N2}' -f $normal_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Overtime(hrs)' -Value ('{0:N2}' -f $overtime_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Training(hrs)' -Value ('{0:N2}' -f $training_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'PTO(hrs)' -Value ('{0:N2}' -f $pto_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Holiday(hrs)' -Value ('{0:N2}' -f $holiday_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Non-Billable(hrs)' -Value ('{0:N2}' -f $non_billable_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Utilized(hrs)' -Value ('{0:N2}' -f $utilized_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Billable(hrs)' -Value ('{0:N2}' -f $billable_hours) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Billable(%)' -Value ('{0:N0}' -f $percent_billable) Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Utilized(%)' -Value ('{0:N0}' -f $percent_utilized) $report += $obj # Advance to next pay period $From = Get-Date $From.AddMonths(1) -Day 1 } Write-Output $report } |