Many doc directory improvements, including:
[asterisk/asterisk.git] / doc / tex / queues-with-callback-members.tex
1
2 \section{Introduction}
3
4 Pardon, but the dialplan in this tutorial will be expressed
5 in AEL, the new Asterisk Extension Language. If you are
6 not used to its syntax, we hope you will find it to some
7 degree intuitive. If not, there are documents explaining
8 its syntax and constructs.
9
10
11 \section{Configuring Call Queues}
12
13 \subsection{queues.conf}
14 First of all, set up call queues in queue.conf
15
16 Here is an example:
17
18 \begin{astlisting}
19 \begin{verbatim}
20    =========== queues.conf ===========
21    | ; Cool Digium Queues            |
22    | [general]                       |
23    | persistentmembers = yes         |
24    |                                 |
25    | ; General sales queue           |
26    | [sales-general]                 |
27    | music=default                   |
28    | context=sales                   |
29    | strategy=ringall                |
30    | joinempty=strict                |
31    | leavewhenempty=strict           |
32    |                                 |
33    | ; Customer service queue        |
34    | [customerservice]               |
35    | music=default                   |
36    | context=customerservice         |
37    | strategy=ringall                |
38    | joinempty=strict                |
39    | leavewhenempty=strict           |
40    |                                 |
41    | ; Support dispatch queue        |
42    | [dispatch]                      |
43    | music=default                   |
44    | context=dispatch                |
45    | strategy=ringall                |
46    | joinempty=strict                |
47    | leavewhenempty=strict           |
48    ===================================
49 \end{verbatim}
50 \end{astlisting}
51
52 In the above, we have defined 3 separate calling queues:
53 sales-general, customerservice, and dispatch.
54
55 Please note that the sales-general queue specifies a
56 context of "sales", and that customerservice specifies the
57 context of "customerservice", and the dispatch
58 queue specifies the context "dispatch". These three
59 contexts must be defined somewhere in your dialplan.
60 We will show them after the main menu below.
61
62 In the [general] section, specifying the persistentmembers=yes,
63 will cause the agent lists to be stored in astdb, and
64 recalled on startup.
65
66 The strategy=ringall will cause all agents to be dialed
67 together, the first to answer is then assigned the incoming
68 call.
69
70 "joinempty" set to "strict" will keep incoming callers from
71 being placed in queues where there are no agents to take calls.
72 The Queue() application will return, and the dial plan can
73 determine what to do next.
74
75 If there are calls queued, and the last agent logs out, the
76 remaining incoming callers will immediately be removed from
77 the queue, and the Queue() call will return, IF the "leavewhenempty" is
78 set to "strict".
79
80 \subsection{Routing incoming Calls to Queues}
81
82
83 Then in extensions.ael, you can do these things:
84
85 \subsubsection{The Main Menu}
86
87 At Digium, incoming callers are sent to the "mainmenu" context, where they
88 are greeted, and directed to the numbers they choose...
89
90 \begin{astlisting}
91 \begin{verbatim}
92 context mainmenu {
93
94         includes {
95                 digium;
96                 queues-loginout;
97         }
98
99         0 => goto dispatch,s,1;
100         2 => goto sales,s,1;
101         3 => goto customerservice,s,1;
102         4 => goto dispatch,s,1;
103
104         s => {
105                 Ringing();
106                 Wait(1);
107                 Set(attempts=0);
108                 Answer();
109                 Wait(1);
110                 Background(digium/ThankYouForCallingDigium);
111                 Background(digium/YourOpenSourceTelecommunicationsSupplier);
112                 WaitExten(0.3);
113         repeat:
114                 Set(attempts=$[${attempts} + 1]);
115                 Background(digium/IfYouKnowYourPartysExtensionYouMayDialItAtAnyTime);
116                 WaitExten(0.1);
117                 Background(digium/Otherwise);
118                 WaitExten(0.1);
119                 Background(digium/ForSalesPleasePress2);
120                 WaitExten(0.2);
121                 Background(digium/ForCustomerServicePleasePress3);
122                 WaitExten(0.2);
123                 Background(digium/ForAllOtherDepartmentsPleasePress4);
124                 WaitExten(0.2);
125                 Background(digium/ToSpeakWithAnOperatorPleasePress0AtAnyTime);
126                 if( ${attempts} < 2 ) {
127                         WaitExten(0.3);
128                         Background(digium/ToHearTheseOptionsRepeatedPleaseHold);
129                 }
130                 WaitExten(5);
131                 if( ${attempts} < 2 ) goto repeat;
132                 Background(digium/YouHaveMadeNoSelection);
133                 Background(digium/ThisCallWillBeEnded);
134                 Background(goodbye);
135                 Hangup();
136         }
137 }
138 \end{verbatim}
139 \end{astlisting}
140
141 \subsubsection{The Contexts referenced from the queues.conf file}
142
143 \begin{astlisting}
144 \begin{verbatim}
145 context sales {
146
147         0 => goto dispatch,s,1;
148         8 => Voicemail(${SALESVM});
149
150         s => {
151                 Ringing();
152                 Wait(2);
153                 Background(digium/ThankYouForContactingTheDigiumSalesDepartment);
154                 WaitExten(0.3);
155                 Background(digium/PleaseHoldAndYourCallWillBeAnsweredByOurNextAvailableSalesRepresentative);
156                 WaitExten(0.3);
157                 Background(digium/AtAnyTimeYouMayPress0ToSpeakWithAnOperatorOr8ToLeaveAMessage);
158                 Set(CALLERID(name)=Sales);
159                 Queue(sales-general,t);
160                 Set(CALLERID(name)=EmptySalQ);
161                 goto dispatch,s,1;
162                 Playback(goodbye);
163                 Hangup();
164         }
165 }
166 \end{verbatim}
167 \end{astlisting}
168
169 Please note that there is only one attempt to queue a call in the sales queue. All sales agents that
170 are logged in will be rung.
171
172 \begin{astlisting}
173 \begin{verbatim}
174 context customerservice {
175
176         0 => {
177                 SetCIDName(CSVTrans);
178                 goto dispatch|s|1;
179         }
180         8 => Voicemail(${CUSTSERVVM});
181
182         s => {
183                 Ringing();
184                 Wait(2);
185                 Background(digium/ThankYouForCallingDigiumCustomerService);
186                 WaitExten(0.3);
187         notracking:
188                 Background(digium/PleaseWaitForTheNextAvailableCustomerServiceRepresentative);
189                 WaitExten(0.3);
190                 Background(digium/AtAnyTimeYouMayPress0ToSpeakWithAnOperatorOr8ToLeaveAMessage);
191                 Set(CALLERID(name)=Cust Svc);
192                 Set(QUEUE_MAX_PENALTY=10);
193                 Queue(customerservice,t);
194                 Set(QUEUE_MAX_PENALTY=0);
195                 Queue(customerservice,t);
196                 Set(CALLERID(name)=EmptyCSVQ);
197                 goto dispatch,s,1;
198                 Background(digium/NoCustomerServiceRepresentativesAreAvailableAtThisTime);
199                 Background(digium/PleaseLeaveAMessageInTheCustomerServiceVoiceMailBox);
200                 Voicemail(${CUSTSERVVM});
201                 Playback(goodbye);
202                 Hangup();
203         }
204 }
205 \end{verbatim}
206 \end{astlisting}
207
208 Note that calls coming into customerservice will first be try to queue
209 calls to those agents with a QUEUE\_MAX\_PENALTY of 10, and if none are available,
210 then all agents are rung.
211
212 \begin{astlisting}
213 \begin{verbatim}
214 context dispatch
215 {
216
217         s => {
218                 Ringing();
219                 Wait(2);
220                 Background(digium/ThankYouForCallingDigium);
221                 WaitExten(0.3);
222                 Background(digium/YourCallWillBeAnsweredByOurNextAvailableOperator);
223                 Background(digium/PleaseHold);
224                 Set(QUEUE_MAX_PENALTY=10);
225                 Queue(dispatch|t);
226                 Set(QUEUE_MAX_PENALTY=20);
227                 Queue(dispatch|t);
228                 Set(QUEUE_MAX_PENALTY=0);
229                 Queue(dispatch|t);
230                 Background(digium/NoOneIsAvailableToTakeYourCall);
231                 Background(digium/PleaseLeaveAMessageInOurGeneralVoiceMailBox);
232                 Voicemail(${DISPATCHVM});
233                 Playback(goodbye);
234                 Hangup();
235         }
236 }
237 \end{verbatim}
238 \end{astlisting}
239
240 And in the dispatch context, first agents of priority 10 are tried, then
241 20, and if none are available, all agents are tried.
242
243 Notice that a common pattern is followed in each of the three queue contexts:
244
245 First, you set QUEUE\_MAX\_PENALTY to a value, then you call
246 Queue($<$queue-name$>$,option,...) (see the Queue application documetation for details)
247
248 In the above, note that the "t" option is specified, and this allows the
249 agent picking up the incoming call the luxury of transferring the call to
250 other parties.
251
252 The purpose of specifying the QUEUE\_MAX\_PENALTY is to develop a set of priorities
253 amongst agents. By the above usage, agents with lower number priorities will
254 be given the calls first, and then, if no-one picks up the call, the QUEUE\_MAX\_PENALTY
255 will be incremented, and the queue tried again. Hopefully, along the line, someone
256 will pick up the call, and the Queue application will end with a hangup.
257
258 The final attempt to queue in most of our examples sets the QUEUE\_MAX\_PENALTY
259 to zero, which means to try all available agents.
260
261
262 \subsection{Assigning agents to Queues}
263
264 In this example dialplan, we want to be able to add and remove agents to
265 handle incoming calls, as they feel they are available. As they log in,
266 they are added to the queue's agent list, and as they log out, they are
267 removed. If no agents are available, the queue command will terminate, and
268 it is the duty of the dialplan to do something appropriate, be it sending
269 the incoming caller to voicemail, or trying the queue again with a higher
270 QUEUE\_MAX\_PENALTY.
271
272 Because a single agent can make themselves available to more than one queue,
273 the process of joining multiple queues can be handled automatically by the
274 dialplan.
275
276 \subsubsection{Agents Log In and Out}
277
278 \begin{astlisting}
279 \begin{verbatim}
280 context queues-loginout
281 {
282         6092 => {
283                         Answer();
284                         Read(AGENT_NUMBER,agent-enternum);
285                         VMAuthenticate(${AGENT_NUMBER}@default,s);
286                         Set(queue-announce-success=1);
287                         goto queues-manip,I${AGENT_NUMBER},1;
288                 }
289
290         6093 => {
291                         Answer();
292                         Read(AGENT_NUMBER,agent-enternum);
293                         Set(queue-announce-success=1);
294                         goto queues-manip,O${AGENT_NUMBER},1;
295                 }
296 }
297 \end{verbatim}
298 \end{astlisting}
299
300 In the above contexts, the agents dial 6092 to log into their queues,
301 and they dial 6093 to log out of their queues. The agent is prompted
302 for their agent number, and if they are logging in, their passcode,
303 and then they are transferred to the proper extension in the
304 queues-manip context.  The queues-manip context does all the
305 actual work:
306
307 \begin{astlisting}
308 \begin{verbatim}
309 context queues-manip {
310
311         // Raquel Squelch
312         _[IO]6121 => {
313                 &queue-addremove(dispatch,10,${EXTEN});
314                 &queue-success(${EXTEN});
315         }
316
317         // Brittanica Spears
318         _[IO]6165 => {
319                 &queue-addremove(dispatch,20,${EXTEN});
320                 &queue-success(${EXTEN});
321         }
322
323         // Rock Hudson
324         _[IO]6170 => {
325                 &queue-addremove(sales-general,10,${EXTEN});
326                 &queue-addremove(customerservice,20,${EXTEN});
327                 &queue-addremove(dispatch,30,${EXTEN});
328                 &queue-success(${EXTEN});
329         }
330
331         // Saline Dye-on
332         _[IO]6070 => {
333                 &queue-addremove(sales-general,20,${EXTEN});
334                 &queue-addremove(customerservice,30,${EXTEN});
335                 &queue-addremove(dispatch,30,${EXTEN});
336                 &queue-success(${EXTEN});
337         }
338 }
339 \end{verbatim}
340 \end{astlisting}
341
342 In the above extensions, note that the queue-addremove macro is used
343 to actually add or remove the agent from the applicable queue,
344 with the applicable priority level. Note that agents with a
345 priority level of 10 will be called before agents with levels
346 of 20 or 30.
347
348 In the above example, Raquel will be dialed first in the dispatch
349 queue, if she has logged in. If she is not, then the second call of
350 Queue() with priority of 20 will dial Brittanica if she is present,
351 otherwise the third call of Queue() with MAX\_PENALTY of 0 will
352 dial Rock and Saline simultaneously.
353
354 Also note that Rock will be among the first to be called in the sales-general
355 queue, and among the last in the dispatch queue. As you can see in
356 main menu, the callerID is set in the main menu so they can tell
357 which queue incoming calls are coming from.
358
359 The call to queue-success() gives some feedback to the agent
360 as they log in and out, that the process has completed.
361
362 \begin{astlisting}
363 \begin{verbatim}
364 macro queue-success(exten)
365 {
366         if( ${queue-announce-success} > 0 )
367         {
368                 switch(${exten:0:1})
369                 {
370                 case I:
371                         Playback(agent-loginok);
372                         Hangup();
373                 case O:
374                         Playback(agent-loggedoff);
375                         Hangup();
376                 }
377         }
378 }
379 \end{verbatim}
380 \end{astlisting}
381
382 The queue-addremove macro is defined in this manner:
383
384 \begin{astlisting}
385 \begin{verbatim}
386 macro queue-addremove(queuename,penalty,exten)
387 {
388         switch(${exten:0:1})
389         {
390         case I:  // Login
391                 {
392                  AddQueueMember(${queuename},Local/${exten:1}@agents,${penalty});
393                  break;
394                 }
395         case O:  // Logout
396                 {
397                  RemoveQueueMember(${queuename},Local/${exten:1}@agents);
398                  break;
399                 }
400         case P:  // Pause
401                 {
402                  PauseQueueMember(${queuename},Local/${exten:1}@agents);
403                  break;
404                 }
405         case U:  // Unpause
406                 {
407                  UnpauseQueueMember(${queuename},Local/${exten:1}@agents);
408                  break;
409                 }
410         default: // Invalid
411                 {
412                  Playback(invalid);
413                 }
414         }
415 }
416 \end{verbatim}
417 \end{astlisting}
418
419 Basically, it uses the first character of the exten variable, to determine the
420 proper actions to take. In the above dial plan code, only the cases I or O are used,
421 which correspond to the Login and Logout actions.
422
423
424 \subsection{Controlling The Way Queues Call the Agents}
425
426 Notice in the above, that the commands to manipulate agents in queues have
427 "@agents" in their arguments. This is a reference to the agents context:
428
429 \begin{astlisting}
430 \begin{verbatim}
431 context agents
432 {
433         // General sales queue
434         8010 =>
435         {
436                 Set(QUEUE_MAX_PENALTY=10);
437                 Queue(sales-general,t);
438                 Set(QUEUE_MAX_PENALTY=0);
439                 Queue(sales-general,t);
440                 Set(CALLERID(name)=EmptySalQ);
441                 goto dispatch,s,1;
442         }
443         // Customer Service queue
444         8011 =>
445         {
446                 Set(QUEUE_MAX_PENALTY=10);
447                 Queue(customerservice,t);
448                 Set(QUEUE_MAX_PENALTY=0);
449                 Queue(customerservice,t);
450                 Set(CALLERID(name)=EMptyCSVQ);
451                 goto dispatch,s,1;
452         }
453         8013 =>
454         {
455                 Dial(iax2/sweatshop/9456@from-ecstacy);
456
457                 Set(CALLERID(name)=EmptySupQ);
458                 Set(QUEUE_MAX_PENALTY=10);
459                 Queue(support-dispatch,t);
460                 Set(QUEUE_MAX_PENALTY=20);
461                 Queue(support-dispatch,t);
462                 Set(QUEUE_MAX_PENALTY=0); // means no max
463                 Queue(support-dispatch,t);
464                 goto dispatch,s,1;
465         }
466         6121 => &callagent(${RAQUEL},${EXTEN});
467         6165 => &callagent(${SPEARS},${EXTEN});
468         6170 => &callagent(${ROCK},${EXTEN});
469         6070 => &callagent(${SALINE},${EXTEN});
470 }
471 \end{verbatim}
472 \end{astlisting}
473
474 In the above, the variables \${RAQUEL}, etc stand for
475 actual devices to ring that person's
476 phone (like Zap/37).
477
478 The 8010, 8011, and 8013 extensions are purely for transferring
479 incoming callers to queues. For instance, a customer service
480 agent might want to transfer the caller to talk to sales. The
481 agent only has to transfer to extension 8010, in this case.
482
483 Here is the callagent macro, note that if a person in the
484 queue is called, but does not answer, then they are automatically
485 removed from the queue.
486
487 \begin{astlisting}
488 \begin{verbatim}
489 macro callagent(device,exten)
490 {
491         if( ${GROUP_COUNT(${exten}@agents)}=0 )
492         {
493                 Set(OUTBOUND_GROUP=${exten}@agents);
494                 Dial(${device},300,t);
495                 switch(${DIALSTATUS})
496                 {
497                 case BUSY:
498                         Busy();
499                         break;
500                 case NOANSWER:
501                         Set(queue-announce-success=0);
502                         goto queues-manip,O${exten},1;
503                 default:
504                         Hangup();
505                         break;
506                 }
507         }
508         else
509         {
510                 Busy();
511         }
512 }
513 \end{verbatim}
514 \end{astlisting}
515
516 In the callagent macro above, the \${exten} will
517 be 6121, or 6165, etc, which is the extension of the agent.
518
519 The use of the GROUP\_COUNT, and OUTBOUND\_GROUP follow this line
520 of thinking. Incoming calls can be queued to ring all agents in the
521 current priority. If some of those agents are already talking, they
522 would get bothersome call-waiting tones. To avoid this inconvenience,
523 when an agent gets a call, the OUTBOUND\_GROUP assigns that
524 conversation to the group specified, for instance 6171@agents.
525 The \${GROUP\_COUNT()} variable on a subsequent call should return
526 "1" for that group. If GROUP\_COUNT returns 1, then the busy()
527 is returned without actually trying to dial the agent.
528
529 \subsection{Pre Acknowledgement Message}
530
531 If you would like to have a pre acknowledge message with option to reject the message
532 you can use the following dialplan Macro as a base with the 'M' dial argument.
533
534 \begin{astlisting}
535 \begin{verbatim}
536 [macro-screen]
537 exten=>s,1,Wait(.25)
538 exten=>s,2,Read(ACCEPT,screen-callee-options,1)
539 exten=>s,3,Gotoif($[${ACCEPT} = 1] ?50)
540 exten=>s,4,Gotoif($[${ACCEPT} = 2] ?30)
541 exten=>s,5,Gotoif($[${ACCEPT} = 3] ?40)
542 exten=>s,6,Gotoif($[${ACCEPT} = 4] ?30:30)
543 exten=>s,30,Set(MACRO_RESULT=CONTINUE)
544 exten=>s,40,Read(TEXTEN,custom/screen-exten,)
545 exten=>s,41,Gotoif($[${LEN(${TEXTEN})} = 3]?42:45)
546 exten=>s,42,Set(MACRO_RESULT=GOTO:from-internal^${TEXTEN}^1)
547 exten=>s,45,Gotoif($[${TEXTEN} = 0] ?46:4)
548 exten=>s,46,Set(MACRO_RESULT=CONTINUE)
549 exten=>s,50,Playback(after-the-tone)
550 exten=>s,51,Playback(connected)
551 exten=>s,52,Playback(beep)
552 \end{verbatim}
553 \end{astlisting}
554
555 \subsection{Caveats}
556
557 In the above examples, some of the possible error checking has been omitted,
558 to reduce clutter and make the examples clearer.