Public/AutoAttendant/Update-TeamsAutoAttendantBusinessHours.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? function Update-TeamsAutoAttendantBusinessHours { <# .SYNOPSIS Changing, amending or replacing the Business 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 BusinessHoursGreeting Optional. Replaces the Greeting for the Default Call Flow (during business hours) 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 DefaultCallFlow is provided, this parameter will be ignored. .PARAMETER BusinessHoursCallFlowOption Optional. Disconnect, TransferCallToTarget, Menu. TransferCallToTarget requires BusinessHoursCallTarget. Menu requires BusinessHoursMenu If DefaultCallFlow is provided, this parameter will be ignored. .PARAMETER BusinessHoursCallTarget Optional. Requires BusinessHoursCallFlowOption 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) If DefaultCallFlow is provided, this parameter will be ignored. .PARAMETER BusinessHoursMenu Optional. Requires BusinessHoursCallFlowOption to be Menu and expects an AutoAttendantMenuObject If DefaultCallFlow is provided, this parameter will be ignored. .PARAMETER DefaultCallFlow Optional. Call Flow Object to pass to Set-CsAutoAttendant (used as the Default Call Flow) Using this parameter to define the default Call Flow overrides all -BusinessHours Parameters .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 EnableSharedVoicemailSystemPromptSuppression Optional. Where possible, tries to suppress System Prompts. Effective only for SharedVoicemail Targets as an Operator or MenuOption. Otherwise has no effect. .PARAMETER ForceListenMenuEnabled Optional. Toggles ForceListenMenuEnabled on Call Flow Objects. Only has an effect for Menus with MenuOptions. .PARAMETER PassThru Optional. Displays Auto Attendant Object after action. .EXAMPLE Update-TeamsAutoAttendantBusinessHours -Name "My Auto Attendant" -TimeZone UTC-05:00 Changes the Auto Attendant "My Auto Attendant" and applies the TimeZone to UTC-05:00 .EXAMPLE Update-TeamsAutoAttendantBusinessHours -Name "My Auto Attendant" -LanguageId pt-BR -EnableVoiceResponse Changes the Auto Attendant "My Auto Attendant", setting the language setting to Portuguese (Brazil) It also enables Voice Responses if they are available for the language .EXAMPLE Update-TeamsAutoAttendantBusinessHours -Name "My Auto Attendant" -Operator "tel:+1555123456" -PassThru Changes the Auto Attendant "My Auto Attendant", setting the Operator as a Callable Entity (Forward to Pstn) PassThru will re-query the Auto Attendant object and display it afterwards. .EXAMPLE Update-TeamsAutoAttendantBusinessHours -Name "My Auto Attendant" -BusinessHoursCallFlowOption TransferCallToTarget -BusinessHoursCallTarget User@domain.com -EnableTranscription Changes the Auto Attendant "My Auto Attendant", setting the Default 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-TeamsAutoAttendantBusinessHours -Name "My Auto Attendant" -BusinessHoursGreeting "Welcome to Contoso" -BusinessHoursCallFlowOption Menu -BusinessHoursMenu $MenuObject Changes the Auto Attendant "My Auto Attendant", setting the Default 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-TeamsAutoAttendantBusinessHours.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', DefaultParameterSetName = 'Options', PositionalBinding = $false)] [Alias('Update-TeamsAABusinessHours')] [OutputType([System.Void])] param( [Parameter(Mandatory, Position = 0, ValueFromPipeline, HelpMessage = 'Name of the Auto Attendant')] [string]$Name, [Parameter(HelpMessage = 'Business Hours Greeting - Text String or Recording')] [ArgumentCompleter( { '<Your Text-to-speech-string>', 'C:\Temp\' })] [string]$BusinessHoursGreeting, [Parameter(ParameterSetName = 'Options', HelpMessage = 'Business Hours Call Flow - Default options')] [ValidateSet('Disconnect', 'TransferCallToTarget', 'Menu')] [string]$BusinessHoursCallFlowOption, [Parameter(ParameterSetName = 'Options', HelpMessage = 'Business Hours Call Target - BusinessHoursCallFlowOption = TransferCallToTarget')] [string]$BusinessHoursCallTarget, [Parameter(ParameterSetName = 'Options', HelpMessage = 'Business Hours Call Target - BusinessHoursCallFlowOption = Menu')] [object]$BusinessHoursMenu, [Parameter(Mandatory, ParameterSetName = 'CallFlow', HelpMessage = 'Default Call Flow')] [object]$DefaultCallFlow, [Parameter(HelpMessage = 'Tries to Enable Transcription wherever possible')] [boolean]$EnableTranscription, [Parameter(HelpMessage = 'Tries to Suppress System Prompts wherever possible')] [boolean]$EnableSharedVoicemailSystemPromptSuppression, [Parameter(HelpMessage = 'Enables ForceListen on CallFlow Objects')] [boolean]$ForceListenMenuEnabled, [Parameter(HelpMessage = 'By default, no output is generated, PassThru will display the Object changed')] [switch]$PassThru ) #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 DefaultCallFlow' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 #region Processing DefaultCallFlow VS BusinessHours* Parameters if ($PSBoundParameters.ContainsKey('DefaultCallFlow')) { # DefaultCallFlow Write-Information 'DefaultCallFlow - Overriding all BusinessHours-Parameters' if ($PSBoundParameters.ContainsKey('BusinessHoursGreeting')) { $PSBoundParameters.Remove('BusinessHoursGreeting') } if ($PSBoundParameters.ContainsKey('BusinessHoursCallFlowOption')) { $PSBoundParameters.Remove('BusinessHoursCallFlowOption') } if ($PSBoundParameters.ContainsKey('BusinessHoursCallTarget')) { $PSBoundParameters.Remove('BusinessHoursCallTarget') } # Testing provided Object Type if (($DefaultCallFlow | Get-Member | Select-Object TypeName -First 1).TypeName -ne 'Deserialized.Microsoft.Rtc.Management.Hosted.OAA.Models.CallFlow') { Write-Error "DefaultCallFlow - Type is not of 'Microsoft.Rtc.Management.Hosted.OAA.Models.CallFlow'. Please provide a Call Flow Object" -Category InvalidType break } } else { # BusinessHours Parameters if ( $PSBoundParameters.ContainsKey('BusinessHoursCallFlowOption') ) { switch ($BusinessHoursCallFlowOption) { 'TransferCallToTarget' { # Must contain Target if (-not $PSBoundParameters.ContainsKey('BusinessHoursCallTarget')) { Write-Error -Message "BusinessHoursCallFlowOption (TransferCallToTarget) - Parameter 'BusinessHoursCallTarget' missing" break } # Must not contain a Menu if ($PSBoundParameters.ContainsKey('BusinessHoursMenu')) { Write-Verbose -Message 'BusinessHoursCallFlowOption (TransferCallToTarget) - Parameter BusinessHoursMenu cannot be used and will be omitted!' -Verbose $PSBoundParameters.Remove('BusinessHoursMenu') } } 'Menu' { # Must contain a Menu if (-not $PSBoundParameters.ContainsKey('BusinessHoursMenu')) { Write-Error -Message 'BusinessHoursCallFlowOption (Menu) - BusinessHoursMenu missing' break } else { if (($BusinessHoursMenu | Get-Member | Select-Object -First 1).TypeName -notmatch 'Microsoft.Rtc.Management.Hosted.OAA.Models.Menu') { Write-Error -Message "BusinessHoursCallFlowOption (Menu) - BusinessHoursMenu not of the Type 'Microsoft.Rtc.Management.Hosted.OAA.Models.Menu'" -Category InvalidType break } } # Must not contain Target if ($PSBoundParameters.ContainsKey('BusinessHoursCallTarget')) { Write-Verbose -Message "BusinessHoursCallFlowOption (Menu) - Parameter 'BusinessHoursCallTarget' cannot be used and will be omitted!"-Verbose $PSBoundParameters.Remove('BusinessHoursCallTarget') } } 'Disconnect' { # Must not contain a Menu if ($PSBoundParameters.ContainsKey('BusinessHoursMenu')) { Write-Verbose -Message 'BusinessHoursCallFlowOption (Disconnect) - Parameter BusinessHoursMenu cannot be used and will be omitted!' -Verbose $PSBoundParameters.Remove('BusinessHoursMenu') } # Must not contain Target if ($PSBoundParameters.ContainsKey('BusinessHoursCallTarget')) { Write-Verbose -Message "BusinessHoursCallFlowOption (Disconnect) - Parameter 'BusinessHoursCallTarget' cannot be used and will be omitted!"-Verbose $PSBoundParameters.Remove('BusinessHoursCallTarget') } } } } } #endregion # Preparing Splatting Object for New-TeamsCallableEntity $TeamsCallableEntityParams = @{ 'ErrorAction' = 'Stop' } if ( $PSBoundParameters.ContainsKey('EnableTranscription') ) { $TeamsCallableEntityParams += @{ EnableTranscription = $EnableTranscription } } if ( $PSBoundParameters.ContainsKey('EnableSharedVoicemailSystemPromptSuppression') ) { $TeamsCallableEntityParams += @{ EnableSharedVoicemailSystemPromptSuppression = $EnableSharedVoicemailSystemPromptSuppression } } } #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 - Business Hours Call Flow #NOTE All Options in Region Settings use ID 1 for showing progress $ActivityID1 = 'Business Hours Call Flow' $StatusID1 = 'Applying Settings' if ( $DefaultCallFlow ) { $CurrentOperationID1 = 'Business Hours Call Flow - Default Call Flow' Write-BetterProgress -Id 1 -Activity $ActivityID1 -Status $StatusID1 -CurrentOperation $CurrentOperationID1 -Step ($private:CountID1++) -Of $private:StepsID1 # Using As-Is Write-Information "INFO: '$AAName' DefaultCallFlow - Custom Object provided. Over-riding other options (like switch 'BusinessHoursCallFlow')" $AAInstance.DefaultCallFlow = $DefaultCallFlow Write-Information 'INFO: Pending Application: DefaultCallFlow changed: Full Call Flow applied' } else { Write-Verbose -Message "'$AAName' DefaultCallFlow - No Custom Object - Processing 'BusinessHours'-Parameters" #region BusinessHoursGreeting if ( $PSBoundParameters.ContainsKey('BusinessHoursGreeting') ) { $CurrentOperationID1 = 'Business Hours Call Flow - Greeting' Write-BetterProgress -Id 1 -Activity $ActivityID1 -Status $StatusID1 -CurrentOperation $CurrentOperationID1 -Step ($private:CountID1++) -Of $private:StepsID1 try { $BusinessHoursGreetingObject = New-TeamsAutoAttendantPrompt -String "$BusinessHoursGreeting" if ( -not $BusinessHoursGreetingObject) { throw } # Continuing only if CallTarget is created Write-Information "INFO: '$AAName' Business Hours Call Flow - Greeting created" $AAInstance.DefaultCallFlow.Greetings = @($BusinessHoursGreetingObject) Write-Information 'INFO: Pending Application: DefaultCallFlow changed: Greeting' } catch { Write-Warning -Message "'$AAName' CallFlow - BusinessHoursCallFlow - Greeting not enumerated. Omitting Greeting" } } #endregion #region Processing BusinessHoursCallFlowOption if ( $PSBoundParameters.ContainsKey('BusinessHoursCallFlowOption') ) { $BusinessHoursMenuObject = $null $CurrentOperationID1 = 'Business Hours Call Flow - Call Flow Option' Write-BetterProgress -Id 1 -Activity $ActivityID1 -Status $StatusID1 -CurrentOperation $CurrentOperationID1 -Step ($private:CountID1++) -Of $private:StepsID1 switch ($BusinessHoursCallFlowOption) { 'TransferCallToTarget' { Write-Verbose -Message "'$AAName' DefaultCallFlow - Transferring to Target" try { $BusinessHoursCallTargetEntity = New-TeamsCallableEntity "$BusinessHoursCallTarget" @TeamsCallableEntityParams if ( -not $BusinessHoursCallTargetEntity) { throw } # Building Menu Only if Successful $BusinessHoursMenuOptionTransfer = New-CsAutoAttendantMenuOption -Action TransferCallToTarget -CallTarget $BusinessHoursCallTargetEntity -DtmfResponse Automatic $BusinessHoursMenuObject = New-CsAutoAttendantMenu -Name 'Business Hours Menu' -MenuOptions @($BusinessHoursMenuOptionTransfer) Write-Information "INFO: '$AAName' Business Hours Call Flow - Menu (TransferCallToTarget) created" } catch { Write-Warning -Message 'BusinessHoursCallTarget - Error creating Call Target - Omiting change to DefaultCallFlow' } } 'Menu' { Write-Verbose -Message "'$AAName' DefaultCallFlow - Menu" if ( $PSBoundParameters.ContainsKey('BusinessHoursMenu') ) { # Menu is passed on as-is - $BusinessHoursMenu is defined and attached $BusinessHoursMenuObject = $BusinessHoursMenu Write-Information "INFO: '$AAName' Business Hours Call Flow - Menu (BusinessHoursMenu) used" } else { # No custom / default Menu is currently created # $BusinessHoursMenu 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 Disconnect" $BusinessHoursMenuOptionDefault = New-CsAutoAttendantMenuOption -Action DisconnectCall -DtmfResponse Automatic $BusinessHoursMenuObject = New-CsAutoAttendantMenu -Name 'Business Hours Menu' -MenuOptions @($BusinessHoursMenuOptionDefault) } } # Applying $BusinessHoursMenuObject if ( $BusinessHoursMenuObject ) { $AAInstance.DefaultCallFlow.Menu = $BusinessHoursMenuObject Write-Information 'INFO: Pending Application: DefaultCallFlow changed: CallFlowOption/Menu' } else { Write-Warning -Message 'BusinessHoursCallTarget - Error creating Menu - Omiting change to DefaultCallFlow' } } #endregion #region Switches # ForceListenMenuEnabled if ( $PSBoundParameters.ContainsKey('ForceListenMenuEnabled') ) { $AAInstance.DefaultCallFlow.ForceListenMenuEnabled = $ForceListenMenuEnabled Write-Information "INFO: Pending Application: DefaultCallFlow changed: ForceListenMenuEnabled set to: $ForceListenMenuEnabled" } # Shared Voicemail Transcription & Skip System Prompt $AAInstance.DefaultCallFlow.Menu.MenuOptions | ForEach-Object { if ($_.CallTarget.Type -eq 'SharedVoicemail') { $SharedVoiceMailCallTarget = $_.Calltarget.Id | Get-TeamsCallableEntity # EnableTranscription $_.CallTarget.EnableTranscription = $EnableTranscription if ( $PSBoundParameters.ContainsKey('EnableTranscription') ) { Write-Information "INFO: Pending Application: DefaultCallFlow changed: Transcription set for MenuOption $($_.DtmfResponse -replace 'Tone', ''): '$($SharedVoiceMailCallTarget.Entity)' ($EnableTranscription)" } # EnableSharedVoicemailSystemPromptSuppression if ( $PSBoundParameters.ContainsKey('EnableSharedVoicemailSystemPromptSuppression') ) { $_.CallTarget.EnableSharedVoicemailSystemPromptSuppression = $EnableSharedVoicemailSystemPromptSuppression Write-Information "INFO: Pending Application: DefaultCallFlow changed: SkipSystemMessage set for MenuOption $($_.DtmfResponse -replace 'Tone', ''): '$($SharedVoiceMailCallTarget.Entity)' ($EnableSharedVoicemailSystemPromptSuppression)" } } } #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 Write-Output $AAFinal.DefaultCallFlow | Format-List } #endregion Write-Progress -Id 0 -Activity $ActivityID0 -Completed } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } # Update-TeamsAutoAttendantBusinessHours |