|
0:00:14
|
Ok, so let's take a look at custom scripting now.
|
|
0:00:16
|
And I mentioned that we'll try to figure out why Ben
|
|
0:00:20
|
was chosen first. We will do that as we modify
|
|
0:00:24
|
our script and send more calls in, but let's just
|
|
0:00:26
|
for right now go ahead and get into custom scripting.
|
|
0:00:31
|
So let's log back into our desktop and we're done
|
|
0:00:35
|
with the web admin interface for the time being. We're actually
|
|
0:00:39
|
going to leave it on application configuration settings
|
|
0:00:42
|
so the application, application management
|
|
0:00:44
|
because as we make changes to the script that this uses
|
|
0:00:48
|
and if you'll recall, it uses the script for simple
|
|
0:00:52
|
queuing which we actually uploaded via the web interface
|
|
0:00:56
|
which placed it in the LDAP repository
|
|
0:01:00
|
but we're going to leave it on this application page
|
|
0:01:03
|
because from here, whenever we make a change to the script
|
|
0:01:06
|
that just makes the change to the actual repository.
|
|
0:01:09
|
But the application that's running is just an instance of
|
|
0:01:14
|
the script and this is done, this abstraction
|
|
0:01:17
|
is done so that I can be using the same script
|
|
0:01:20
|
if I have it in a generic enough fashion for multiple
|
|
0:01:24
|
applications. Obviously, I might have different
|
|
0:01:28
|
override values for those different applications. For
|
|
0:01:32
|
instance, this generic queuing doesn't have any
|
|
0:01:35
|
music on hold while they're in queue, so that's not
|
|
0:01:39
|
desirable, but it does -- and I could modify it to
|
|
0:01:43
|
support that and still keep it generic enough
|
|
0:01:46
|
but it also doesn't specify the CS queue and it lets me
|
|
0:01:49
|
override that so I could use this one script for simple queuing
|
|
0:01:53
|
for five different queues that I have, create five different
|
|
0:01:59
|
applications and five different subsystem RMCM queues
|
|
0:02:05
|
and then for each application a different trigger and in each
|
|
0:02:09
|
application tick the override box and place the different queue name.
|
|
0:02:14
|
And that way, I'm using the same script, but every
|
|
0:02:19
|
time I call it for use in an application for use in an
|
|
0:02:23
|
instance, I'm actually copying that into running
|
|
0:02:28
|
memory overriding the default values, but just per my instance
|
|
0:02:34
|
of the script, so every time I make a change to the script
|
|
0:02:36
|
it's for those reasons that we just enumerated that
|
|
0:02:40
|
it's necessary to click refresh.
|
|
0:02:43
|
Now some of these others like the summary of the
|
|
0:02:46
|
application if we want to look at it or copy this to
|
|
0:02:49
|
another application, keep preserving the settings or
|
|
0:02:52
|
delete, that's what those other icons are
|
|
0:02:54
|
but we'll end up using refresh a number of times.
|
|
0:02:57
|
And you can always refresh all applications. Just bear in mind
|
|
0:03:01
|
you typically in a production environment want to only refresh
|
|
0:03:03
|
one at a time simply because it will disconnect callers so
|
|
0:03:08
|
you only want to refresh the one that you're actually working on
|
|
0:03:10
|
in sort of a maintenance mode for that -- at least for that
|
|
0:03:14
|
application. Ok, so we're going to go ahead and minimize
|
|
0:03:19
|
the web page and we're going to open up start
|
|
0:03:23
|
programs
|
|
0:03:27
|
Cisco -- sorry
|
|
0:03:29
|
UCCX admin and the UCCX Editor.
|
|
0:03:37
|
And the reason we need to log in, we could click
|
|
0:03:39
|
log on anonymously is that if we log in
|
|
0:03:43
|
sorry, the user is not admin it is UCCX admin
|
|
0:03:46
|
so our LDAP user and password cisco
|
|
0:03:51
|
is that if we log in, we actually have access to the repository
|
|
0:03:54
|
not just to the local file system.
|
|
0:03:57
|
This not only helps us with prompt management, document
|
|
0:04:01
|
management, script management, grammar management, but also
|
|
0:04:05
|
debugging becomes much easier.
|
|
0:04:08
|
So in the deep dives I go much deeper into this
|
|
0:04:11
|
interface, on the left here we basically have -- and
|
|
0:04:14
|
you should probably be familiar with if you've gone over the deep dives
|
|
0:04:17
|
we basically have the element or step pane, sometimes I
|
|
0:04:22
|
call it a Java bean pane
|
|
0:04:25
|
so we've got four panes, four window panes. Here
|
|
0:04:27
|
we've got the editor pane. This is where we do most of our
|
|
0:04:30
|
visual development. Down here to the bottom left
|
|
0:04:33
|
we have our variable pane where we will create
|
|
0:04:35
|
and edit variables and give them different values and attributes.
|
|
0:04:39
|
It's also where we will watch variables be dynamically populated
|
|
0:04:43
|
with their values as we actually run what's called a reactive debug
|
|
0:04:51
|
to the script and we actually watch a call process through the script
|
|
0:04:57
|
in live real time.
|
|
0:05:00
|
Hopefully in slowed down time, so we can watch it.
|
|
0:05:03
|
And then here down here we have our debugging
|
|
0:05:05
|
and validation pane.
|
|
0:05:08
|
And for any script that we run, we're going to want to
|
|
0:05:11
|
run tools validate which only validate syntax
|
|
0:05:16
|
basically making sure that if we have let's say something like a
|
|
0:05:18
|
go to, go to this part of the script that there's
|
|
0:05:22
|
actually a label there that we can go to.
|
|
0:05:27
|
It validates syntax, it does not validate logic
|
|
0:05:31
|
human logic or why we did a certain programming logic
|
|
0:05:35
|
so that is where we'll use the debug reactive script
|
|
0:05:39
|
in order to debug our own logic and see what
|
|
0:05:43
|
path the call is actually taking in the script versus
|
|
0:05:46
|
what we intended, so let's go open
|
|
0:05:51
|
and again, we can open from our file system, but
|
|
0:05:53
|
let's go up here to script repository
|
|
0:05:57
|
and we're going to choose the default repository and
|
|
0:05:59
|
this is where -- actually, if I select it and then press
|
|
0:06:03
|
open, it works better, but this is where if I didn't
|
|
0:06:05
|
upload a script to begin with
|
|
0:06:08
|
then I might not even see default
|
|
0:06:10
|
because it hadn't created that repository.
|
|
0:06:13
|
And in here we see the script we uploaded which is
|
|
0:06:17
|
simple queuing.
|
|
0:06:20
|
Ok,
|
|
0:06:22
|
so we see it open, we see an accept
|
|
0:06:25
|
first of all, we start and end a script.
|
|
0:06:27
|
We see accept, we see play prompt
|
|
0:06:31
|
select resource, this is the actual ICD or ACD
|
|
0:06:35
|
the actual queuing mechanism.
|
|
0:06:38
|
And if we open it up, we have two output branches.
|
|
0:06:41
|
One is for connected and one is for queued.
|
|
0:06:43
|
If we expand the queued, we have output branches for a
|
|
0:06:47
|
label for queue loop
|
|
0:06:50
|
to play a prompt. Delay for the variable
|
|
0:06:54
|
delay while queued which is an int type or an integer
|
|
0:06:58
|
Java integer, the value is 30
|
|
0:07:00
|
but because it's a parameter, the attribute of parameter
|
|
0:07:03
|
I can double click to open that.
|
|
0:07:06
|
Because it has the tick box of parameter, that's
|
|
0:07:10
|
where it was visible
|
|
0:07:15
|
here
|
|
0:07:16
|
and for the instance that we used, we overrid it
|
|
0:07:19
|
or overrode it
|
|
0:07:22
|
as a value.
|
|
0:07:28
|
Ok, so parameter is what makes it show up here
|
|
0:07:32
|
and makes it able to be overridden.
|
|
0:07:35
|
We have four parameters.
|
|
0:07:37
|
CS queue, delay while queued, welcome prompt and queue prompt.
|
|
0:07:41
|
If I take a look back at the editor, here are my four.
|
|
0:07:45
|
CS queue with a empty default value
|
|
0:07:48
|
and it's a string.
|
|
0:07:50
|
The integer of delay while queued.
|
|
0:07:52
|
Queue prompt which has SP
|
|
0:07:56
|
as a default value is system prompt.
|
|
0:07:59
|
Then it has a -- and this is the format
|
|
0:08:01
|
either P for Prompt and if it's P for Prompt
|
|
0:08:05
|
it either has to be in the file system
|
|
0:08:09
|
under user prompt, but again, we don't ever want to
|
|
0:08:13
|
use the file system, it should be in the repository.
|
|
0:08:17
|
It will actually look in both places.
|
|
0:08:21
|
SP is for system prompt, then we have a left bracket
|
|
0:08:26
|
then we have the directory ICD
|
|
0:08:29
|
backslash and then the actual name of the file
|
|
0:08:33
|
ICD queue.wav
|
|
0:08:36
|
and then a right bracket and that's the format is
|
|
0:08:41
|
P or SP left right bracket
|
|
0:08:43
|
and the name of the file with a relative path.
|
|
0:08:47
|
So relative to whatever the default directory is.
|
|
0:08:51
|
And there's a separate default directory for
|
|
0:08:53
|
system prompt of course then there is for prompt.
|
|
0:08:56
|
And even if we're looking at prompts
|
|
0:09:02
|
that have been uploaded into the LDAP, the repository
|
|
0:09:07
|
first of all, we know that EN US is the default. Why?
|
|
0:09:10
|
Because back in system service parameters, we saw that
|
|
0:09:13
|
that was the default language. We can also just go to default
|
|
0:09:17
|
which will essentially take us the same place as here.
|
|
0:09:22
|
But we do have the ability to create new folders.
|
|
0:09:25
|
So if I was creating a prompt and I wanted that
|
|
0:09:28
|
to be a P for prompt
|
|
0:09:31
|
and I wanted it to be in a subfolder because I have
|
|
0:09:33
|
maybe 15 or 150 let's say prompts
|
|
0:09:38
|
and I want to keep them organized, then I would -- if I created a new folder
|
|
0:09:43
|
and placed the prompt there
|
|
0:09:47
|
then I would reference this as the base directory
|
|
0:09:52
|
so I would reference beginning here
|
|
0:09:56
|
folder name\folder name\folder name\file
|
|
0:10:01
|
or however many folders deep I have.
|
|
0:10:03
|
Also, from prompt management
|
|
0:10:06
|
I can upload individual prompts at a time
|
|
0:10:11
|
or if I -- oops that's not what I meant to check.
|
|
0:10:14
|
If I go back
|
|
0:10:17
|
to the root you actually have the ability to upload
|
|
0:10:20
|
zip files, but only from the root.
|
|
0:10:22
|
So what you do to upload zip files is you create all
|
|
0:10:26
|
your prompts and you create them with the proper
|
|
0:10:29
|
folder structure. They'll actually create the folder structure if
|
|
0:10:33
|
it's not already there and you just make sure that they have
|
|
0:10:36
|
EN US as the base folder so that it drops it in here
|
|
0:10:40
|
creates the folders and places the prompts in there.
|
|
0:10:44
|
Prompts that you'll be creating in the lab.
|
|
0:10:46
|
Remember yesterday we looked at Unity Connection
|
|
0:10:49
|
we could have used Unity Express and we looked at
|
|
0:10:53
|
the tool for recording an audio processing.
|
|
0:10:56
|
I would simply from my candidate desktop
|
|
0:10:59
|
where I will be able to browse to my individual
|
|
0:11:05
|
servers. I would go to Unity Connection or Unity Express
|
|
0:11:10
|
grab any sort of greeting, prompt, user or system call
|
|
0:11:17
|
handler, name, recorded name any of those recording Java applets
|
|
0:11:23
|
and I would press record regardless of whether I actually
|
|
0:11:27
|
wanted to use that for that particular user
|
|
0:11:29
|
or system call handler, record the prompt because it
|
|
0:11:32
|
will record it in the proper format which is CCIT ulaw
|
|
0:11:38
|
G.711 8 kilohertz, 8 bit mono
|
|
0:11:43
|
and it has to be in that specifically, but it will do that
|
|
0:11:47
|
automatically. I've got a decent high quality mic
|
|
0:11:49
|
it's called a handset. It'll call the phone, I'll
|
|
0:11:52
|
record it, I won't press save for that page, instead I will
|
|
0:11:58
|
stop recording when I'm done and then I will choose save
|
|
0:12:04
|
to local file. I'll save it to my candidate workstation
|
|
0:12:07
|
I'll come over here to a different window which is my
|
|
0:12:10
|
UCCX administration application prompt management
|
|
0:12:13
|
go to my default language so directory, upload new prompt
|
|
0:12:19
|
browse, upload the prompt from my desktop where
|
|
0:12:23
|
I probably will have saved it, click upload of course I haven't entered
|
|
0:12:27
|
one right here, and the prompt will be available
|
|
0:12:31
|
and it will be available for all of my applications as well.
|
|
0:12:35
|
If I actually go back to my application here
|
|
0:12:39
|
and I choose to override
|
|
0:12:41
|
this actually let's me select from -- and you know what here
|
|
0:12:44
|
I'll just give you an example. Let's go back to prompt management.
|
|
0:12:48
|
Let's go into EN US
|
|
0:12:51
|
Let's upload a new prompt -- actually you know what let's
|
|
0:12:54
|
create a directory called widget widgets
|
|
0:13:04
|
folder successfully created.
|
|
0:13:07
|
Now let's drop down into this directory and upload a new
|
|
0:13:10
|
prompt here.
|
|
0:13:11
|
Browse
|
|
0:13:14
|
I'm already in program files WF avid scripts, I'm going to
|
|
0:13:18
|
to go back to WF avid
|
|
0:13:19
|
and go back to prompts
|
|
0:13:22
|
where I have some default. I don't have any default user ones.
|
|
0:13:27
|
There's the directory structure actually that it creates.
|
|
0:13:33
|
But I have some system ones
|
|
0:13:35
|
G.711 because I'm not using G.729 as the codec
|
|
0:13:39
|
if I had switched it in service parameters, then
|
|
0:13:41
|
I would record those in the G.729 codec
|
|
0:13:48
|
and I would go and -- which incidentally if
|
|
0:13:52
|
I needed to record them in Unity Connection as G.729
|
|
0:13:55
|
in service parameters over there, I would switch the default
|
|
0:13:57
|
not -- it doesn't have to do with the codec that was used to
|
|
0:14:01
|
connect to Unity Connection because we mentioned it does software
|
|
0:14:04
|
transoding, but it has to do with the codec that is selected
|
|
0:14:10
|
in service parameters to store messages in and I
|
|
0:14:13
|
could change it to G.729 over there if I was instructed
|
|
0:14:16
|
to use G.729 only as the codec for here and I needed
|
|
0:14:20
|
to record a message in the proper codec.
|
|
0:14:23
|
Ok, so you do have the tools and I'll go into maybe
|
|
0:14:26
|
EN US and so earlier we just saw that SP Service Prompt
|
|
0:14:39
|
or sorry System Prompt ICD\ it's kind of small there, but
|
|
0:14:43
|
ICD\ directory
|
|
0:14:46
|
so that's here
|
|
0:14:50
|
where we were in System the codec and then the
|
|
0:14:57
|
language which is now the default directory
|
|
0:14:59
|
and ICD and I think it was ICD welcome or
|
|
0:15:02
|
ICD welcome to, so that's actually where it
|
|
0:15:05
|
found those and I would use whatever it was that I'm
|
|
0:15:09
|
wanting to use. Let's say welcome, let's upload welcome.
|
|
0:15:18
|
Return to prompt management.
|
|
0:15:20
|
I see that prompt here. Now if I go back to applications
|
|
0:15:24
|
and there's a reason I'm taking a tangent to do that
|
|
0:15:27
|
before we go into custom editing because I want to show you a way
|
|
0:15:30
|
to access that from the UCCX visual editor as well.
|
|
0:15:34
|
Now if I override a prompt, I can actually choose that
|
|
0:15:38
|
prompt and it automatically has all of the prompts
|
|
0:15:43
|
of course if you have a large number of them, then
|
|
0:15:45
|
this becomes quite cumbersome and you actually do want to
|
|
0:15:48
|
key them in. In future versions of UCCX, you actually have a filter
|
|
0:15:52
|
where you can select subsections if I had maybe a thousand prompts
|
|
0:15:55
|
which actually isn't that uncommon for large call centers
|
|
0:15:58
|
but I have the directory widgets welcome. It's already
|
|
0:16:02
|
in the proper format and I don't have to key it in properly
|
|
0:16:04
|
or I don't have to key it in manually
|
|
0:16:07
|
although I can if I so desire
|
|
0:16:10
|
click edit
|
|
0:16:13
|
and actually change this name, but I need to be
|
|
0:16:16
|
careful and sure that I want to
|
|
0:16:18
|
and I can actually even listen to that -- of course I don't have a
|
|
0:16:22
|
medial player installed or a sound card, but I can even
|
|
0:16:25
|
listen to that prompt to make sure it's the right prompt for me.
|
|
0:16:29
|
Ok, so back in UCCX
|
|
0:16:33
|
here we have a prompt. Let's say we want this to be
|
|
0:16:36
|
something other -- let's scroll this over, so we can
|
|
0:16:40
|
see more of the information.
|
|
0:16:42
|
Let's say I want this to be something other than ICD welcome
|
|
0:16:46
|
let's go into properties. We can always right click on a
|
|
0:16:49
|
step or element and click properties. Down the left we have
|
|
0:16:54
|
three tabs that are almost always there. Comments or
|
|
0:16:57
|
annotations about the task or step that you're doing
|
|
0:17:01
|
and an example of an annotation is this right here.
|
|
0:17:06
|
It's the start step, but the annotation says simple queuing
|
|
0:17:10
|
it puts it in /* simple queuing template,
|
|
0:17:14
|
simple queuing template */ to indicate it's a comment.
|
|
0:17:17
|
I also for almost every step have a label.
|
|
0:17:22
|
The reason I would use a label
|
|
0:17:24
|
as we were down here in queue loop, we had a standalone
|
|
0:17:26
|
label, so it doesn't have the anything other than label
|
|
0:17:31
|
itself because that's the whole properties of that
|
|
0:17:34
|
step, but the reason we have a label
|
|
0:17:36
|
is that we played a prompt, we delayed for 45 and then we
|
|
0:17:40
|
had a go to. We go to a label, that's what actually
|
|
0:17:44
|
forms this loop.
|
|
0:17:46
|
It's not the words, but it's actually the go to
|
|
0:17:51
|
and go back to the top, so you need to be careful
|
|
0:17:53
|
that you places things in the proper order. By the way,
|
|
0:17:58
|
UCCX unless there's a go to that redirects
|
|
0:18:03
|
then the -- unless there's a go to that redirects
|
|
0:18:09
|
the script processes top-down by default.
|
|
0:18:13
|
So if I accidentally had this here
|
|
0:18:15
|
maybe I accidentally moved it, it's going to delay for 45
|
|
0:18:19
|
seconds, go to the loop and it will bypass the prompt.
|
|
0:18:23
|
This will never get played.
|
|
0:18:25
|
Any time I drag a step on top of another step
|
|
0:18:29
|
it will automatically be placed below that step, so if I drag
|
|
0:18:33
|
this on play prompt, this play prompt will be dragged
|
|
0:18:37
|
or dropped below play prompt.
|
|
0:18:40
|
The queue prompt was dropped below the welcome prompt.
|
|
0:18:43
|
Ok, we'll just put that back.
|
|
0:18:47
|
But the reason that I can have if I right click
|
|
0:18:50
|
let's go back to the one we were looking at, a label
|
|
0:18:53
|
is that instead of having a separate step called a label
|
|
0:18:58
|
for every time I want to go somewhere, I can actually
|
|
0:19:01
|
reference that I want to go to a particular step that already
|
|
0:19:05
|
exists because it also contains a label
|
|
0:19:09
|
and then the top tab on the left has most of the properties
|
|
0:19:13
|
and then there are tabs on the right which -- or at the
|
|
0:19:16
|
top I guess of this top tab that have the individual
|
|
0:19:23
|
properties or groupings of properties for this
|
|
0:19:26
|
particular step. This step is a prompt or a play prompt
|
|
0:19:31
|
to be more specific because there are other types of
|
|
0:19:33
|
prompt steps in terms of container prompts or
|
|
0:19:38
|
creating auto generated prompts for text to speech
|
|
0:19:42
|
things like that.
|
|
0:19:45
|
There's a lot of information about the steps
|
|
0:19:48
|
whether a prompt is interruptible or not if I press no, someone can press
|
|
0:19:52
|
DTMF digits all day and if my prompt is two minutes long
|
|
0:19:55
|
they have to listen to all two minutes. If interruptible is
|
|
0:19:58
|
yes which it is by default, they press a DTMF digit
|
|
0:20:01
|
it skips the two-minute prompt, the actual audio recording, and it
|
|
0:20:06
|
goes to whatever next step there is.
|
|
0:20:13
|
We also have input buffers. This is for DTMF, so if a user has
|
|
0:20:17
|
input something, when we get to this particular step
|
|
0:20:21
|
do we want to flush or get rid of anything the user might
|
|
0:20:24
|
have done because we're maybe playing them a prompt
|
|
0:20:27
|
in this case, it's just a play prompt. Later we might
|
|
0:20:30
|
look at something under media like get digit string where we want to
|
|
0:20:34
|
actually get digits from a user and if I right click on that
|
|
0:20:37
|
before I get digits, I may want to flush the input buffer.
|
|
0:20:42
|
Why? Because I'm asking the user for their account
|
|
0:20:46
|
number and -- it's a new step we've changed the script
|
|
0:20:51
|
recently and we've got a lot of power users that call into our
|
|
0:20:54
|
call center and they're used to pressing two
|
|
0:20:57
|
option 2, option 3, option 6 to get where they want to go
|
|
0:21:01
|
but now, that would be taken because we've changed it
|
|
0:21:04
|
that would be taking as the actual DTMF for the get digit
|
|
0:21:08
|
string, the string that we want to store their DTMF
|
|
0:21:11
|
digits for their account number. So instead, I flush input buffer
|
|
0:21:17
|
and then I tell them things like filter, how long of a
|
|
0:21:22
|
string of digits am I looking for, which digits are you allowed
|
|
0:21:26
|
to press, is there a terminating digit, let's say none, so
|
|
0:21:31
|
typically it's good practice to any time I'm getting a digit
|
|
0:21:35
|
string, I need to play a prompt to tell the user to input the
|
|
0:21:39
|
actual string, but I might play them a prompt saying
|
|
0:21:42
|
please enter your ten-digit account number followed by
|
|
0:21:45
|
the hash sign or pound sign depending on where you're at
|
|
0:21:48
|
what you call it or I could have no terminating digit and
|
|
0:21:51
|
then I would just say, 'Please enter your ten-digit account number.'
|
|
0:21:55
|
Ok, the problem is most people are accustomed to pressing hash at the end.
|
|
0:21:59
|
Whatever, whatever your lab tells you, whatever your
|
|
0:22:01
|
customers tell you.
|
|
0:22:05
|
Ok, so here we're playing a prompt.
|
|
0:22:11
|
On the prompt tab, we can either as we have here
|
|
0:22:15
|
call a variable or we could go to ellipsis, the dot, dot, dot
|
|
0:22:21
|
and down here we've got all the different Java types
|
|
0:22:24
|
actually four of these are not Java types, they're
|
|
0:22:26
|
specific to UCCX and they're very easily identifiable
|
|
0:22:30
|
visually. They're the ones with colored icons.
|
|
0:22:32
|
Document, prompt, grammar
|
|
0:22:35
|
and script and they change what we have available here.
|
|
0:22:39
|
If I go to prompt and I say browse prompts
|
|
0:22:43
|
first of all,
|
|
0:22:45
|
I probably want to get rid of this information
|
|
0:22:47
|
because it's going to fill in information there.
|
|
0:22:50
|
I say browse prompts, I go to the prompt repository
|
|
0:22:54
|
go to the English US
|
|
0:22:57
|
the widget subfolder and I see the welcome.wav
|
|
0:23:01
|
and it automatically fills in what I need
|
|
0:23:06
|
for playing welcome.wav in the widget subfolder.
|
|
0:23:09
|
Again, I could have done that from the actual
|
|
0:23:13
|
application admin interface as a parameter if I was calling a
|
|
0:23:19
|
variable. In this case, maybe I don't want to because maybe
|
|
0:23:24
|
I have a lot of variables or a lot of prompts and it's just
|
|
0:23:28
|
going to show too many on that screen or whatever,
|
|
0:23:30
|
whatever my reason might be, but this will work just fine.
|
|
0:23:35
|
Ok, so now it's not relying on a variable.
|
|
0:23:38
|
It doesn't matter that ICD welcome.wav is here, we could
|
|
0:23:40
|
get rid of it because I'm specifying that user prompt.
|
|
0:23:46
|
Are there any questions as we're going along so far?
|
|
0:23:51
|
So now we're just going to take a look at some examples
|
|
0:23:53
|
of something that might be asked of you, so let's
|
|
0:23:56
|
get rid of this
|
|
0:23:58
|
and let's say that you're asked to do something
|
|
0:24:02
|
like play that welcome prompt
|
|
0:24:05
|
but let's say you're instructed to test to see if any agents
|
|
0:24:12
|
are logged in before ever sending any calls into
|
|
0:24:22
|
even see if a select resource is available which if we happened
|
|
0:24:27
|
to know -- if we're able to ascertain before sending
|
|
0:24:31
|
them to the select resource that there are no agents available
|
|
0:24:34
|
then we would know that they're going to go into the queued.
|
|
0:24:38
|
Actually, just because it's super simple, let's make sure that
|
|
0:24:40
|
these guys in queue here music on hold.
|
|
0:24:44
|
Let's go to -- is it under media? No.
|
|
0:24:46
|
It's under general.
|
|
0:24:50
|
And let's do -- nope
|
|
0:24:52
|
sorry, call contact
|
|
0:24:54
|
let's do call hold right after the prompt
|
|
0:24:58
|
and take them off hold after the delay, so
|
|
0:25:02
|
now if music on hold is delivered -- is configured
|
|
0:25:06
|
for those CTI ports which it is
|
|
0:25:09
|
based on the device pool and the MRGL and the user
|
|
0:25:12
|
this user hold by the way, this is not network hold.
|
|
0:25:15
|
When we go to transfer the call to the agent, that's
|
|
0:25:18
|
network hold, but this is user hold. Anyhow,
|
|
0:25:24
|
we're placing the call on hold for 45 seconds and then
|
|
0:25:28
|
unholding. Music on hold will be played.
|
|
0:25:32
|
Ok, so we took care of that real quick.
|
|
0:25:34
|
But now we want to make sure that they don't get to
|
|
0:25:36
|
the queued output branch, they're not in an infinite loop
|
|
0:25:41
|
unless there are actually agents logged in, in the first place.
|
|
0:25:45
|
If there are not agents logged in, then we wish to play them
|
|
0:25:49
|
a message saying, 'No agents are available at this time.'
|
|
0:25:55
|
'We're sorry for the inconvenience. Please wait while we forward you to
|
|
0:25:58
|
voice mail.'
|
|
0:25:59
|
It might upset the caller, but at least they won't wait
|
|
0:26:02
|
infinitely in queue with false hopes.
|
|
0:26:05
|
So what we're going to do for that is ACD
|
|
0:26:09
|
and get reporting statistic.
|
|
0:26:14
|
Now there are two types of reporting. There's historical
|
|
0:26:16
|
reporting where we look back on the previous day and before
|
|
0:26:20
|
and see how our call center's been operating and then there's
|
|
0:26:24
|
real time reporting.
|
|
0:26:26
|
This is part of the real time reporting engine
|
|
0:26:30
|
So we're going to get reporting statistic
|
|
0:26:36
|
based on the CS queue.
|
|
0:26:41
|
The field from the CS queue we want to know is the
|
|
0:26:44
|
logged in resources and which CS queue?
|
|
0:26:48
|
Well, it's going to be the one that is the variable
|
|
0:26:51
|
which will be overridden by the parameter and
|
|
0:26:54
|
therefore populated with whatever CS queue we have
|
|
0:26:57
|
and we're going to store the number of logged in
|
|
0:27:00
|
resources in this field. We can always mouse over a field
|
|
0:27:05
|
and it will show us what type -- what Java type of variable
|
|
0:27:10
|
or value can be placed here.
|
|
0:27:13
|
In this case, if we scroll or mouse over, it says,
|
|
0:27:18
|
'Choose a integer, int, non-final variable...'
|
|
0:27:21
|
and it goes away quickly, so we have to mouse over again.
|
|
0:27:24
|
'... class attribute or array element -- element.'
|
|
0:27:27
|
And we can also just click this down and see
|
|
0:27:30
|
there's only one available and if we looked down at the
|
|
0:27:33
|
existing variables, we see that that is delay while queued
|
|
0:27:36
|
it's the type Java type int or integer, so because I don't
|
|
0:27:41
|
want to fill this in again, I'm just going to go ahead and
|
|
0:27:43
|
choose that so that it will allow me to hit ok without
|
|
0:27:47
|
saying there's a problem.
|
|
0:27:49
|
I'm going to come back and change it. I don't really want it
|
|
0:27:52
|
stored there.
|
|
0:27:55
|
If I did store it there, it would just override that
|
|
0:27:57
|
value, but then the problem is the delay while queued would
|
|
0:28:01
|
then also be overridden once I got there.
|
|
0:28:04
|
So to start out the script because it had been overridden
|
|
0:28:06
|
by the parameter in the application interface it's
|
|
0:28:10
|
45, here we store the number of logged in
|
|
0:28:14
|
resource maybe there's one that overrides the value of 45
|
|
0:28:20
|
which had already overridden 30, we get to call hold if
|
|
0:28:23
|
we ever got there because -- well, we would get there because
|
|
0:28:26
|
there was an agent logged in, but they're not ready maybe
|
|
0:28:29
|
call hold we delay for the value of the overridden
|
|
0:28:33
|
value of one, so obviously that's not a good idea.
|
|
0:28:36
|
So I'm going to go ahead and create a new variable.
|
|
0:28:38
|
The type is an integer, the name is number
|
|
0:28:46
|
of agents logged in currently.
|
|
0:28:57
|
Call it whatever we want.
|
|
0:28:59
|
Most people in UCCX programming have the first word with a lowercase
|
|
0:29:06
|
and all the rest with uppercase. It said it had to be non-final
|
|
0:29:10
|
we won't even talk about that. Array just means we can have
|
|
0:29:13
|
multiple values in array in however many dimensions
|
|
0:29:17
|
we're not going to talk about that.
|
|
0:29:19
|
Parameter, we don't want this to be overridden. This
|
|
0:29:21
|
is a dynamically populated value. We'll say ok,
|
|
0:29:25
|
we'll go back to delay while queued, go to properties
|
|
0:29:29
|
choose the resulting or change the resulting statistic
|
|
0:29:32
|
to populate for this CS queue, populate the number of logged in resources
|
|
0:29:39
|
in this variable, so we should see this variable here dynamically
|
|
0:29:45
|
filled in as we run a live call against this reactive debug.
|
|
0:29:55
|
So now we -- the script has a variable that contains the
|
|
0:29:58
|
amount of logged in resources but we haven't acted on that information.
|
|
0:30:01
|
We've just gathered the information. Now it's up to us
|
|
0:30:04
|
to act on that information. In order to do so, we use
|
|
0:30:09
|
a -- we use a logical if
|
|
0:30:14
|
we basically want to say if something happens, then
|
|
0:30:22
|
do something else or then do something, else do something else.
|
|
0:30:26
|
So this 'if' statement, this comparison, will always evaluate
|
|
0:30:34
|
to an output -- branch of Boolean True or Boolean False.
|
|
0:30:37
|
That is to say the statement will either be true, yes that
|
|
0:30:43
|
was accurate, the if statement was -- the comparison was accurate
|
|
0:30:46
|
or no, it wasn't. We have to write the logic, so we'll
|
|
0:30:49
|
right click and do properties and we almost never want to use
|
|
0:30:53
|
the drop-down because that's just true and false. We want to use the
|
|
0:30:55
|
ellipsis, choose our variable so we want to say agent
|
|
0:31:00
|
number of agents logged in currently and this is Boolean logic, so
|
|
0:31:04
|
I have to if I want to do equals, it's actually equal equal
|
|
0:31:07
|
otherwise, it would be something like greater than or equal or
|
|
0:31:11
|
less than or equal or even not equal to.
|
|
0:31:16
|
Ok,
|
|
0:31:18
|
we could say if the number of agents is not equal to zero
|
|
0:31:23
|
now any time I'm putting in a number, I need to think about
|
|
0:31:26
|
what that number is and I kind of need to think about
|
|
0:31:28
|
what type of variable this is.
|
|
0:31:31
|
In this case, we know this variable's an integer.
|
|
0:31:33
|
So the number does not go inside double quotes.
|
|
0:31:38
|
If I'm dealing with a phone number that is always
|
|
0:31:42
|
a string. Think about how you see a phone number
|
|
0:31:48
|
206 -- not only how you see it, but how you say it
|
|
0:31:51
|
2065015111, you never say let's see
|
|
0:31:57
|
5111, so that would be five
|
|
0:32:00
|
you never say 2 billion 65 thousand -- whatever
|
|
0:32:15
|
one hundred and eleven or whatever.
|
|
0:32:18
|
It's probably even more than that, you never say that
|
|
0:32:20
|
that would be an integer
|
|
0:32:21
|
counting incrementally, but it's actually a string
|
|
0:32:24
|
so phone numbers are a string. In this case, this is an integer
|
|
0:32:27
|
so we don't put double quotes. Anything that's a phone number
|
|
0:32:30
|
or a string, we do put double quotes.
|
|
0:32:33
|
I say ok, I can say apply or just ok. So if the number of
|
|
0:32:38
|
agents is not equal to zero, if that's true
|
|
0:32:42
|
then that means we have agents available.
|
|
0:32:44
|
Not equal to zero, sort of a double negative.
|
|
0:32:49
|
So if that's true, then we have agents available.
|
|
0:32:52
|
If it's false, then we have no agents available.
|
|
0:33:03
|
Ok, if we wrote this another way and said
|
|
0:33:05
|
number of agents currently logged in is equal to zero
|
|
0:33:08
|
then true means we have no agents and false means we
|
|
0:33:12
|
don't or have no agents or we do have agents available,
|
|
0:33:15
|
so whichever way you want to write the logic is up to you.
|
|
0:33:19
|
Ok, so now we need to do something with that. We've
|
|
0:33:21
|
evaluated this information that we've gathered. We've
|
|
0:33:25
|
gathered it, now we've evaluated it, but now we
|
|
0:33:28
|
need to do something with it, so at this point, if we do nothing
|
|
0:33:33
|
both of them whichever output branch it takes
|
|
0:33:36
|
it simply continues down to select resource.
|
|
0:33:39
|
We want to -- let's just do a simple redirect
|
|
0:33:44
|
and say call contact redirect
|
|
0:33:48
|
if it's true that no -- that the number of agents
|
|
0:33:54
|
currently logged in is not equal to zero, then
|
|
0:33:58
|
agents are available and we wanted to go to the
|
|
0:34:01
|
select resource, so let's go here to the select resource
|
|
0:34:04
|
go to properties, go to the label and say ACD.
|
|
0:34:12
|
Ok,
|
|
0:34:14
|
giving it a label of ACD,
|
|
0:34:17
|
Now we want to come up here to the general
|
|
0:34:19
|
grab a go to
|
|
0:34:22
|
drop it on the true output branch
|
|
0:34:24
|
say properties and if it's true that the number of agents
|
|
0:34:29
|
logged in is not equal to zero, then we want to go to
|
|
0:34:34
|
the ACD.
|
|
0:34:36
|
If it's false, we want to redirect them where?
|
|
0:34:41
|
We want to redirect them to the destination of I don't know
|
|
0:34:45
|
let's see
|
|
0:34:47
|
What was our voice mail pilot?
|
|
0:35:02
|
Our voice mail pilot was 1850
|
|
0:35:08
|
so we want to redirect them to 1850
|
|
0:35:12
|
Does this work? Nope.
|
|
0:35:14
|
It's unable to parse the expression because
|
|
0:35:18
|
it's an unassignable type
|
|
0:35:20
|
the type was integer, but it was expecting a string.
|
|
0:35:23
|
If you just read the error and I know in the lab you
|
|
0:35:26
|
can be pressed for time and kind of a little bit stressed
|
|
0:35:29
|
out, so you might not take the time to read the error
|
|
0:35:32
|
but try to slow yourself down and read the error
|
|
0:35:34
|
it tells you right what it is. You gave it an integer
|
|
0:35:37
|
it's expecting a string. What does that mean?
|
|
0:35:40
|
Put double quotes around it.
|
|
0:35:44
|
Now hit apply.
|
|
0:35:46
|
Now it took no problem.
|
|
0:35:48
|
Now called address.
|
|
0:35:51
|
We can actually change the called address. We can
|
|
0:35:53
|
preserve the called address. What was the original called?
|
|
0:35:57
|
The DID for this application was -- what was it? 1990?
|
|
0:36:05
|
So if we preserve it, 1990
|
|
0:36:08
|
was the called address which means it will become the redirecting
|
|
0:36:13
|
called. As it leaves through this call redirect, what was called
|
|
0:36:19
|
what the user dialed becomes redirect called or rdnis.
|
|
0:36:23
|
What does that mean? Unity Connection because
|
|
0:36:26
|
we're sending the call to Unity Connection as the
|
|
0:36:28
|
new dnis, it will take our existing redirecting number
|
|
0:36:35
|
our called number becoming redirecting and it will try to
|
|
0:36:39
|
find a mailbox for 1990
|
|
0:36:41
|
If we have either a system call handler or anything in the
|
|
0:36:46
|
system actually that has the extension or DTMF
|
|
0:36:49
|
access ID of 1990, that's where it will send it.
|
|
0:36:53
|
If not, we might want it to send it somewhere
|
|
0:36:57
|
specific. I don't know we had that 555 system call handler.
|
|
0:37:02
|
That's not necessarily where I want to hand it, but let's just
|
|
0:37:06
|
say I want to.
|
|
0:37:07
|
I could actually put in here
|
|
0:37:14
|
reset to 555 in double quotes.
|
|
0:37:16
|
So what does that do? That resets the called address
|
|
0:37:19
|
it changes it from what it was which was 1990
|
|
0:37:23
|
it basically spoofs it to 555 and that becomes
|
|
0:37:27
|
the redirect number.
|
|
0:37:30
|
So we'll leave it there and if that works, then
|
|
0:37:32
|
we should get, what was it? One of the prosumer or professional
|
|
0:37:36
|
support. I don't remember if it was for widgets or wodgets
|
|
0:37:39
|
but professional widgets or professional wodgets support.
|
|
0:37:43
|
So we'll test and see if that works.
|
|
0:37:47
|
And then we have output branches was the call redirect
|
|
0:37:50
|
successful, busy, invalid, unsuccessful.
|
|
0:37:52
|
By the way, if we -- let's say the call redirect was successful
|
|
0:37:57
|
the RTP stream is gone, it's been redirected to 1850
|
|
0:38:02
|
however, the script continues to process
|
|
0:38:08
|
until it's done and by default, it just goes top down.
|
|
0:38:12
|
So we might very well do something
|
|
0:38:16
|
whoops
|
|
0:38:17
|
like go to end, so we might come down to this end
|
|
0:38:22
|
give it a label called this
|
|
0:38:26
|
is the end.
|
|
0:38:30
|
Little reference to Jim Morrison and then go to end.
|
|
0:38:40
|
And we could copy that to -- you can copy inside
|
|
0:38:43
|
UCCX, so copy that to busy, invalid, unsuccessful whatever.
|
|
0:38:47
|
Probably wouldn't want to do that in production environment
|
|
0:38:50
|
but fine for the lab, really we want it to be successful in
|
|
0:38:54
|
the lab. We want to be successful and therefore attain our number.
|
|
0:39:02
|
But I might also do something else. I might also do something
|
|
0:39:05
|
before I send it to the end like I might do something let's
|
|
0:39:10
|
say such as grab an e-mail contact, create an e-mail.
|
|
0:39:18
|
The subject being a string double quote say
|
|
0:39:23
|
so sorry -- so sorry that we had to disconnect you
|
|
0:39:28
|
basically. Body,
|
|
0:39:31
|
we are really sorry
|
|
0:39:38
|
and who the e-mail contact is.
|
|
0:39:44
|
user@domain.com
|
|
0:39:49
|
User, all this information would probably have been
|
|
0:39:52
|
gotten by a database, so if we actually received
|
|
0:39:54
|
a call, look up their calling party or their account number
|
|
0:39:57
|
based on digits they gave us, do a database dip,
|
|
0:40:00
|
grab their e-mail address, store it in a variable
|
|
0:40:03
|
what type of a variable? Mouse over, it says a
|
|
0:40:06
|
contact variable, so we would have created a
|
|
0:40:10
|
value or a variable of the type contact. We would have
|
|
0:40:15
|
stored their e-mail address there.
|
|
0:40:19
|
Oh, it's actually expecting a contact variable, not a
|
|
0:40:27
|
not an actual e-mail address, so we would have stored it
|
|
0:40:29
|
in the contact variable. We would have created one.
|
|
0:40:39
|
And I don't remember the exact format for the contact
|
|
0:40:48
|
that's fine. We would -- basically we would create
|
|
0:40:51
|
the contact variable, we would then create the e-mail
|
|
0:40:56
|
and then we would send the e-mail
|
|
0:41:01
|
and actually...
|
|
0:41:04
|
Oh, sorry
|
|
0:41:08
|
so let's create the type of contact.
|
|
0:41:15
|
Name, e-mail
|
|
0:41:19
|
create the e-mail
|
|
0:41:22
|
sorry, really sorry
|
|
0:41:27
|
that we had to hang up on you, the contact
|
|
0:41:30
|
is the e-mail contact
|
|
0:41:33
|
and then we grab that e-mail contact
|
|
0:41:36
|
that we just created and here's where we actually
|
|
0:41:39
|
send it to the user at the domain.com
|
|
0:41:44
|
and of course if we mouse over, we could have a variable
|
|
0:41:47
|
that was a string. We could have gotten that information
|
|
0:41:49
|
from a database and populated the variable earlier and then
|
|
0:41:54
|
e-mailed them based on the variable.
|
|
0:41:55
|
Who is it from? Us.
|
|
0:41:58
|
It's from the CS queue whatever.
|
|
0:42:03
|
And send it immediately, don't queue it.
|
|
0:42:04
|
So right before it's successful
|
|
0:42:08
|
in -- right before it's successful in
|
|
0:42:15
|
redirecting them or actually after it's redirected their audio
|
|
0:42:18
|
we create an e-mail, send it to them apologizing and then
|
|
0:42:22
|
we go to the end of the script.
|
|
0:42:23
|
So that's something we could do.
|
|
0:42:26
|
If there are agents available, then we go to the ACD.
|
|
0:42:32
|
Let's just test our syntax so far. It looks like our syntax is ok.
|
|
0:42:38
|
Our logic may not work, but at least our syntax does.
|
|
0:42:42
|
Now while we're in queue, let's do something like try to
|
|
0:42:46
|
figure out how many calls are in queue
|
|
0:42:52
|
and tell the agent or sorry, tell the calling party, not
|
|
0:42:55
|
necessarily the smartest thing in production networks, just depends on
|
|
0:42:58
|
how busy or deep your queues get, but tell the
|
|
0:43:02
|
calling party, in this instance, how many -- what their position
|
|
0:43:06
|
in queue is, so we're going to get more real time data.
|
|
0:43:11
|
We're going to get a real time reporting
|
|
0:43:14
|
oops
|
|
0:43:17
|
why isn't it letting me drag?
|
|
0:43:22
|
Do I have another window open?
|
|
0:43:25
|
Nope.
|
|
0:43:27
|
Let's just save this.
|
|
0:43:32
|
Ok, let's try to drag anything.
|
|
0:43:36
|
It's not letting me drag anything.
|
|
0:43:40
|
Let me shut this down.
|
|
0:43:42
|
Open it back up.
|
|
0:43:56
|
Open the script from the repository.
|
|
0:44:04
|
Ha! It didn't save that either -- Oh, yeah it did. Sorry.
|
|
0:44:08
|
Yeah, there we go.
|
|
0:44:09
|
False, call redirect
|
|
0:44:12
|
successful, e-mail, send it, great.
|
|
0:44:15
|
Ok,
|
|
0:44:17
|
so now let's see if it lets me drag elements.
|
|
0:44:21
|
Yep, not sure what happened.
|
|
0:44:26
|
So while they're in queue
|
|
0:44:30
|
we want to get the reporting statistic of let's say we want
|
|
0:44:42
|
to get the reporting statistic of from the object which is the CS queue.
|
|
0:44:50
|
This particular queue. We want to see
|
|
0:44:59
|
position in queue.
|
|
0:45:01
|
Which queue are we wanting information from because
|
|
0:45:04
|
we might have more than one. The CS queue which is blank
|
|
0:45:07
|
and overridden at the application when we're
|
|
0:45:10
|
actually applying this script.
|
|
0:45:12
|
The contact is the triggering contact
|
|
0:45:15
|
the calling party and we want to store this in -- it looks like
|
|
0:45:19
|
it needs to be an integer, so let's go create an integer.
|
|
0:45:22
|
We'll just cancel, create a type int
|
|
0:45:26
|
by the way, if you type this wrong, it says it's not valid
|
|
0:45:33
|
because it wants lowercase int so you may just want to
|
|
0:45:36
|
use the drop-down.
|
|
0:45:39
|
Name, let's call this position in queue.
|
|
0:45:50
|
And say ok.
|
|
0:45:54
|
We are also going to look at weight time.
|
|
0:45:59
|
We'll do that in a minute.
|
|
0:46:02
|
So let's again say CS queue
|
|
0:46:05
|
field
|
|
0:46:08
|
position in queue
|
|
0:46:10
|
of which queue? The CS queue.
|
|
0:46:12
|
And we're going to store the information we gather
|
|
0:46:15
|
in position in queue.
|
|
0:46:19
|
Now we've gathered the information, we need to do something
|
|
0:46:21
|
with it, so let's say we want to play the queue prompt
|
|
0:46:27
|
that says your position in queue -- well, actually first of all that says
|
|
0:46:34
|
'Thank you for waiting. Your call is very important to us.'
|
|
0:46:36
|
'Please continue to hold.' And then we want to play a
|
|
0:46:39
|
prompt that tells them what their position in queue is.
|
|
0:46:42
|
Now, while we mentioned that text-to-speech is a
|
|
0:46:47
|
third party product, that's for complex text. If all we want to do
|
|
0:46:52
|
is have the engine read back a simple value such as a time
|
|
0:46:58
|
or a number, there's actually a built-in text-to-speech
|
|
0:47:01
|
interpreter -- actually, what it really does is it looks at a bunch of
|
|
0:47:06
|
existing prompts that have been recorded for that number
|
|
0:47:09
|
but we can actually generate a prompt based on a simple number
|
|
0:47:14
|
or time, so what we're going to do is go up to prompt
|
|
0:47:19
|
and we're going to create a generated prompt.
|
|
0:47:25
|
It doesn't really matter where we put this
|
|
0:47:27
|
I could put position in queue here. This is just when
|
|
0:47:30
|
it evaluates that.
|
|
0:47:34
|
In fact, let me just go ahead and put everything up here.
|
|
0:47:37
|
Ok, so I've got my position in queue evaluation. Now I'm
|
|
0:47:41
|
going to create a generated prompt. The generator type is
|
|
0:47:44
|
a number. The constructor type is a number only.
|
|
0:47:50
|
And the number, the values, if I click set, is the variable
|
|
0:47:55
|
where the number was stored which is position in queue.
|
|
0:47:59
|
So now the number that it's going to generate a
|
|
0:48:02
|
prompt for is based on the dynamically gathered information
|
|
0:48:08
|
of position in queue.
|
|
0:48:10
|
We don't want to override the language, EN US is fine.
|
|
0:48:15
|
Any output prompt needs to be stored in a variable
|
|
0:48:18
|
that can be empty called prompt at least to begin with.
|
|
0:48:23
|
So let's just go ahead and say cancel.
|
|
0:48:27
|
We have to create a variable called of the type prompt.
|
|
0:48:32
|
And the name will be let's say position
|
|
0:48:38
|
in queue prompt.
|
|
0:48:44
|
Actually, let's say position in queue number
|
|
0:48:53
|
number prompt or something like that.
|
|
0:48:59
|
Go back here. The generator type is a number.
|
|
0:49:04
|
The number is the variable position in queue which is an integer.
|
|
0:49:10
|
And we're taking and placing that in the output prompt
|
|
0:49:14
|
position in queue number prompt.
|
|
0:49:17
|
Now that's not playing a prompt and if we played the prompt, we
|
|
0:49:21
|
could now -- in fact, I can just copy this and paste it
|
|
0:49:26
|
and we can just play the prompt
|
|
0:49:32
|
for the variable position in queue number prompt
|
|
0:49:36
|
but all this is going to do is say -- let's say there were seven other
|
|
0:49:41
|
people in queue
|
|
0:49:44
|
and we play, 'Your call is very important to us. Please continue
|
|
0:49:47
|
to hold seven.' or 'Your position in queue is eight.'
|
|
0:49:53
|
Whatever.
|
|
0:49:54
|
But it doesn't actually say, 'You're currently the eighth caller.'
|
|
0:50:00
|
or 'Your position in queue is currently number eight.'
|
|
0:50:04
|
so we would need to have another prompt
|
|
0:50:08
|
and there are things that we could do to create container
|
|
0:50:10
|
prompts where we take all three of these, create a
|
|
0:50:14
|
container or a way that the prompt is stored, all
|
|
0:50:20
|
three of them are aggregate together and sometimes you
|
|
0:50:23
|
want to do that, sometimes you don't.
|
|
0:50:25
|
For the lab, it's just simpler to have a bunch of play prompts.
|
|
0:50:29
|
And then I might actually come up here and go record the
|
|
0:50:33
|
prompt and the actual prompt gets recorded and it says
|
|
0:50:38
|
something like you're currently -- 'Currently your position in queue
|
|
0:50:43
|
is number eight.' Eight is what will be played next
|
|
0:50:50
|
but right now we just want to play
|
|
0:50:53
|
left bracket, right bracket
|
|
0:50:56
|
'Your position in queue...'
|
|
0:51:09
|
Did I spell that right? Queue
|
|
0:51:12
|
'.... is number .wav'
|
|
0:51:17
|
whatever I actually named the prompt that I had created
|
|
0:51:21
|
with Unity Connection and uploaded.
|
|
0:51:26
|
Ok, I didn't actually play the -- or I didn't actually create that
|
|
0:51:29
|
so we won't hear that being played right now, but that's what
|
|
0:51:34
|
I would do is I would record that, so here I've got it says,
|
|
0:51:38
|
'Your call is very important to us.' Here it would say,
|
|
0:51:41
|
'Your position in queue is number.' and then we read the actual number.
|
|
0:51:46
|
In our case, when we test it, it's going to say, 'Your call is very important
|
|
0:51:49
|
to us.' Not be able to do anything, but it won't error out.
|
|
0:51:53
|
Why won't it error out? Because continue on prompt errors
|
|
0:51:58
|
is set to yes. It goes ahead and continues. If I said no,
|
|
0:52:01
|
then we'd have an issue. It would go back to the default...
|
|
0:52:05
|
default application prompt.
|
|
0:52:06
|
But here I'm just saying continue, so it will just ignore the fact that
|
|
0:52:10
|
it can't find that file and say -- if I let's say we have
|
|
0:52:14
|
one other caller in queue is probably what we'll do, it will
|
|
0:52:17
|
say my position in queue two.
|
|
0:52:19
|
So, 'Your call is very important to us two.'
|
|
0:52:22
|
Then it will go to hold 45 seconds, unhold. We'll probably change that
|
|
0:52:27
|
from 45 seconds when we test. Unhold and then go
|
|
0:52:31
|
back and get your reporting statistic again.
|
|
0:52:35
|
See it it's changed.
|
|
0:52:36
|
Now what if we also wanted to do something like say
|
|
0:52:39
|
'Your average expected wait time.' Now this is something you almost
|
|
0:52:43
|
never want to do if you have a relatively light
|
|
0:52:48
|
call queue. If you have a relatively light call queue, you
|
|
0:52:51
|
typically want to tell the caller what position in queue they are
|
|
0:52:54
|
because you want them to know there's only like
|
|
0:52:57
|
two or three people ahead of you.
|
|
0:52:59
|
However, if you don't have very many caller deep in your queue
|
|
0:53:03
|
then the calculation, the algorithm that's run in order to determine
|
|
0:53:10
|
your expected wait time tends to be quite erroneous.
|
|
0:53:15
|
And this is just in real life. I'm kind of giving you some
|
|
0:53:17
|
tips. In the lab, you do whatever you're told of course.
|
|
0:53:22
|
But if you have a deep call queue, you almost never
|
|
0:53:26
|
want to tell the callers how deep the queue is, your position in queue
|
|
0:53:31
|
is like number 40
|
|
0:53:34
|
unless you're trying to get them to hang up and you will
|
|
0:53:38
|
you have a script that actually goes and places their name
|
|
0:53:44
|
places their phone number based on their calling number or input number
|
|
0:53:48
|
in a -- basically an XML file or database and we tell them
|
|
0:53:57
|
that they can expect to call back.
|
|
0:53:59
|
And it resets their position in queue, it doesn't keep them in their current
|
|
0:54:02
|
position, however, as soon as an agent becomes available
|
|
0:54:05
|
it automatically calls them back, reserves the agent, waits for the
|
|
0:54:10
|
system to call the original caller back and then connects
|
|
0:54:15
|
them to the agent and that's the way really good
|
|
0:54:18
|
really good call centers are written and you can do that
|
|
0:54:21
|
with UCCX. It's not difficult at all.
|
|
0:54:23
|
I shouldn't say it's not difficult. It's a quite involved script, quite
|
|
0:54:27
|
difficult script, but it's not impossible to do in any way.
|
|
0:54:31
|
Something that wouldn't be done in the lab.
|
|
0:54:34
|
But that might be a reason you wanted to tell someone
|
|
0:54:36
|
that they're number 40 in queue.
|
|
0:54:38
|
However, if you do have deep queues, then the algorithm
|
|
0:54:42
|
of expected wait time becomes fairly accurate. Again, we're
|
|
0:54:46
|
talking about the lab, so let's say the lab simply said
|
|
0:54:49
|
tell them their position in queue and their expected wait time.
|
|
0:54:53
|
We need to get real time data, so let's just copy this
|
|
0:54:57
|
and I can right click and do copy or I have Ben just hitting
|
|
0:55:00
|
control C
|
|
0:55:02
|
and I'm going to go ahead and copy it or paste it right here.
|
|
0:55:08
|
And I'm going to change a number of things.
|
|
0:55:12
|
I want same from the CS queue...
|
|
0:55:14
|
The field I want is the expected wait time
|
|
0:55:18
|
from the CS queue.
|
|
0:55:20
|
And I want to store it in a integer.
|
|
0:55:25
|
So I'm just going to go ahead and hit ok.
|
|
0:55:27
|
I really don't want to store that integer, so I'm going to create
|
|
0:55:30
|
a new int of name expected
|
|
0:55:37
|
wait time number
|
|
0:55:43
|
and I'm going to change this variable.
|
|
0:55:46
|
The first one got position in queue, this one gets expected
|
|
0:55:48
|
wait time and stores it in the new variable expected wait time number.
|
|
0:55:54
|
And then just like I created a generated prompt for the
|
|
0:55:58
|
last one, I'm going to copy that and paste it.
|
|
0:56:01
|
And I'm going to need a new prompt, I already know that.
|
|
0:56:06
|
So I'm just going to create the prompt expected wait time
|
|
0:56:18
|
prompt number or number prompt.
|
|
0:56:27
|
And so I'll go to my generated prompt.
|
|
0:56:31
|
The generator is a time.
|
|
0:56:37
|
Constructor is time,
|
|
0:56:40
|
but I want hours and minutes I don't want it to say...
|
|
0:56:47
|
I don't want it to say your expected wait time is 0030
|
|
0:56:52
|
I want it to say four hours and three minutes or hopefully
|
|
0:56:55
|
not four hours, but three minutes maybe.
|
|
0:56:58
|
And so actually...
|
|
0:57:03
|
No, let's just use time because I need a single value for what I'm
|
|
0:57:06
|
doing right here and we'll say time is the expected wait time
|
|
0:57:10
|
number, ok,
|
|
0:57:13
|
now this is only going to say the number.
|
|
0:57:16
|
Alright, so
|
|
0:57:19
|
and I need to store it in expected wait time prompt
|
|
0:57:24
|
so this is only if I played this prompt, it's only going to
|
|
0:57:29
|
say the actual number and I may want it to do something like
|
|
0:57:34
|
say number of minutes.
|
|
0:57:36
|
So let's say I have play prompt.
|
|
0:57:42
|
And...
|
|
0:57:46
|
just so that I can separate where these are actually being played
|
|
0:57:49
|
for our demonstration without having to bore you of creating
|
|
0:57:52
|
the prompt, I'm going to copy this prompt and paste it
|
|
0:57:58
|
here and I'm going to change this prompt to the expected wait time
|
|
0:58:06
|
number prompt. Now this is only going to say a number.
|
|
0:58:10
|
So I also sort of want it to say minutes.
|
|
0:58:14
|
In other words, 'Your expected wait time...' and I would record that
|
|
0:58:17
|
prompt 'Your expected wait time is...' it would place -- it would generate
|
|
0:58:22
|
and say the number and then I would also play another prompt
|
|
0:58:25
|
saying minutes.
|
|
0:58:29
|
So I'm going to copy this again.
|
|
0:58:33
|
Paste it again.
|
|
0:58:38
|
And change this to the
|
|
0:58:44
|
prompt, browse prompts
|
|
0:58:47
|
and I actually here want to go to WF avid prompts.
|
|
0:58:54
|
I want to go to system prompts for G.711 codec
|
|
0:58:58
|
EN US and I want to say...
|
|
0:59:03
|
Do I have it here somewhere?
|
|
0:59:07
|
Generated time
|
|
0:59:13
|
minutes, there we go.
|
|
0:59:18
|
Ok, so it's going to play that entire system prompt
|
|
0:59:22
|
and I actually -- I could replace this with SP
|
|
0:59:27
|
since it's a system prompt
|
|
0:59:33
|
in the folder generated time and then minutes. wav
|
|
0:59:39
|
Ok, so now -- as soon as I get into queue
|
|
0:59:43
|
hits a label, does nothing
|
|
0:59:45
|
evaluates position in queue and then creates
|
|
0:59:50
|
a generated prompt based on that, it doesn't play it
|
|
0:59:53
|
it just creates it, stores it in the variable called position
|
|
0:59:57
|
in queue number prompt
|
|
0:59:58
|
evaluates from real time data or the real time reporting
|
|
1:00:04
|
engine the expected wait time, grabs it integer number
|
|
1:00:07
|
places it in a variable
|
|
1:00:10
|
takes that variable, creates a prompt, places it in this
|
|
1:00:14
|
empty prompt and then it plays that wait time number
|
|
1:00:19
|
and then after it says that, it says minutes. So what we're going to do
|
|
1:00:22
|
is we're going to get in queue and we're going to hear it
|
|
1:00:26
|
say two or it's going to be really out of wack
|
|
1:00:30
|
it might say 20 or 200 minutes.
|
|
1:00:35
|
Now we could do other things like if it was 200
|
|
1:00:37
|
minutes, we could run some math with the script to divide by
|
|
1:00:41
|
60 and come up with hours and minutes. We can make it
|
|
1:00:45
|
a lot more intelligent, but again this is a lab environment
|
|
1:00:49
|
you're going to have a lot of points allocated to this
|
|
1:00:52
|
you're not going to be taking a lot of time.
|
|
1:00:53
|
They know that this isn't a call center exam.
|
|
1:00:58
|
I kind of hope they would release a call center CCIE
|
|
1:01:01
|
because I like it so much, but the whole thing would
|
|
1:01:04
|
basically be scripting and troubleshooting
|
|
1:01:07
|
especially if it's IPCC enterprise.
|
|
1:01:09
|
Anyhow,
|
|
1:01:11
|
so it's going to say, 'Five minutes'
|
|
1:01:15
|
Then it's going to say, 'Thank you for waiting. Your call is
|
|
1:01:18
|
very important to us. Please continue to hold while your
|
|
1:01:20
|
call is answered by the next available agent.'
|
|
1:01:24
|
then it's going to say nothing because we didn't
|
|
1:01:28
|
actually record this and then it's going to say,
|
|
1:01:30
|
'Two' and 'This is going to be your position in queue.'
|
|
1:01:38
|
Ok, even be let's see if there is real quick.
|
|
1:01:42
|
A prompt, ellipsis, prompt tab
|
|
1:01:45
|
browse prompt
|
|
1:01:47
|
we're already in the system prompts.
|
|
1:01:51
|
Let's look in this root directory is there a
|
|
1:01:54
|
your number or your position in queue.
|
|
1:01:59
|
User dialog
|
|
1:02:03
|
No.
|
|
1:02:05
|
I mean there's a number of things that are already recorded
|
|
1:02:07
|
such as 'still there', so 'are you still there?'
|
|
1:02:14
|
Let's see...
|
|
1:02:19
|
There very well may be already 'your position in queue'
|
|
1:02:23
|
in one of these folders.
|
|
1:02:43
|
Stay on the line
|
|
1:02:44
|
collect digits
|
|
1:02:46
|
please wait for the next available operator
|
|
1:02:48
|
by the way, some of these that are ICM are typically used for
|
|
1:02:51
|
UCCE or enterprise, but they have slightly different
|
|
1:02:55
|
ways of saying it, so if you were told to let's say play
|
|
1:02:58
|
a welcome prompt or a queued prompt to wait for the
|
|
1:03:02
|
next available operator, but don't use the default one. Make it
|
|
1:03:05
|
say something specific, but don't use your own voice, use
|
|
1:03:08
|
the Cisco lady voice. It might be another, well it would be another
|
|
1:03:12
|
prompt that's already recorded. Just read through the names. They
|
|
1:03:15
|
typically indicate exact -- and when I say read through the names
|
|
1:03:19
|
I mean of the system prompts, so program files WF avid prompts
|
|
1:03:23
|
system codec language
|
|
1:03:27
|
but there are typically already some that are recorded.
|
|
1:03:32
|
If it's the Cisco lady, it would have to be.
|
|
1:03:35
|
Hold connect. Let's just -- folder.
|
|
1:03:38
|
I guess there's two other folders.
|
|
1:03:42
|
These are all for auto attendant.
|
|
1:03:46
|
There would be no -- whoops, I went up two levels.
|
|
1:03:50
|
Generated
|
|
1:03:53
|
these are all the generated prompts that are used
|
|
1:03:56
|
when it reads the actual number.
|
|
1:04:07
|
So there's probably not going to be anything in there.
|
|
1:04:09
|
Ok, so there's probably not something that already says
|
|
1:04:13
|
'your call is the next call' or 'your call is the position in queue' whatever.
|
|
1:04:17
|
Alright, so we know what it's going to play. We've done
|
|
1:04:21
|
all this. Let's go ahead and press save. Actually let's do
|
|
1:04:25
|
tools validate. There's no syntax logic. I should say
|
|
1:04:29
|
not syntax error. There may be logic error.
|
|
1:04:31
|
Let's press save.
|
|
1:04:33
|
We can go ahead and close this script.
|
|
1:04:38
|
We're going to switch over
|
|
1:04:41
|
to the application interface.
|
|
1:04:44
|
And let's change this delay while queued to ten seconds, so
|
|
1:04:49
|
that we don't actually wait too long
|
|
1:04:54
|
while we're testing it. Let's update it.
|
|
1:04:58
|
And let's go back to the application list and
|
|
1:05:01
|
refresh the application, so it pulls in the new instance of the
|
|
1:05:04
|
saved script in the repository and let's go ahead and test.
|
|
1:05:09
|
So here to test.
|
|
1:05:12
|
Actually, let's pull up our phones and make sure they're ready first.
|
|
1:05:17
|
And let's make sure we're still logged in.
|
|
1:05:23
|
Looks like we are. Let's grab Branch 2 Phone 2
|
|
1:05:30
|
We have corporate headquarter phone 2
|
|
1:05:34
|
Branch 2 Phone 1 -- let's grab corporate headquarter phone 1
|
|
1:05:37
|
so that we can have a few callers in queue.
|
|
1:05:40
|
I'm going to go ahead and minimize this.
|
|
1:05:42
|
Bring my phones over.
|
|
1:05:46
|
So let's make sure that our agents are not ready.
|
|
1:05:50
|
Ok, this agent is not ready.
|
|
1:05:53
|
This agent is ready. Let's change its state.
|
|
1:05:55
|
We want calls to go to queue.
|
|
1:06:00
|
Actually let's make both of these agents logged out
|
|
1:06:03
|
to begin with
|
|
1:06:06
|
because we want to test the functionality that
|
|
1:06:08
|
checks to see if agents are logged in.
|
|
1:06:11
|
And if they are not logged in, they are logged out
|
|
1:06:15
|
then zero agents are available and it redirects
|
|
1:06:19
|
to Voice mail and we want to hear the fact that it
|
|
1:06:21
|
hit the call handler for the professional -- what was it?
|
|
1:06:25
|
Professional wodget support or professional widget support.
|
|
1:06:27
|
I think it was professional widget support.
|
|
1:06:30
|
Why? Because 555 was the extension of that
|
|
1:06:34
|
-- not that that's necessarily where we want it to go
|
|
1:06:36
|
just an example.
|
|
1:06:38
|
Ok, so let's have anyone call in
|
|
1:06:41
|
1990
|
|
1:06:48
|
Well actually, first of all let's just do that again real quick.
|
|
1:06:51
|
I wanted to do a debug reactive, but let's just do it real quick.
|
|
1:06:54
|
Dial
|
|
1:07:01
|
So we heard it say welcome, that was the script
|
|
1:07:04
|
and then we heard, 'Sorry, prowidget support is not available.'
|
|
1:07:09
|
That was Unity Connection. How can we be sure?
|
|
1:07:11
|
Glad you asked.
|
|
1:07:13
|
Let's go ahead and minimize all these just to avoid confusion.
|
|
1:07:17
|
Go up to debug reactive script.
|
|
1:07:20
|
We will choose the script name.
|
|
1:07:24
|
And we'll choose how long we want to wait for the call
|
|
1:07:26
|
to come in. I would always just choose a longer value rather than
|
|
1:07:29
|
shorter. It just means that it won't time out on you.
|
|
1:07:33
|
Now we'll go over and tell the call to dial.
|
|
1:07:38
|
And it's going to ring continually until I accept this call.
|
|
1:07:43
|
And I can just press play up here.
|
|
1:07:47
|
Actually I'm not sure why it's not giving me my pointer.
|
|
1:07:50
|
Or I can do what's called step over.
|
|
1:07:52
|
And it doesn't look like a pointer. It looks like an hour glass
|
|
1:07:55
|
but it's working just fine. I'm going to step over one at a time
|
|
1:07:58
|
otherwise, if I hit play, it's going to go really fast.
|
|
1:08:01
|
So I'm going to step over. As soon as I go past here, we
|
|
1:08:05
|
accept the call.
|
|
1:08:11
|
There we go.
|
|
1:08:13
|
We accepted the call.
|
|
1:08:17
|
And so it stopped ringing.
|
|
1:08:18
|
As soon as press play -- let me turn up this volume.
|
|
1:08:21
|
As soon as I press play
|
|
1:08:24
|
or I'm sorry not play, but step over. It stepped over the
|
|
1:08:27
|
prompt for welcome and it played just the prompt.
|
|
1:08:34
|
Why? Because we had changed the default
|
|
1:08:38
|
ICD welcome which said
|
|
1:08:42
|
welcome to our queue -- whatever it said, I don't remember, but
|
|
1:08:44
|
I just changed it with welcome. Maybe that's what it was to begin with, I don't remember.
|
|
1:08:49
|
So now we're going to look at our variables down here.
|
|
1:08:52
|
And I'm expanding this so we can see them.
|
|
1:08:55
|
Number of agents logged in.
|
|
1:08:59
|
This is going to -- where is it? Number of agents logged in
|
|
1:09:04
|
currently this -- once we hit step over, this value will update.
|
|
1:09:07
|
So I hit step over.
|
|
1:09:09
|
It stays at zero, so now we evaluate the expression
|
|
1:09:17
|
is the number of agents logged in not equal to zero.
|
|
1:09:22
|
False, it is not equal to zero which means it
|
|
1:09:25
|
is equal to zero.
|
|
1:09:29
|
Six one way half a dozen the other -- so call redirect
|
|
1:09:32
|
to 1850, but remember we told it to reset the called number
|
|
1:09:38
|
to 555 which becomes the redirect called number
|
|
1:09:43
|
which when it gets to Unity Connection looks at that redirect
|
|
1:09:46
|
number and says, 'Do I have an extension?' It does have
|
|
1:09:49
|
a system call handler for prowidget support.
|
|
1:09:54
|
So as soon as I press step over here
|
|
1:09:57
|
it's going to redirect.
|
|
1:10:03
|
So that was Unity Connection playing that message.
|
|
1:10:07
|
That greeting and now it's going on and it's trying
|
|
1:10:10
|
to create an e-mail.
|
|
1:10:13
|
Where was my contact here for e-mail? It's currently
|
|
1:10:15
|
null. If I step over
|
|
1:10:19
|
group is not configured and cannot create new e-mail contacts.
|
|
1:10:21
|
That's because my e-mail subsystem isn't up because
|
|
1:10:25
|
I didn't ever provision a e-mail server
|
|
1:10:30
|
back here under subsystem's e-mail. If I had provisioned a
|
|
1:10:33
|
server, it would have worked.
|
|
1:10:37
|
Ok, so it basically failed.
|
|
1:10:39
|
Well, it failed that step. It obviously worked properly
|
|
1:10:43
|
for everything else.
|
|
1:10:45
|
Ok, so we're going to go ahead and shut down this current
|
|
1:10:47
|
debug session.
|
|
1:10:50
|
And we will start another session.
|
|
1:10:52
|
Reactive script, same script
|
|
1:10:56
|
and let's just give it a large value so we can do what we need to do.
|
|
1:11:00
|
And we're now going to go and log in.
|
|
1:11:06
|
So I'm just going to hit services
|
|
1:11:09
|
to log out altogether, services again. This one's trying to log in
|
|
1:11:14
|
it did, but it's in a state of not ready. Here I'll press two.
|
|
1:11:17
|
This will auto log in with one-button login
|
|
1:11:20
|
but go to a state of not ready.
|
|
1:11:22
|
That's great.
|
|
1:11:24
|
Let's try the call again.
|
|
1:11:31
|
It's going to keep ringing until I take the call, step over
|
|
1:11:35
|
step over, play welcome
|
|
1:11:40
|
evaluate the next statement.
|
|
1:11:42
|
Ok, we see that it evaluated the statement number of agents
|
|
1:11:46
|
currently logged in is now set to two.
|
|
1:11:50
|
So which output branch does it take? True, go to ACD.
|
|
1:11:53
|
So where does it go? It comes down here.
|
|
1:11:57
|
One of the things we never looked at was the SRS
|
|
1:12:02
|
temp resource selected. This is the agent that has
|
|
1:12:05
|
been selected by the system based on whatever resource selection
|
|
1:12:10
|
criteria, skills based routing we set up.
|
|
1:12:13
|
Now if there's two agents logged in, but none are available
|
|
1:12:17
|
then it's not going to select anyone.
|
|
1:12:20
|
Stop scrolling. Ok.
|
|
1:12:22
|
Let's step over.
|
|
1:12:24
|
So we see it didn't go to the connected branch, it went
|
|
1:12:26
|
to the queued branch in queue loop.
|
|
1:12:29
|
-- position in queue
|
|
1:12:31
|
change
|
|
1:12:35
|
and now the position in queue is we're the first position in queue.
|
|
1:12:41
|
The number prompt will be created next, so now
|
|
1:12:46
|
we see a com.cisco.prompt generated
|
|
1:12:49
|
so it's dynamically generated this prompt with the number
|
|
1:12:52
|
one that's going to be played.
|
|
1:12:54
|
Let's look at expected wait time.
|
|
1:12:58
|
Step over.
|
|
1:12:59
|
It says expected wait time is less than one minute.
|
|
1:13:03
|
Now it's going to generate the prompt so now there's a
|
|
1:13:06
|
second generated prompt and now it's going to say
|
|
1:13:10
|
basically it's going to play the prompt less than one.
|
|
1:13:20
|
Ok,
|
|
1:13:24
|
now it's going to play 'Your call is very important to us.'
|
|
1:13:32
|
That's a lie of course.
|
|
1:13:35
|
Now it should play 'Your position in queue'
|
|
1:13:39
|
It's now playing that, so we need to go take a look
|
|
1:13:42
|
at that.
|
|
1:13:44
|
And then -- whoops. Oh, it's not playing that
|
|
1:13:47
|
because we didn't record that.
|
|
1:13:51
|
So it recorded one. It basically it can't play -1
|
|
1:13:55
|
because it doesn't have -- it can only play integers.
|
|
1:13:58
|
Integers are non-negative values.
|
|
1:14:01
|
Alright, so it couldn't play the -1, but it
|
|
1:14:04
|
did play the 'position in' one so if we would have said after the
|
|
1:14:07
|
queue, if we would have actually recorded
|
|
1:14:09
|
'Your current position in the queue is number' then this would have said
|
|
1:14:14
|
'one' so now if we go step over, it should play music on hold.
|
|
1:14:25
|
Whoops, I accidentally hung up.
|
|
1:14:27
|
-- hear music on hold, so we will have to evaluate that.
|
|
1:14:30
|
And if I say next, the contact terminated remotely
|
|
1:14:35
|
it hung up.
|
|
1:14:38
|
Ok, so let's actually have a few callers in queue
|
|
1:14:42
|
I'm not going to go to a debug reactive
|
|
1:14:44
|
I'm just going to dial in.
|
|
1:15:00
|
Ok, now it's not hearing music on hold.
|
|
1:15:03
|
So we would have to go figure why that is
|
|
1:15:06
|
and that would really be something for the media
|
|
1:15:09
|
section -- I'm going to go ahead and turn this down.
|
|
1:15:13
|
That would really be something for the media section.
|
|
1:15:15
|
We would do all the things we would do to troubleshoot
|
|
1:15:17
|
media. We're not going to do that right now because
|
|
1:15:20
|
that doesn't really have anything to do with UCCX
|
|
1:15:23
|
it has to do with actual -- it's the same thing as if a
|
|
1:15:28
|
phone wasn't playing music on hold what would we do to
|
|
1:15:32
|
troubleshoot? We'd go take a look at the media resource
|
|
1:15:35
|
first of all the device pool of that device, the media
|
|
1:15:38
|
resource group list, the media resource group
|
|
1:15:41
|
the MOH servers, make sure they're up and running.
|
|
1:15:44
|
Is it multicast or unicast? If it's multicast, am I trying to
|
|
1:15:48
|
play a stream that isn't able to be played? Actually,
|
|
1:15:52
|
you know what, that's what it is.
|
|
1:15:54
|
I'm calling in from a Branch 2 phone
|
|
1:15:57
|
and I previously when we did media, I had told it to
|
|
1:16:02
|
play from that local router over there
|
|
1:16:05
|
and there is no -- the router over there doesn't have
|
|
1:16:09
|
that actual MOH multicast file provisioned right now.
|
|
1:16:15
|
You know what -- let's just see if it is that simple.
|
|
1:16:18
|
I believe that's what's going on. If so, that would be very hard
|
|
1:16:23
|
because my router go rebooted. Actually let's say
|
|
1:16:26
|
telephony service do sh flash | in .au
|
|
1:16:37
|
Ok, here we've got music on hold. Let's say moh
|
|
1:16:42
|
music on hold
|
|
1:16:44
|
multicast
|
|
1:16:47
|
moh 239111
|
|
1:16:52
|
port 16384
|
|
1:16:56
|
route and I want to route it to 177.3.11.1 and also
|
|
1:17:03
|
177.1.254.3
|
|
1:17:22
|
Ok, it's still not playing. That's ok, -- this later
|
|
1:17:25
|
and again, we probably would have already set up media.
|
|
1:17:27
|
When we call in from corporate headquarters, we will
|
|
1:17:30
|
be able to hear that music on hold.
|
|
1:17:33
|
Ok, so let's go ahead and call in from corporate headquarter
|
|
1:17:36
|
phone 1
|
|
1:17:40
|
1990
|
|
1:17:45
|
Now, this should play the number 2
|
|
1:17:56
|
There we go, so we heard position two
|
|
1:18:01
|
and we're hearing music on hold
|
|
1:18:04
|
because multicast is actually coming from the CUCM
|
|
1:18:08
|
server and it's still just saying minutes.
|
|
1:18:11
|
It's not saying let's see
|
|
1:18:16
|
Oh, we don't have the debug up. We'll go ahead and call in from the
|
|
1:18:19
|
third phone here. The reason it's still just saying minutes instead of
|
|
1:18:22
|
reading the number is because it can't read the generated prompt
|
|
1:18:26
|
of -1 and like I said, it's still -- it's very inaccurate
|
|
1:18:30
|
until you've had call -- queues that have been queued for a decent
|
|
1:18:34
|
depth and a long time, it takes the algorithm a good
|
|
1:18:38
|
amount of minutes -- maybe 10 or 20 minutes of calls
|
|
1:18:42
|
in queue and actually agents answering these calls in
|
|
1:18:46
|
decent random orders to take all that information
|
|
1:18:50
|
into account and come up with a valid number.
|
|
1:18:52
|
Otherwise, it will always tell your callers that they
|
|
1:18:54
|
have -- you can just do an evaluation that says,
|
|
1:18:58
|
'if number of minutes equals -1, then play prompt
|
|
1:19:08
|
less than one minute.' And you record that.
|
|
1:19:10
|
The problem is, it will almost always tell your callers that
|
|
1:19:13
|
there's less than one minute of wait when there really isn't.
|
|
1:19:16
|
Ok, so here we're going to dial the third call in
|
|
1:19:31
|
and let's see... Oh, it's not going to let the third caller in
|
|
1:19:34
|
because we only have two media ports.
|
|
1:19:37
|
Ok, so I'm going to go ahead and hang up from
|
|
1:19:41
|
Jack Shepherd and we're going to go back to the
|
|
1:19:43
|
debug reactive script
|
|
1:19:47
|
so it rang busy because we only had two media ports.
|
|
1:19:52
|
Ok, so I'm going to have him call in again.
|
|
1:19:58
|
And we're going to go back
|
|
1:20:00
|
and step over, step over
|
|
1:20:03
|
play the prompt of welcome.
|
|
1:20:07
|
Look at the number of agents logged in. It's two.
|
|
1:20:12
|
That's true, go to the ACD.
|
|
1:20:14
|
Send it to queued, look at the position in queue.
|
|
1:20:18
|
What's my position in queue?
|
|
1:20:20
|
Step -- my position into queue is two.
|
|
1:20:24
|
Generate the prompt.
|
|
1:20:26
|
And now the expected wait time, gather that information.
|
|
1:20:31
|
It still says -1 which is not accurate.
|
|
1:20:34
|
Generate that prompt.
|
|
1:20:36
|
And now play that prompt which is -- it's not going to play
|
|
1:20:40
|
anything and then play minutes.
|
|
1:20:44
|
And then play 'Your call is important to us.'
|
|
1:20:56
|
Play a prompt that we never created
|
|
1:20:58
|
and then play 'Your position in queue' which is number
|
|
1:21:04
|
so you're the second caller.
|
|
1:21:06
|
Call hold, music on hold
|
|
1:21:08
|
delay, now I pressed step over, but we actually have to
|
|
1:21:12
|
wait the ten seconds.
|
|
1:21:20
|
Now, -- step over
|
|
1:21:22
|
and then it goes back to the queue loop
|
|
1:21:24
|
we get reporting statistic etc.
|
|
1:21:27
|
Let's say I just go through.
|
|
1:21:29
|
Let's just press play at this point. If you press
|
|
1:21:32
|
play, it will just go ahead and play through.
|
|
1:21:38
|
Notice I pressed hash and I just escaped that queue
|
|
1:21:42
|
telling me the same thing or that prompt. Why?
|
|
1:21:45
|
Because the prompt was interruptible.
|
|
1:21:48
|
So at this point
|
|
1:21:52
|
I'm going to go ahead and go to an agent
|
|
1:21:55
|
where we see how many calls are queued
|
|
1:21:58
|
the actual queue time has been about seven minutes
|
|
1:22:00
|
I'm going to change my state
|
|
1:22:06
|
to the state of one ready.
|
|
1:22:11
|
And as soon as I do, that agent is placed in a
|
|
1:22:14
|
reserved state.
|
|
1:22:19
|
And they may take the call. Actually,
|
|
1:22:22
|
I muted the wrong phone. They're taking the first call
|
|
1:22:25
|
in queue, but UCCX is actually -- or sorry
|
|
1:22:29
|
the corporate headquarter phone 1 is still on hold
|
|
1:22:33
|
so this is in a state of talking.
|
|
1:22:36
|
There's still one call in queue. I'm going to
|
|
1:22:39
|
go ahead and hang up.
|
|
1:22:45
|
Now why is the other call in still in queue?
|
|
1:22:47
|
Because if I can see down here at the bottom, my
|
|
1:22:52
|
-- I'm in a state of work. I think we gave it 45 seconds.
|
|
1:22:55
|
I'm going to go ahead and while I'm there, change my
|
|
1:22:58
|
state to two not ready. I could change it to
|
|
1:23:02
|
ready and go ready quicker.
|
|
1:23:17
|
Let's tell it to go to the queue loop
|
|
1:23:22
|
and for some reason it skipped over all those.
|
|
1:23:34
|
Sometimes the debug doesn't work perfectly
|
|
1:23:37
|
so my expected wait time is still -1.
|
|
1:23:42
|
Minutes
|
|
1:23:44
|
it's actually not playing the prompts at this point which
|
|
1:23:46
|
is interesting.
|
|
1:23:48
|
I'm not sure why it's not playing the prompts right now.
|
|
1:23:50
|
It could be because we're in the debug.
|
|
1:24:03
|
Now this actually if I hang up on the debug, it actually
|
|
1:24:06
|
hangs up on that particular process as well.
|
|
1:24:11
|
The particular calling party.
|
|
1:24:13
|
So let's call in again.
|
|
1:24:20
|
It's not saying my place in queue anymore.
|
|
1:24:40
|
There we go. It was because I pressed the hash
|
|
1:24:42
|
that it wasn't playing that two.
|
|
1:24:48
|
Ok, so caller is queued.
|
|
1:24:50
|
Let's go ahead and grab one.
|
|
1:25:01
|
So we're taking the call from Jack Shepherd.
|
|
1:25:04
|
If we let it play through again, it should actually
|
|
1:25:07
|
play one this next time
|
|
1:25:09
|
because it's no longer the second call in queue.
|
|
1:25:16
|
There we go. We've got something other than
|
|
1:25:18
|
the number of minutes are that number of -1.
|
|
1:25:21
|
It read it in the wrong time operator.
|
|
1:25:26
|
So it updated my position in queue, it read the
|
|
1:25:29
|
expected wait time because it actually had something
|
|
1:25:31
|
other than the value that it had before.
|
|
1:25:38
|
It says 12:57 AM
|
|
1:25:41
|
obviously...
|
|
1:26:02
|
so there
|
|
1:26:09
|
my one agent should be exiting a state of work here
|
|
1:26:12
|
automatically going back to a state of available
|
|
1:26:15
|
I think we had it 45 seconds was the wrap up time. Yep
|
|
1:26:19
|
there we go, it's automatically in a state of ready. It's taking
|
|
1:26:22
|
the call.
|
|
1:26:26
|
Ok,
|
|
1:26:27
|
this other call, so we see the expected wait time is
|
|
1:26:32
|
114 minutes at this point based on actually having
|
|
1:26:34
|
some calls through. The problem is what we were doing
|
|
1:26:39
|
was -- and I'm just going to go ahead and hang up
|
|
1:26:40
|
on everything here.
|
|
1:26:44
|
We were reading this time
|
|
1:26:53
|
expected wait time -- I'm sorry, the expected
|
|
1:26:56
|
wait time prompt generation. We were reading it in just
|
|
1:27:01
|
time and we should have been reading it in --
|
|
1:27:05
|
as I started to do -- time, but the constructor type
|
|
1:27:09
|
of hours and -- for hours or
|
|
1:27:11
|
we could do some division.
|
|
1:27:13
|
We could simply say expected wait time is and it would say
|
|
1:27:19
|
114 minutes or we could do some actual math
|
|
1:27:25
|
with the script and have it divide that out and say
|
|
1:27:28
|
that that's one hour and what would that be?
|
|
1:27:30
|
One hour and 54 minutes
|
|
1:27:33
|
and then we could divide that out into the hours
|
|
1:27:36
|
and the minutes and play those separately
|
|
1:27:40
|
and it actually wants a value for here
|
|
1:27:44
|
so it's not going to just take nothing, so we would
|
|
1:27:47
|
have to do that separating of that out.
|
|
1:27:52
|
Ok,
|
|
1:27:53
|
but that's what we would have had to do.
|
|
1:27:57
|
But we did go through and we did create a script
|
|
1:27:59
|
or let's say there was a script already here
|
|
1:28:02
|
we could have been asked to troubleshoot something like this.
|
|
1:28:08
|
Are there any questions on the custom scripting that we've done?
|
|
1:28:12
|
I realize we didn't start back at the real beginning basics
|
|
1:28:17
|
that was never the intent of any of the modules of this
|
|
1:28:20
|
particular course, so if anyone doesn't have a good basis of
|
|
1:28:23
|
UCCX, I recommend that maybe you go back and
|
|
1:28:26
|
look at some of our deep dives or some of the more
|
|
1:28:30
|
remedial rudimentary classes that we have on UCCX
|
|
1:28:36
|
but otherwise, in terms of what we've done so far
|
|
1:28:40
|
the CS queues, the ordering
|
|
1:28:43
|
Ah! That was one thing
|
|
1:28:45
|
we didn't actually finish. Let me just go touch up on that
|
|
1:28:48
|
while I still leave the offer out there that if there's
|
|
1:28:51
|
any questions on anything we've done so far, please go
|
|
1:28:53
|
ahead and ask those questions now.
|
|
1:28:57
|
The one thing we haven't done yet is determine why
|
|
1:29:02
|
earlier -- and let's just see if -- let's just have him
|
|
1:29:07
|
dial in. Actually let's make sure both are ready.
|
|
1:29:16
|
Whoops
|
|
1:29:19
|
BLinus we want in a state of ready.
|
|
1:29:25
|
Ok, now BLinus and HReyes are both in a state of ready.
|
|
1:29:32
|
We believed earlier from our RMCM subsystem
|
|
1:29:36
|
contact service queue -- actually, let me just go back
|
|
1:29:39
|
and look at the sales -- I'm sorry skills and look at the
|
|
1:29:42
|
resources and how the skills are assigned and just make sure
|
|
1:29:47
|
that my -- everything here is correct. So sales
|
|
1:29:52
|
Ben Linus has eight as a competency level for sales
|
|
1:29:56
|
and three as a competency level for support.
|
|
1:30:01
|
Ok,
|
|
1:30:02
|
and let's go back and make sure Hugo Reyes -- and
|
|
1:30:05
|
nine for support as we have listed. That's correct.
|
|
1:30:08
|
Contact service queue widget sales, scroll down next
|
|
1:30:12
|
and we gave sales a weight of 101
|
|
1:30:15
|
101 and 101
|
|
1:30:17
|
and support a weight of 100
|
|
1:30:21
|
So just to be sure. We have Calculator in the lab
|
|
1:30:25
|
so 8 times 101
|
|
1:30:28
|
is 808, yep
|
|
1:30:29
|
3 times 100 obviously 100
|
|
1:30:32
|
plus 808 equals 1108
|
|
1:30:34
|
so my math is right there.
|
|
1:30:36
|
3 times 101 is 303
|
|
1:30:38
|
9 times 100 is 900
|
|
1:30:40
|
so 900+303 is 1203
|
|
1:30:45
|
so Hugo should be chosen first.
|
|
1:30:48
|
And it shows that he is chosen first here.
|
|
1:30:52
|
So that evaluates properly.
|
|
1:30:56
|
Oops
|
|
1:31:01
|
So let's -- Ben Linus. This is Hugo
|
|
1:31:04
|
on the right, Hugo should get the call first.
|
|
1:31:06
|
Dial the number.
|
|
1:31:09
|
Who is getting the call?
|
|
1:31:12
|
It is Hugo Reyes that's getting the call.
|
|
1:31:14
|
So not really sure -- maybe we were in the middle
|
|
1:31:19
|
of changing something or I'm not really sure, maybe
|
|
1:31:21
|
the other user wasn't actually in a state of ready and I just
|
|
1:31:24
|
missed that, but as long as Hugo is ready
|
|
1:31:27
|
and I'm just going to real quick change his state here.
|
|
1:31:32
|
So he's ready again.
|
|
1:31:34
|
Screen should update here in a second.
|
|
1:31:36
|
Whoops.
|
|
1:31:37
|
State ready.
|
|
1:31:40
|
Ok, they're both in a state of ready.
|
|
1:31:44
|
Ready and ready.
|
|
1:31:45
|
If I place the call again, Hugo should still get the call again.
|
|
1:31:50
|
Who gets it?
|
|
1:31:52
|
It is indeed -- it is indeed Hugo a second time.
|
|
1:31:57
|
So he does always win out.
|