diff --git a/src/img/20220202-212929-rdgkk5ibpn.png b/src/img/20220202-212929-rdgkk5ibpn.png new file mode 100644 index 00000000..3ca57eca Binary files /dev/null and b/src/img/20220202-212929-rdgkk5ibpn.png differ diff --git a/src/img/20220204-134305-axntyw9ix9.png b/src/img/20220204-134305-axntyw9ix9.png new file mode 100644 index 00000000..313fdd2a Binary files /dev/null and b/src/img/20220204-134305-axntyw9ix9.png differ diff --git a/src/img/20220204-134647-r5p68s9p2h.png b/src/img/20220204-134647-r5p68s9p2h.png new file mode 100644 index 00000000..587cbd48 Binary files /dev/null and b/src/img/20220204-134647-r5p68s9p2h.png differ diff --git a/src/img/20220206-124420-zdhir7q27u.png b/src/img/20220206-124420-zdhir7q27u.png new file mode 100644 index 00000000..7b41a8bd Binary files /dev/null and b/src/img/20220206-124420-zdhir7q27u.png differ diff --git a/src/img/20220212-085154-rkphfln0cy.png b/src/img/20220212-085154-rkphfln0cy.png new file mode 100644 index 00000000..28b74b33 Binary files /dev/null and b/src/img/20220212-085154-rkphfln0cy.png differ diff --git a/src/img/20220212-085905-lgtyacccuy.png b/src/img/20220212-085905-lgtyacccuy.png new file mode 100644 index 00000000..970487d8 Binary files /dev/null and b/src/img/20220212-085905-lgtyacccuy.png differ diff --git a/src/img/20220215-081521-bhUh8IrI7x.png b/src/img/20220215-081521-bhUh8IrI7x.png new file mode 100644 index 00000000..4a14acd4 Binary files /dev/null and b/src/img/20220215-081521-bhUh8IrI7x.png differ diff --git a/src/img/aa-cq-management-getting-id.png b/src/img/aa-cq-management-getting-id.png new file mode 100644 index 00000000..3d6bd18d Binary files /dev/null and b/src/img/aa-cq-management-getting-id.png differ diff --git a/src/pages/blog/2022-01-31-manage-call-queue-and-auto-attendant.mdx b/src/pages/blog/2022-01-31-manage-call-queue-and-auto-attendant.mdx new file mode 100644 index 00000000..072c27f3 --- /dev/null +++ b/src/pages/blog/2022-01-31-manage-call-queue-and-auto-attendant.mdx @@ -0,0 +1,671 @@ +--- +templateKey: blog-post +title: Manage Call Queue and Auto Attendant +date: 2022-01-31T19:15:49.500Z +description: How to manage Call Queue and Auto Attendant settings with PowerShell +featuredpost: false +tags: + - teams + - powershell + - call queue + - auto attendant +--- +## Prerequisites + +## Preparation + +For this article, we'll use a test attendant. We'll also modify the call queue, where the calls land after going through auto attendant. + +Let's save their names to variables: + +```powershell +$attendantName = 'ATT_TEST' +$callQueueName = 'CQ_TEST' +``` + +### Getting the identifiers + +Next, we'll use PowerShell to pull call queue and auto attendant objects. We'll use [`Get-CsAutoAttendant`](https://docs.microsoft.com/en-us/powershell/module/skype/get-csautoattendant?view=skype-ps) and [`Get-CsCallQueue`](https://docs.microsoft.com/en-us/powershell/module/skype/get-cscallqueue?view=skype-ps). + + + +We can also get the identity from the Teams Admin Center. When we edit an auto attendant or a call queue, id is the last part of the page URL: + +![](../../img/aa-cq-management-getting-id.png "Getting ID from the Teams Admin Center URL") + + + +Both cmdlets have similar parameters. Two of them might be useful to get the identifiers of our objects: `Identity` and `NameFilter`. Both parameters accept a string. + +We will use `NameFilter` to get our objects. We need to be careful though. Using `NameFilter` returns all objects matching the filter. For example, if our filter is *Test*, we'll get the objects with names: + +* Test (this is desired) +* Test2 +* NotTest + +After the *Get-* cmdlets we'll add `Where-Object` at the end. This is to ensure that we only use the object with the exact name we provided: + +```powershell +$aa = Get-CsAutoAttendant -NameFilter $attendantName | + Where-Object Name -eq $attendantName +$cq = Get-CsCallQueue -NameFilter $callQueueName | + Where-Object Name -eq $callQueueName +``` + +We now have our objects saved to the variable. Let's start modifying them! + + + +The activities below are not dependent (unless specified otherwise). We can use only one of them and the effect will be the same. + + + +## Managing general options + +### Changing the operator to a person + +The operator of an auto attendant is a callable entity. There is one difference in comparison to other entities (person, voice app, or phone number). When we create the menu, there's a predefined voice command, which redirects to the operator. + +In this example, we'll set Megan Bowen to be the auto attendant operator: + +```powershell +# Here we enter the User Principal Name +$operatorUPN = 'MeganB@contoso.com' + +# We define callable entity using Identity +$operatorObjectId = (Get-CsOnlineUser $operatorUPN).Identity +$callableEntityPersonParams = @{ + Identity = $operatorObjectId + Type = 'User' +} +$callableEntityPerson = New-CsAutoAttendantCallableEntity @callableEntityPersonParams + +# We set the operator +$aa.Operator = $callableEntityPerson + +# And we save +Set-CsAutoAttendant -Instance $aa +``` + +Next time we open the attendant in Teams Admin Center, we should see the operator set: + +![Megan Bowen set as an operator in Teams Admin Center](../../img/20220215-081521-bhUh8IrI7x.png) + +### Changing the operator to the call queue + +We can also set the group of people to act as an operator. We use a call queue for that. + +In the example below we'll provide the ID of the existing call queue. Then we'll set it as an operator. + +```powershell +# Here we enter the call queue name +$operatorCallQueueName = 'CQ_TEST' + +# We define callable entity using the resource account +$operatorQueue = Get-CsCallQueue -NameFilter $operatorCallQueueName | + Where-Object Name -eq $operatorCallQueueName +$operatorQueueAccountId = $operatorQueue.ApplicationInstances[0] +$callableEntityQueueParams = @{ + Identity = $operatorQueueAccountId + Type = 'ApplicationEndpoint' +} +$callableEntityQueue = New-CsAutoAttendantCallableEntity @callableEntityQueueParams + +# We set the operator +$aa.Operator = $callableEntityQueue + +# And we save +Set-CsAutoAttendant -Instance $aa +``` + + + +We might get the error saying *New-CsAutoAttendantCallableEntity: Cannot bind argument to parameter 'Identity' because it is an empty string.* + +In that case, our call queue might not have the resource account assigned yet. We must create the resource account, assign it, and try again. + + + +### Changing the operator to the auto attendant + +Using an auto attendant as an operator allows to define a workflow for contacting the operator. The procedure is similar to setting a call queue as an operator: + +```powershell +# Here we enter the auto attendant name +$operatorAutoAttendantName = 'ATT_RobTest' + +# We define callable entity using the resource account +$operatorAttendant = Get-CsAutoAttendant -NameFilter $operatorAutoAttendantName | + Where-Object Name -eq $operatorAutoAttendantName +$operatorAttendantAccountId = $operatorAttendant.ApplicationInstances[0] +$callableEntityAttendantParams = @{ + Identity = $operatorAttendantAccountId + Type = 'ApplicationEndpoint' +} +$callableEntityAttendant = New-CsAutoAttendantCallableEntity @callableEntityAttendantParams + +# We set the operator +$aa.Operator = $callableEntityAttendant + +# And we save +Set-CsAutoAttendant -Instance $aa +``` + + + +We might get the error saying *New-CsAutoAttendantCallableEntity: Cannot bind argument to parameter 'Identity' because it is an empty string.* + +In that case, our auto attendant might not have the resource account assigned yet. We must create the resource account, assign it, and try again. + + + +### Changing the operator to the phone number + +The only callable entity which we haven't set is the phone number. Let's set it, too. + +```powershell +# Here we enter the number +# It must be in E.164 format +$operatorNumber = '+48123456789' + +# We create the respective entity +$callableEntityNumberParams = @{ + Identity = $operatorNumber + Type = 'ExternalPstn' +} +$callableEntityNumber = New-CsAutoAttendantCallableEntity @callableEntityNumberParams + +# We set the operator +$aa.Operator = $callableEntityNumber + +# And we save +Set-CsAutoAttendant -Instance $aa +``` + +### Removing the operator + +To remove the operator we need to nullify the property: + +```powershell +# We set the operator to $null +$aa.Operator = $null + +# And we save +Set-CsAutoAttendant -Instance $aa +``` + +### Changing the time zone + +Microsoft provides a cmdlet to find out which time zones are supported by auto attendants. The cmdlet is [`Get-CsAutoAttendantSupportedTimeZone`](https://docs.microsoft.com/en-us/powershell/module/skype/get-csautoattendantsupportedtimezone?view=skype-ps). We'll use it to find out the name of the specific zone we'd like to set. + +In this example, I'll try to set the time zone used in Poland. It is UTC+1 and should have Warsaw in its name. + +Let's run the `Get-CsAutoAttendantSupportedTimeZone` . We'll check the structure of the data returned: + +![](../../img/20220212-085154-rkphfln0cy.png "Type of data returned by Get-CsAutoAttendantSupportedTimeZone cmdlet") + +As we can see, each entry has two properties: *Id* and *DisplayName*. We'll filter using the DisplayName. Then we'll use the *Id* and pass it to the auto attendant object. + +We'll first try to filter using the hours' difference *+01:00* and then based on the city name (*Warsaw*). + +```powershell +# By time difference +Get-CsAutoAttendantSupportedTimeZone | + Where-Object DisplayName -like '*+01:00*' + +# By city name +Get-CsAutoAttendantSupportedTimeZone | + Where-Object DisplayName -like '*warsaw*' +``` + +Here's what is returned in both cases: + +![](../../img/20220212-085905-lgtyacccuy.png "Filtering supported time zones") + +Now, when we know the identifier, we can pass it to the auto attendant object: + +```powershell +# Copying data from the filtering above +$timeZoneId = 'Central European Standard Time' + +# Setting the object +$aa.timeZoneId = $timeZoneId + +# And saving +Set-CsAutoAttendant -Instance $aa +``` + +## Managing default call flow + +In this section, we'll manage the options available under the *Call flow* tab. These options will be effective during business hours on business (non-holiday) days. + +We have two areas to manage in this tab: greeting and the destination. Destination specifies where to route the call after the greeting. + +### Changing default greeting + +Ok, something simple first - let's change a greeting for the auto attendant default workflow. Our greeting will be of text-to-speech type: + +```powershell +# First we define the greeting +$TTSPrompt = New-CsAutoAttendantPrompt -TextToSpeechPrompt "Welcome to Contoso!" +# Then we overwrite current AA configuration +$aa.DefaultCallFlow.Greetings = @($TTSPrompt) +# And we set the auto attendant +Set-CsAutoAttendant -Instance $aa +``` + +We can verify the prompt is saved successfully: + +```powershell +# We pull the AA info again +$aa = Get-CsAutoAttendant -NameFilter $attendantName | + Where-Object Name -eq $attendantName +# And now we list +$aa.DefaultCallFlow.Greetings +``` + +The output should look similar to the image below: + +![](../../img/20220202-212929-rdgkk5ibpn.png "Verifying updated text-to-speech prompt") + +### Changing default greeting to audio file + +Changing the default greeting to the audio file is very similar. We'll use the example from the [`New-CsAutoAttendantPrompt` documentation](https://docs.microsoft.com/en-us/powershell/module/skype/new-csautoattendantprompt?view=skype-ps): + +```powershell +# These three lines create the prompt +# If you use Windows PowerShell (5.1 or lower) use: +$content = Get-Content "C:\temp\welcome.wav" -ReadCount 0 -Encoding byte +# For PowerShell (multi-platform) use: +$content = Get-Content "C:\temp\welcome.wav" -ReadCount 0 -AsByteStream +# And then for any platform +$audioFile = Import-CsOnlineAudioFile -ApplicationId "OrgAutoAttendant" -FileName "welcome.wav" -Content $content +$audioFilePrompt = New-CsAutoAttendantPrompt -AudioFilePrompt $audioFile +# Now we use another variable +$aa.DefaultCallFlow.Greetings = @($audioFilePrompt) +# And we set the auto attendant again +Set-CsAutoAttendant -Instance $aa +``` + +### Redirecting the call to the person + +Ok, let's make our auto attendant redirect the call to Megan Bowen: + +```powershell +# Here we enter the User Principal Name +$redirectPersonUPN = 'MeganB@contoso.com' + +# We define callable entity using Identity +$redirectPersonObjectId = (Get-CsOnlineUser $redirectPersonUPN).Identity +$callableEntityPersonParams = @{ + Identity = $redirectPersonObjectId + Type = 'User' +} +$callableEntityPerson = New-CsAutoAttendantCallableEntity @callableEntityPersonParams + +# We need menu option +$newAAPersonMenuOptionParams = @{ + Action = 'TransferCallToTarget' + DtmfResponse = 'Automatic' + CallTarget = $callableEntityPerson +} +$AAPersonMenuOption = New-CsAutoAttendantMenuOption @newAAPersonMenuOptionParams + +# Now, we update the default menu options +$aa.DefaultCallFlow.Menu.MenuOptions = @($AAPersonMenuOption) + +# And we set the auto attendant +Set-CsAutoAttendant -Instance $aa +``` + +### Redirecting the call to the call queue + +Our auto attendant can work as a proxy to the call queue. Let's set it up: + +```powershell +# Here we enter the call queue name +$redirectCallQueueName = 'CQ_TEST' + +# We define callable entity using the resource account +$redirectQueue = Get-CsCallQueue -NameFilter $redirectCallQueueName | + Where-Object Name -eq $redirectCallQueueName +$redirectQueueAccountId = $redirectQueue.ApplicationInstances[0] +$callableEntityQueueParams = @{ + Identity = $redirectQueueAccountId + Type = 'ApplicationEndpoint' +} +$callableEntityQueue = New-CsAutoAttendantCallableEntity @callableEntityQueueParams + +# We need menu option +$newAAQueueMenuOptionParams = @{ + Action = 'TransferCallToTarget' + DtmfResponse = 'Automatic' + CallTarget = $callableEntityQueue +} +$AAQueueMenuOption = New-CsAutoAttendantMenuOption @newAAQueueMenuOptionParams + +# Now, we update the default menu options +$aa.DefaultCallFlow.Menu.MenuOptions = @($AAQueueMenuOption) + +# And we set the auto attendant +Set-CsAutoAttendant -Instance $aa +``` + + + +We might get the error saying *New-CsAutoAttendantCallableEntity: Cannot bind argument to parameter 'Identity' because it is an empty string.* + +In that case, our call queue might not have the resource account assigned yet. We must create the resource account, assign it, and try again. + + + +### Redirecting the call to the auto attendant + +Our auto attendant can redirect the call to another attendant. Let's see, how to configure such workflow: + +```powershell +# Here we enter the auto attendant name +$redirectAutoAttendantName = 'ATT_RobTest' + +# We define callable entity using the resource account +$redirectAttendant = Get-CsAutoAttendant -NameFilter $redirectAutoAttendantName | + Where-Object Name -eq $redirectAutoAttendantName +$redirectAttendantAccountId = $redirectAttendant.ApplicationInstances[0] +$callableEntityAttendantParams = @{ + Identity = $redirectAttendantAccountId + Type = 'ApplicationEndpoint' +} +$callableEntityAttendant = New-CsAutoAttendantCallableEntity @callableEntityAttendantParams + +# We need menu option +$newAAAttendantMenuOptionParams = @{ + Action = 'TransferCallToTarget' + DtmfResponse = 'Automatic' + CallTarget = $callableEntityAttendant +} +$AAAttendantMenuOption = New-CsAutoAttendantMenuOption @newAAAttendantMenuOptionParams + +# Now, we update the default menu options +$aa.DefaultCallFlow.Menu.MenuOptions = @($AAAttendantMenuOption) + +# And we set the auto attendant +Set-CsAutoAttendant -Instance $aa +``` + + + +We might get the error saying *New-CsAutoAttendantCallableEntity: Cannot bind argument to parameter 'Identity' because it is an empty string.* + +In that case, our auto attendant might not have the resource account assigned yet. We must create the resource account, assign it, and try again. + + + +### Redirecting the call to the phone number + +### Redirecting the call to the voicemail + +### Redirecting the call to the menu + +## Managing the out-of-hours workflow + +Let's now do the changes to the out-of-hours workflow. + +### Checking if out-of-hours workflow exists + +First things first - the out-of-hours workflow must be defined. Let's check if we have it. + +We'll check if there's an existing call handling association with the type *AfterHours*: + +```powershell +$aa.CallHandlingAssociations | Where-Object {$_.Type.Value -eq 'AfterHours'} +``` + +We should see the object returned: + +![](../../img/20220206-124420-zdhir7q27u.png "Checking if out-of-hours association exists") + +If we don't see anything, we need to add the workflow first. + +### Adding out-of-hours workflow + +TO BE TESTED AGAIN + +When we create an auto attendant we don't need to specify an out-of-hours workflow. If we hit **Submit** in the **Call flow** window (as in the image below), it won't be created: + +![](../../img/20220204-134305-axntyw9ix9.png "Call flow window in auto attendant creator") + +We can check if that's the case by inspecting the value of the *Call flows* property in the `$aa` variable. If it's empty, as in the image below, the out-of-hours workflow is not defined: + +![](../../img/20220204-134647-r5p68s9p2h.png "Inspecting Call Flows value via PowerShell") + +If there's no out-of-hours workflow, we won't be able to modify it. Modifying is described in the later stages. Let's now take care of the workflow. + +To create a workflow, we'll use [`New-CsAutoAttendantCallFlow` cmdlet](https://docs.microsoft.com/en-us/powershell/module/skype/new-csautoattendantcallflow?view=skype-ps). + + + +The script below assumes there's no holiday workflow. If there's one defined, it'll be overwritten! + + + +```powershell +# First, menu option +$newAAOOHMenuOptionParams = @{ + Action = "DisconnectCall" + DtmfResponse = "Automatic" +} +$AAOOHMenuOption = New-CsAutoAttendantMenuOption @newAAOOHMenuOptionParams + +# Then, menu +$newAAMenuParams = @{ + Name = "After hours call flow" + MenuOptions = @($AAOOHMenuOption) +} +$AAOOHMenu = New-CsAutoAttendantMenu @newAAMenuParams + +# Optional greeting +$newAAOOHGreetingParams = @{ + TextToSpeechPrompt = "The office is closed now" +} +$AAOOHGreeting = New-CsAutoAttendantPrompt @newAAOOHGreetingParams + +# And then, the workflow +$newAAOOHFlowParams = @{ + Name = "$attendantName After hours call flow" + Menu = $AAOOHMenu + Greetings = $AAOOHGreeting +} +$AAOOHFlow = New-CsAutoAttendantCallFlow @newAAOOHFlowParams + +# Now, assigning the workflow +$aa.CallFlows = @($AAOOHFlow) + +# We also need to assign the schedule +# Let's create it first +$tr = New-CsOnlineTimeRange -Start 00:00 -End 1.00:00 +$scheduleOOHParams = @{ + Name = "After hours $attendantName" + WeeklyRecurrentSchedule = $true + MondayHours = @($tr) + TuesdayHours = @($tr) + WednesdayHours = @($tr) + ThursdayHours = @($tr) + FridayHours = @($tr) + Complement = $true +} +$OOHSchedule = New-CsOnlineSchedule @scheduleOOHParams + +# And now, assign +$aa.Schedules = @($OOHSchedule) + +# And the same with call handling association +# Creating +$OOHCallHandlingAssociationParams = @{ + CallFlowId = $AAOOHFlow.Id + ScheduleId = $OOHSchedule.Id + Type = 'AfterHours' +} +$OOHAssociation = New-CsAutoAttendantCallHandlingAssociation @OOHCallHandlingAssociationParams + +# And saving +$aa.CallHandlingAssociations = @($OOHAssociation) + +## TODO Fix Set-CsAutoAttendant: Schedule not found. Probably requires specifying configuration id for a schedule +# And saving +Set-CsAutoAttendant -Instance $aa +``` + +### Changing business hours + +In this example, we'll change the business hours. Outside the defined schedule, the out-of-hours workflow will be triggered. + +We'll set the business hours from 9 AM to 5 PM. On Friday, we'll add the additional break between 1 PM and 2 PM. + +```powershell +# Find out-of-hours association +$OOHAssociation = $aa.CallHandlingAssociations | + Where-Object {$_.Type.Value -eq 'AfterHours'} + +# Find the respective schedule +$OOHSchedule = $aa.Schedules | + Where-Object Id -eq $OOHAssociation.ScheduleId + +# Find the respective call flow +$OOHCallFlow = $aa.CallFlows | + Where-Object Id -eq $OOHAssociation.CallFlowId + +# Time range for Monday-Thursday +$weekTimeRange = New-CsOnlineTimeRange -Start 9:00 -End 17:00 +# And for Friday +$fridayTimeRangeMorning = New-CsOnlineTimeRange -Start 9:00 -End 13:00 +$fridayTimeRangeAfternoon = New-CsOnlineTimeRange -Start 14:00 -End 17:00 + +# Setting the schedule +$OOHNewScheduleParams = @{ + Name = "After hours $attendantName" + WeeklyRecurrentSchedule = $true + Complement = $true + MondayHours = @($weekTimeRange) + TuesdayHours = @($weekTimeRange) + WednesdayHours = @($weekTimeRange) + ThursdayHours = @($weekTimeRange) + FridayHours = @($fridayTimeRangeMorning, $fridayTimeRangeAfternoon) + SaturdayHours = @($null) + SundayHours = @($null) +} +$OOHNewSchedule = New-CsOnlineSchedule @OOHNewScheduleParams + +# Generating the association +$OOHCallHandlingAssociationParams = @{ + CallFlowId = $OOHCallFlow.Id + ScheduleId = $OOHNewSchedule.Id + Type = 'AfterHours' +} +$OOHAssociation = New-CsAutoAttendantCallHandlingAssociation @OOHCallHandlingAssociationParams + +# Setting the object +$aa.CallHandlingAssociations = @($OOHAssociation) + +# And saving +Set-CsAutoAttendant -Instance $aa +``` + +### Removing business hours + +### Changing an out-of-hours greeting to text-to-speech + +Let's change the greeting we use out of hours. + +We'll find the workflow responsible for after-hours call handling. Then we'll use [`New-CsAutoAttendantPrompt` cmdlet](https://docs.microsoft.com/en-us/powershell/module/skype/new-csautoattendantprompt?view=skype-ps) to create a new text-to-speech prompt. Then we'll replace the existing one. + +```powershell +# Find out-of-hours association +$OOHAssociation = $aa.CallHandlingAssociations | + Where-Object {$_.Type.Value -eq 'AfterHours'} + +# Find the respective call flow +$OOHCallFlow = $aa.CallFlows | + Where-Object Id -eq $OOHAssociation.CallFlowId + +# Now we define the greeting +$OOHTTSPrompt = New-CsAutoAttendantPrompt -TextToSpeechPrompt "Our offices are closed now!" +# Then we overwrite the current configuration +$OOHCallFlow.Greetings = @($OOHTTSPrompt) +# And we set the auto attendant +Set-CsAutoAttendant -Instance $aa +``` + +### Changing an out-of-hours greeting to an audio file + +We'll find the workflow responsible for after-hours call handling. Then we'll use [`New-CsAutoAttendantPrompt` cmdlet](https://docs.microsoft.com/en-us/powershell/module/skype/new-csautoattendantprompt?view=skype-ps) to create a new prompt from an audio file. Then we'll replace the existing one. + +```powershell +# Find out-of-hours association +$OOHAssociation = $aa.CallHandlingAssociations | + Where-Object {$_.Type.Value -eq 'AfterHours'} + +# Find the respective call flow +$OOHCallFlow = $aa.CallFlows | + Where-Object Id -eq $OOHAssociation.CallFlowId + +# These three lines creates the prompt +# If you use Windows PowerShell (5.1 or lower) use: +$OOHFileContent = Get-Content "C:\temp\ooh-welcome.wav" -ReadCount 0 -Encoding byte +# For PowerShell (multi-platform) use: +$OOHFileContent = Get-Content "C:\temp\ooh-welcome.wav" -ReadCount 0 -AsByteStream +# And then for any platform +$OOHAudioFile = Import-CsOnlineAudioFile -ApplicationId "OrgAutoAttendant" -FileName "ooh-welcome.wav" -Content $OOHFileContent +$OOHAudioFilePrompt = New-CsAutoAttendantPrompt -AudioFilePrompt $OOHAudioFile + +# Then we overwrite the current configuration +$OOHCallFlow.Greetings = @($OOHAudioFilePrompt) +# And we set the auto attendant +Set-CsAutoAttendant -Instance $aa +``` + +### Removing out-of-hours greeting + +To remove the out-of-hours greeting we'll use the following script. + +For [`New-CsAutoAttendantPrompt` cmdlet](https://docs.microsoft.com/en-us/powershell/module/skype/new-csautoattendantprompt?view=skype-ps) we need to specify either a text-to-speech prompt or an audio file. We can set any value as it'll be ignored anyway. + +```powershell +# Find out-of-hours association +$OOHAssociation = $aa.CallHandlingAssociations | + Where-Object {$_.Type.Value -eq 'AfterHours'} + +# Find the respective call flow +$OOHCallFlow = $aa.CallFlows | + Where-Object Id -eq $OOHAssociation.CallFlowId + +# Generate new prompt +$OOHPromptParams = @{ + TextToSpeechPrompt = 'Our offices are closed now!' + ActiveType = 'None' +} +$OOHPromptNone = New-CsAutoAttendantPrompt @OOHPromptParams + +# Replace it +$OOHCallFlow.Greetings = @($OOHPromptNone) + +# And save the changes +Set-CsAutoAttendant -Instance $aa +``` + + + + In theory, we could just set *ActiveType* value of `$OOHCallFlow.Greetings` to *None*. It'd work, but it might be prone to error if Microsoft changes the structure of the call flow object. + + + +## Adding holiday workflow + +## Changing holidays greeting + +## Changing working hours + +## Changing out of hours workflow + +## Adding members in bulk + +## Conclusion \ No newline at end of file