Public/Get-XMatterStaff.ps1

<#
.SYNOPSIS
    Generates weekly on-call schedules for a manager’s direct reports based on geographical location and team membership, efficiently managing on-call responsibilities.
 
.DESCRIPTION
    The Get-XMatterStaff function queries Active Directory to fetch direct reports for a specified manager, filtering them by a given continent.
    It schedules on-call duties over specified dates, organizing the schedule into week-long intervals from Saturday to Sunday.
    The function gives scheduling priority to members of the Linux team and ensures that on-call duties are rotated to prevent consecutive assignments to the same staff members.
 
.PARAMETER sAMAccountName
    The sAMAccountName of the manager.
 
.PARAMETER Continent
    The continent used to filter the direct reports.
 
.PARAMETER EndDate
    Specifies the end date for the on-call schedule period. The function will schedule on-call duties up to this date.
 
.PARAMETER LinuxTeam
    An array of names identifying members of the Linux team, who will be given priority in the on-call schedule.
 
.EXAMPLE
   Get-XMatterStaff -sAMAccountName "atanasan" -Continent "Europe" -EndDate "09/28/2024" -LinuxTeam @("Jane Smith","John Doe")
    This example generates an on-call schedule for the staff under manager 'jdoe' based in Europe, prioritizing the Linux team members Jane Smith and John Doe.
 
.EXAMPLE
    Get-XMatterStaff -sAMAccountName "atanasan" -Continent "Asia" -EndDate "09/28/2024" -LinuxTeam @("John Che","Will Smith")
    This example generates an on-call schedule for the staff under manager 'jdoes' based in Asia, prioritizing the Linux team members Will Smith and John Che.
 
.NOTES
    Requires Active Directory module and appropriate permissions to read Active Directory objects.
#>


Function Get-XMatterStaff {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$sAMAccountName,

        [ValidateSet("Asia", "Europe", "Americas")]
        [string]$Continent = "Europe",

        [Parameter(Mandatory = $true)]
        [DateTime]$EndDate,

        [string[]]$LinuxTeam
    )

    process {
        $staffList = @()

        if ($Continent -eq "Asia") {
           $directReports = Get-ADDirectReports -sAMAccountName $sAMAccountName -Continent $Continent -OnlyIT | Select-Object -ExpandProperty SamAccountName

        }Else{

        $directReports = Get-ADDirectReports -sAMAccountName $sAMAccountName -Continent $Continent -ExcludeJobTitle | Select-Object -ExpandProperty SamAccountName 

        $excludedAdmins = Get-ADDirectReports -sAMAccountName $sAMAccountName -Continent $Continent -ExcludeManager | Select-Object -ExpandProperty Name }

        if(($null -ne $excludedAdmins)){$staffList += $excludedAdmins}

        foreach ($name in $directReports) {
            $additionalReports = Get-ADDirectReports -sAMAccountName $name -Continent $Continent | Select-Object -ExpandProperty Name
            $staffList += $additionalReports
        }

        $staffDetails = foreach ($user in $staffList) {
            [PSCustomObject]@{
                Name         = $user
                Priority     = if ($user -in $LinuxTeam) { 1 } else { 0 }
                LastOnCall   = (Get-Date).AddDays(-14)
                BlockedDates = @()
                Primary      = 0  # Initialize the Primary count
                Secondary    = 0  # Initialize the Secondary count
            }
        }

        $currentDate = (Get-Date).Date
        $weekSchedules = @()

        while ($currentDate -le $EndDate) {
            if ($currentDate.DayOfWeek -eq 'Saturday') {
                $weekEnd = $currentDate.AddDays(1)

                $primary = $staffDetails | Where-Object { $_.LastOnCall -lt $currentDate.AddDays(-7) } | Sort-Object Priority, {Get-Random} | Select-Object -First 1
                $secondary = $staffDetails | Where-Object { $_.Name -ne $primary.Name -and $_.LastOnCall -lt $currentDate.AddDays(-7) } | Sort-Object {Get-Random} | Select-Object -First 1

                if ($primary) {
                    $primary.LastOnCall = $weekEnd
                    $primary.Primary++
                }
                if ($secondary) {
                    $secondary.LastOnCall = $weekEnd
                    $secondary.Secondary++
                }

                $weekSchedules += [PSCustomObject]@{
                    Date       = "$($currentDate.ToString('dd-MM-yyyy')) - $($weekEnd.ToString('dd-MM-yyyy'))"
                    Primary    = $primary.Name
                    Secondary  = $secondary.Name
                }
            }
            $currentDate = $currentDate.AddDays(1)
        }

        $weekSchedules | Write-Output
    }
}