Public/AutoAttendant/Update-TeamsAutoAttendantAfterHours.ps1

# Module: TeamsFunctions
# Function: AutoAttendant
# Author: David Eberhardt
# Updated: 03-SEP 2022
# Status: RC

#TODO Change Parameters to have the prefix removed as it is clear that it is BusinessHours/AfterHours/HolidaySet anyway?
#TODO Add option to replace ONE Menu Option!

function Update-TeamsAutoAttendantAfterHours {
  <#
  .SYNOPSIS
    Changing, amending or replacing the After Hours Call Flow on existing Auto Attendants; Calling Set-CsAutoAttendant
  .DESCRIPTION
    Editing exiting Auto Attendants with Set-CsAutoAttendant requires manual creation of objects and surgical replacement.
    This script tries to simplify editing Auto Attendants by providing four functions:
    Update-TeamsAutoAttendant covers general Settings of the Auto Attendnat
    Update-TeamsAutoAttendantBusinessHours covers the Default Call Flow
    Update-TeamsAutoAttendantAfterHours covers the After Hours Call Flow
    Update-TeamsAutoAttendantHoliday covers the Holiday Call Flow
    Each individual Script can replace the full call flow with a previously created object,
    or amend some specific parts of the respective flow
  .PARAMETER Name
    Name of the Auto Attendant. Required to locate the Auto Attendant.
    Alternatively ID of the Auto Attendant for more precise location
  .PARAMETER AfterHoursGreeting
    Optional. Creates a Greeting for the After Hours Call Flow utilising New-TeamsAutoAttendantPrompt
    A supported Audio File or a text string that is parsed by the text-to-voice engine in the Language specified
    The last 4 digits will determine the type. For an AudioFile they are expected to be the file extension: '.wav', '.wma' or '.mp3'
    If CallFlows and CallHandlingAssociations are provided, this parameter will be ignored.
  .PARAMETER AfterHoursCallFlowOption
    Optional. Disconnect, TransferCallToTarget, Menu.
    TransferCallToTarget requires AfterHoursCallTarget. Menu requires AfterHoursMenu
  .PARAMETER AfterHoursCallTarget
    Optional. Requires AfterHoursCallFlowOption to be TransferCallToTarget. Creates a Callable entity for this Call Target
    Expected are UserPrincipalName (User, ResourceAccount), a TelURI (ExternalPstn), an Office 365 Group Name (SharedVoicemail)
  .PARAMETER AfterHoursMenu
    Optional. Requires AfterHoursCallFlowOption to be Menu and a AfterHoursCallTarget
  .PARAMETER AfterHoursSchedule
    Optional. Default Schedule to apply: One of: MonToFri9to5, MonToFri8to12and13to18, Open24x7
    A more granular Schedule can be used with the Parameter -Schedule
  .PARAMETER Schedule
    Optional. Custom Schedule object to apply for After Hours Call Flow
    Object created with New-TeamsAutoAttendantSchedule or New-CsAutoAttendantSchedule
    Using this parameter to provide a Schedule Object will override the Parameter -AfterHoursSchedule
  .PARAMETER EnableTranscription
    Optional. Where possible, tries to enable Voicemail Transcription.
    Effective only for SharedVoicemail Targets as an Operator or MenuOption. Otherwise has no effect.
  .PARAMETER PassThru
    Optional. Displays Auto Attendant Object after action.
  .PARAMETER Force
    Suppresses confirmation prompt to enable Users for Enterprise Voice, if Users are specified
    Currently no other impact
  .EXAMPLE
    Update-TeamsAutoAttendantAftersHours -Name "My Auto Attendant" -AftersHoursCallFlowOption TransferCallToTarget -AftersHoursCallTarget User@domain.com -EnableTranscription
 
    Changes the Auto Attendant "My Auto Attendant", setting the After Hours Call Flow to TransferCallToTarget, forwarding
    the call to the User User@domain.com and instructs the Command to enable transcription for all eligible call targets
    This only is available for SharedVoicemail so will be ignored for this command.
  .EXAMPLE
    Update-TeamsAutoAttendantAftersHours -Name "My Auto Attendant" -AftersHoursGreeting "Welcome to Contoso" -AftersHoursCallFlowOption Menu -AftersHoursMenu $MenuObject
 
    Changes the Auto Attendant "My Auto Attendant", setting the After Hours Call Flow to Menu, forwarding
    the call to the Menu provided with the MenuObject and also changing the Greeting to the Text-to-voice string provided.
  .INPUTS
    System.String
  .OUTPUTS
    System.Object
  .NOTES
    None
  .COMPONENT
    TeamsAutoAttendant
  .FUNCTIONALITY
    Creates a Auto Attendant with custom settings and friendly names as input
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Update-TeamsAutoAttendantAfterHours.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_TeamsAutoAttendant.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/
  #>


  [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', PositionalBinding = $false)]
  [Alias('Update-TeamsAAAfterHours')]
  [OutputType([System.Void])]
  param(
    [Parameter(Mandatory, Position = 0, ValueFromPipeline, HelpMessage = 'Name of the Auto Attendant')]
    [string]$Name,

    [Parameter(HelpMessage = 'After Hours Greeting - Text String or Recording')]
    [ArgumentCompleter( { '<Your Text-to-speech-string>', 'C:\Temp\' })]
    [string]$AfterHoursGreeting,

    [Parameter(HelpMessage = 'After Hours Call Flow - Default options')]
    [ValidateSet('Disconnect', 'TransferCallToTarget', 'Menu')]
    [string]$AfterHoursCallFlowOption,

    [Parameter(HelpMessage = 'After Hours Call Target - AfterHoursCallFlowOption = TransferCallToTarget')]
    [string]$AfterHoursCallTarget,

    [Parameter(HelpMessage = 'After Hours Call Target - AfterHoursCallFlowOption = Menu')]
    [object]$AfterHoursMenu,

    [Parameter(HelpMessage = 'Default Schedule to apply')]
    [ValidateSet('Open24x7', 'MonToFri9to5', 'MonToFri8to12and13to18')]
    [string]$AfterHoursSchedule,

    [Parameter(HelpMessage = 'Schedule Object created with New-TeamsAutoAttendantSchedule to apply')]
    [object]$Schedule,

    [Parameter(HelpMessage = 'Tries to Enable Transcription wherever possible')]
    [switch]$EnableTranscription,

    [Parameter(HelpMessage = 'By default, no output is generated, PassThru will display the Object changed')]
    [switch]$PassThru,

    [Parameter(HelpMessage = 'Suppresses confirmation prompt to enable Users for Enterprise Voice, if Users are specified')]
    [switch]$Force

  ) #param

  begin {
    Show-FunctionStatus -Level RC
    Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)"
    Write-Verbose -Message "Need help? Online: $global:TeamsFunctionsHelpURLBase$($MyInvocation.MyCommand)`.md"

    # Asserting AzureAD Connection
    if ( -not $script:TFPSSA) { $script:TFPSSA = Assert-AzureADConnection; if ( -not $script:TFPSSA ) { break } }

    # Asserting MicrosoftTeams Connection
    if ( -not (Assert-MicrosoftTeamsConnection) ) { break }

    # Setting Preference Variables according to Upstream settings
    if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') }
    if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') }
    if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') }
    if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { $DebugPreference = 'Continue' }
    if ( $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { $InformationPreference = 'Continue' }

    #Initialising Counters
    $private:StepsID0, $private:StepsID1 = Get-WriteBetterProgressSteps -Code $($MyInvocation.MyCommand.Definition) -MaxId 1
    $private:ActivityID0 = $($MyInvocation.MyCommand.Name)
    [int] $private:CountID0 = [int] $private:CountID1 = 1

    $StatusID0 = 'Verifying input'
    $CurrentOperationID0 = 'Validating CallFlows'
    Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0
    #region Processing AfterHours Parameters
    #VALIDATE Logic
    if ( $PSBoundParameters.ContainsKey('AfterHoursCallFlowOption') ) {
      switch ($AfterHoursCallFlowOption) {
        'TransferCallToTarget' {
          # Must contain Target
          if (-not $PSBoundParameters.ContainsKey('AfterHoursCallTarget')) {
            Write-Error -Message "AfterHoursCallFlowOption (TransferCallToTarget) - Parameter 'AfterHoursCallTarget' missing"
            break
          }

          # Must not contain a Menu
          if ($PSBoundParameters.ContainsKey('AfterHoursMenu')) {
            Write-Verbose -Message 'AfterHoursCallFlowOption (TransferCallToTarget) - Parameter AfterHoursMenu cannot be used and will be omitted!' -Verbose
            $PSBoundParameters.Remove('AfterHoursMenu')
          }
        }

        'Menu' {
          # Must contain a Menu
          if (-not $PSBoundParameters.ContainsKey('AfterHoursMenu')) {
            Write-Error -Message 'AfterHoursCallFlowOption (Menu) - AfterHoursMenu missing'
            break
          }
          else {
            if (($AfterHoursMenu | Get-Member | Select-Object -First 1).TypeName -notmatch 'Microsoft.Rtc.Management.Hosted.OAA.Models.Menu') {
              Write-Error -Message "AfterHoursCallFlowOption (Menu) - AfterHoursMenu not of the Type 'Microsoft.Rtc.Management.Hosted.OAA.Models.Menu'" -Category InvalidType
              break
            }
          }

          # Must not contain Target
          if ($PSBoundParameters.ContainsKey('AfterHoursCallTarget')) {
            Write-Verbose -Message "AfterHoursCallFlowOption (Menu) - Parameter 'AfterHoursCallTarget' cannot be used and will be omitted!"-Verbose
            $PSBoundParameters.Remove('AfterHoursCallTarget')
          }
        }

        'Disconnect' {
          # Must not contain a Menu
          if ($PSBoundParameters.ContainsKey('AfterHoursMenu')) {
            Write-Verbose -Message 'AfterHoursCallFlowOption (Disconnect) - Parameter AfterHoursMenu cannot be used and will be omitted!' -Verbose
            $PSBoundParameters.Remove('AfterHoursMenu')
          }

          # Must not contain Target
          if ($PSBoundParameters.ContainsKey('AfterHoursCallTarget')) {
            Write-Verbose -Message "AfterHoursCallFlowOption (Disconnect) - Parameter 'AfterHoursCallTarget' cannot be used and will be omitted!"-Verbose
            $PSBoundParameters.Remove('AfterHoursCallTarget')
          }
        }
      }
    }
    #endregion

    # Preparing Splatting Object for New-TeamsCallableEntity
    $TeamsCallableEntityParams = @{ 'ErrorAction' = 'Stop' }
    if ( $PSBoundParameters.ContainsKey('EnableTranscription') ) {
      $TeamsCallableEntityParams = @{ 'EnableTranscription' = $true }
    }
  } #begin

  process {
    Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)"
    #region PREPARATION
    $StatusID0 = 'Querying Object'
    # preparing Splatting Object
    $Parameters = $null

    #region Query Unique Element
    $CurrentOperationID0 = "Finding unique result for provided Name '$Name'"
    Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0
    if ( $Name -match $script:TFMatchGuid ) {
      #Identity or ObjectId
      Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand) - ID - '$Name'"
      $AAInstance = Get-CsAutoAttendant -Identity "$Name" -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
    }
    else {
      #Name
      Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand) - Name - '$Name'"
      # Initial Query to determine unique result (single object)
      $AAInstance = Get-CsAutoAttendant -NameFilter "$Name" -WarningAction SilentlyContinue
      $AAInstance = $AAInstance | Where-Object Name -EQ "$Name"
    }

    if ($null -eq $AAInstance) {
      Write-Error "'$Name' No Object found" -Category ParserError -RecommendedAction "Please check 'Name' provided" -ErrorAction Stop
    }
    elseif ($AAInstance.GetType().BaseType.Name -eq 'Array') {
      Write-Error "'$Name' Multiple Results found! Cannot determine unique result." -Category ParserError -RecommendedAction 'Please provide Auto Attendant GUID instead of name' -ErrorAction Stop
    }
    else {
      $AAID = $AAInstance.Identity
      Write-Information "INFO: '$Name' Auto Attendant found: Identity: $AAID"
      if ($PSBoundParameters.ContainsKey('Debug') -or $DebugPreference -eq 'Continue') {
        " Function: $($MyInvocation.MyCommand.Name) - Auto Attendant", ($AAInstance | Format-Table -AutoSize | Out-String).Trim() | Write-Debug
      }
    }
    #endregion

    # Defining Name for reference below
    $AAName = "$($AAInstance.Name)"
    #endregion

    #region SETTINGS
    #NOTE All Options in Region Settings use ID 1 for showing progress
    $ActivityID1 = 'After Hours Call Flow'
    $StatusID1 = 'Applying Settings'

    #region Finding Artefacts
    $AfterHoursCHA = $AAInstance.CallHandlingAssociations | Where-Object Type -EQ 'AfterHours'
    $AfterHoursScheduleId = $AfterHoursCHA.ScheduleId
    $AfterHoursCallFlowId = $AfterHoursCHA.CallFlowId

    $AfterHoursScheduleObject = $AAInstance.Schedules | Where-Object Id -EQ $AfterHoursScheduleId
    $AfterHoursCallFlow = $AAInstance.CallFlows | Where-Object Id -EQ $AfterHoursCallFlowId
    #endregion

    #region After Hours Greeting
    if ($PSBoundParameters.ContainsKey('AfterHoursGreeting')) {
      $CurrentOperationID1 = 'After Hours Call Flow - Greeting'
      Write-BetterProgress -Id 1 -Activity $ActivityID1 -Status $StatusID1 -CurrentOperation $CurrentOperationID1 -Step ($private:CountID1++) -Of $private:StepsID1
      try {
        $AfterHoursGreetingObject = New-TeamsAutoAttendantPrompt -String "$AfterHoursGreeting"
        if ( -not $AfterHoursGreetingObject) { throw } # Continuing only if CallTarget is created
        $AfterHoursCallFlow.Greetings = $AfterHoursGreetingObject
        Write-Information 'INFO: Pending Application: After Hours CallFlow changed: Greeting'
      }
      catch {
        Write-Warning -Message "'$AAName' CallFlow - AfterHoursCallFlow - Greeting not enumerated. Omitting Greeting"
      }
    }
    #endregion

    #region After Hours Schedule
    $CurrentOperationID1 = 'After Hours Call Flow - Schedule'
    Write-BetterProgress -Id 1 -Activity $ActivityID1 -Status $StatusID1 -CurrentOperation $CurrentOperationID1 -Step ($private:CountID1++) -Of $private:StepsID1
    if ( $PSBoundParameters.ContainsKey('Schedule') ) {
      if ($AfterHoursSchedule) {
        Write-Information 'INFO: Schedule - Custom Schedule Object overrides AfterHoursSchedule provided'
        $PSBoundParameters.Remove('AfterHoursSchedule')
      }

      # Testing provided Object Type
      if (($Schedule | Get-Member | Select-Object TypeName -First 1).TypeName -notmatch 'Microsoft.Rtc.Management.Hosted.Online.Models.Schedule') {
        Write-Error "Schedule - Type is not of 'Microsoft.Rtc.Management.Hosted.Online.Models.Schedule'. Please provide a Schedule Object" -Category InvalidType
        break
      }
    }
    elseif ( $PSBoundParameters.ContainsKey('AfterHoursSchedule') ) {
      Write-Information "INFO: '$Name' Schedule - AfterHoursSchedule provided, Using: '$AfterHoursSchedule'"
      # Creating Schedule
      $CurrentOperationID0 = 'After Hours Call Flow - Creating Schedule'
      Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0
      $Schedule = switch ($AfterHoursSchedule) {
        'Open24x7' {
          New-TeamsAutoAttendantSchedule -Name 'After Hours Schedule' -WeeklyRecurrentSchedule -BusinessDays MonToSun -BusinessHours AllDay -Complement
        }
        'MonToFri9to5' {
          New-TeamsAutoAttendantSchedule -Name 'After Hours Schedule' -WeeklyRecurrentSchedule -BusinessDays MonToFri -BusinessHours 9to5 -Complement
        }
        'MonToFri8to12and13to18' {
          New-TeamsAutoAttendantSchedule -Name 'After Hours Schedule' -WeeklyRecurrentSchedule -BusinessDays MonToFri -BusinessHours 8to12and13to18 -Complement
        }
      }
      Write-Verbose -Message "After Hours Schedule - Schedule created: '$AfterHoursSchedule'"

    }
    else {
      $Schedule = $null
      Write-Verbose -Message 'After Hours Schedule - Schedule not provided'
    }

    # Apply Schedule Object back to identified $AfterHoursSchedule
    if ( $Schedule ) {
      $AfterHoursScheduleObject = $Schedule
      $AfterHoursCHA.ScheduleId = $Schedule.Id
      Write-Information 'INFO: Pending Application: After Hours CallFlow changed: Schedule'
    }
    else {
      Write-Verbose -Message 'After Hours Schedule - No Schedule Object processed'

    }
    #endregion

    #region Processing AfterHoursCallFlowOption
    if ( $PSBoundParameters.ContainsKey('AfterHoursCallFlowOption') ) {
      $AfterHoursMenuObject = $null
      $CurrentOperationID1 = 'After Hours Call Flow - Call Flow Option'
      Write-BetterProgress -Id 1 -Activity $ActivityID1 -Status $StatusID1 -CurrentOperation $CurrentOperationID1 -Step ($private:CountID1++) -Of $private:StepsID1
      switch ($AfterHoursCallFlowOption) {
        'TransferCallToTarget' {
          Write-Verbose -Message "'$AAName' DefaultCallFlow - Transferring to Target"
          try {
            $AfterHoursCallTargetEntity = New-TeamsCallableEntity "$AfterHoursCallTarget" @TeamsCallableEntityParams
            if ( -not $AfterHoursCallTargetEntity) { throw } # Building Menu Only if Successful
            $AfterHoursMenuOptionTransfer = New-CsAutoAttendantMenuOption -Action TransferCallToTarget -CallTarget $AfterHoursCallTargetEntity -DtmfResponse Automatic
            $AfterHoursMenuObject = New-CsAutoAttendantMenu -Name 'After Hours Menu' -MenuOptions @($AfterHoursMenuOptionTransfer)
            Write-Information "INFO: '$AAName' After Hours Call Flow - Menu (TransferCallToTarget) created"
          }
          catch {
            Write-Warning -Message 'AfterHoursCallTarget - Error creating Call Target - Omiting change to DefaultCallFlow'
            $AfterHoursMenuOptionDefault = New-CsAutoAttendantMenuOption -Action DisconnectCall -DtmfResponse Automatic
            $AfterHoursMenuObject = New-CsAutoAttendantMenu -Name 'After Hours Menu' -MenuOptions @($AfterHoursMenuOptionDefault)
          }
        }
        'Menu' {
          Write-Verbose -Message "'$AAName' DefaultCallFlow - Menu"
          if ( $PSBoundParameters.ContainsKey('AfterHoursMenu') ) {
            # Menu is passed on as-is - $AfterHoursMenu is defined and attached
            $AfterHoursMenuObject = $AfterHoursMenu
            Write-Information "INFO: '$AAName' After Hours Call Flow - Menu (AfterHoursMenu) used"
          }
          else {
            # No custom / default Menu is currently created
            # $AfterHoursMenu is Mandatory. If this is built out, the check against this must also be removed!
          }
        }
        'Disconnect' {
          Write-Verbose -Message "'$AAName' DefaultCallFlow not provided or 'Disconnect' - Using default (Disconnect)"
          $AfterHoursMenuOptionDefault = New-CsAutoAttendantMenuOption -Action DisconnectCall -DtmfResponse Automatic
          $AfterHoursMenuObject = New-CsAutoAttendantMenu -Name 'After Hours Menu' -MenuOptions @($AfterHoursMenuOptionDefault)
        }
      }

      # Apply Menu Object back to identified $AfterHoursSchedule
      if ( $AfterHoursMenuObject ) {
        $AfterHoursCallFlow.Menu = $AfterHoursMenuObject
        Write-Information 'INFO: Pending Application: After Hours CallFlow changed: CallFlowOption/Menu'
      }
      else {
        Write-Warning -Message 'AfterHoursCallTarget - Error creating Menu - Omiting change to AfterHoursCallFlow'
      }
    }
    #endregion
    #endregion
    Write-Progress -Id 1 -Activity $ActivityID1 -Completed


    #region ACTION
    #Preparing Splatting Object
    $Parameters = @{
      'Instance'      = $AAInstance
      'WarningAction' = if ( $PSBoundParameters.ContainsKey('WarningAction') ) { $PSCmdlet.SessionState.PSVariable.GetValue('WarningAction') } else { 'Continue' }
      'ErrorAction'   = if ( $PSBoundParameters.ContainsKey('ErrorAction') ) { $PSCmdlet.SessionState.PSVariable.GetValue('ErrorAction') } else { 'Stop' }
    }

    Write-Verbose -Message '[PROCESS] Updating Auto Attendant'
    if ($PSBoundParameters.ContainsKey('Debug') -or $DebugPreference -eq 'Continue') {
      " Function: $($MyInvocation.MyCommand.Name) - Parameters (Set-CsAutoAttendant)", ($Parameters | Format-Table -AutoSize | Out-String).Trim() | Write-Debug
    }

    # Updating Auto Attendant (Set-CsAutoAttendant)
    $StatusID0 = 'Updating Auto Attendant'
    $CurrentOperationID0 = "'$AAName'"
    Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0
    if ($PSCmdlet.ShouldProcess("$AAName", 'Set-CsAutoAttendant')) {
      try {
        # Create the Auto Attendant with all enumerated Parameters passed through splatting
        $null = (Set-CsAutoAttendant @Parameters)
        #Write-Information "INFO: All pending changes applied to Auto Attendant Instance for '$AAName'"
        Write-Host "INFO: All pending changes applied to Auto Attendant Instance for '$AAName'" -ForegroundColor Magenta
      }
      catch {
        Write-Error -Message "Error updating the Auto Attendant: $($_.Exception.Message)" -Category InvalidResult
        return
      }
    }
    else {
      return
    }
    #endregion


    #region OUTPUT
    if ( $PassThru ) {
      $StatusID0 = 'Validation/PassThru'
      $CurrentOperationID0 = 'Re-Querying Object'
      Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0
      $AAFinal = Get-TeamsAutoAttendant -Name $AAInstance.Identity -Detailed -WarningAction SilentlyContinue
      #region Limiting output to Holiday Call Flows only
      $AHCHA = $AAFinal.CallHandlingAssociations | Where-Object Type -EQ AfterHours
      $AHCF = $AAFinal.CallFlows | Where-Object Name -EQ $($AHCHA.CallFlow)
      $AHSC = $AAFinal.Schedules | Where-Object Name -EQ $($AHCHA.Schedule)

      $AAFinal.CallFlows = $AHCHA
      $AAFinal.Schedules = $AHCF
      $AAFinal.CallHandlingAssociations = $AHSC
      #endregion
      Write-Output $AAFinal | Select-Object Callflows, Schedules, Callhandlingassociations | Format-List
    }
    #endregion
    Write-Progress -Id 0 -Activity $ActivityID0 -Completed

  } #process

  end {
    Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)"

  } #end
} # Update-TeamsAutoAttendantAfterHours