Automatically create new buddy upon reception of a presence stanza of
[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                         break;
374                 case O:
375                         Playback(agent-loggedoff);
376                         Hangup();
377                         break;
378                 }
379         }
380 }
381 \end{verbatim}
382 \end{astlisting}
383
384 The queue-addremove macro is defined in this manner:
385
386 \begin{astlisting}
387 \begin{verbatim}
388 macro queue-addremove(queuename,penalty,exten)
389 {
390         switch(${exten:0:1})
391         {
392         case I:  // Login
393                  AddQueueMember(${queuename},Local/${exten:1}@agents,${penalty});
394                  break;
395         case O:  // Logout
396                  RemoveQueueMember(${queuename},Local/${exten:1}@agents);
397                  break;
398         case P:  // Pause
399                  PauseQueueMember(${queuename},Local/${exten:1}@agents);
400                  break;
401         case U:  // Unpause
402                  UnpauseQueueMember(${queuename},Local/${exten:1}@agents);
403                  break;
404         default: // Invalid
405                  Playback(invalid);
406                  break;
407         }
408 }
409 \end{verbatim}
410 \end{astlisting}
411
412 Basically, it uses the first character of the exten variable, to determine the
413 proper actions to take. In the above dial plan code, only the cases I or O are used,
414 which correspond to the Login and Logout actions.
415
416
417 \subsection{Controlling The Way Queues Call the Agents}
418
419 Notice in the above, that the commands to manipulate agents in queues have
420 "@agents" in their arguments. This is a reference to the agents context:
421
422 \begin{astlisting}
423 \begin{verbatim}
424 context agents
425 {
426         // General sales queue
427         8010 =>
428         {
429                 Set(QUEUE_MAX_PENALTY=10);
430                 Queue(sales-general,t);
431                 Set(QUEUE_MAX_PENALTY=0);
432                 Queue(sales-general,t);
433                 Set(CALLERID(name)=EmptySalQ);
434                 goto dispatch,s,1;
435         }
436         // Customer Service queue
437         8011 =>
438         {
439                 Set(QUEUE_MAX_PENALTY=10);
440                 Queue(customerservice,t);
441                 Set(QUEUE_MAX_PENALTY=0);
442                 Queue(customerservice,t);
443                 Set(CALLERID(name)=EMptyCSVQ);
444                 goto dispatch,s,1;
445         }
446         8013 =>
447         {
448                 Dial(iax2/sweatshop/9456@from-ecstacy);
449
450                 Set(CALLERID(name)=EmptySupQ);
451                 Set(QUEUE_MAX_PENALTY=10);
452                 Queue(support-dispatch,t);
453                 Set(QUEUE_MAX_PENALTY=20);
454                 Queue(support-dispatch,t);
455                 Set(QUEUE_MAX_PENALTY=0); // means no max
456                 Queue(support-dispatch,t);
457                 goto dispatch,s,1;
458         }
459         6121 => &callagent(${RAQUEL},${EXTEN});
460         6165 => &callagent(${SPEARS},${EXTEN});
461         6170 => &callagent(${ROCK},${EXTEN});
462         6070 => &callagent(${SALINE},${EXTEN});
463 }
464 \end{verbatim}
465 \end{astlisting}
466
467 In the above, the variables \$\{RAQUEL\}, etc stand for
468 actual devices to ring that person's
469 phone (like Zap/37).
470
471 The 8010, 8011, and 8013 extensions are purely for transferring
472 incoming callers to queues. For instance, a customer service
473 agent might want to transfer the caller to talk to sales. The
474 agent only has to transfer to extension 8010, in this case.
475
476 Here is the callagent macro, note that if a person in the
477 queue is called, but does not answer, then they are automatically
478 removed from the queue.
479
480 \begin{astlisting}
481 \begin{verbatim}
482 macro callagent(device,exten)
483 {
484         if( ${GROUP_COUNT(${exten}@agents)}=0 )
485         {
486                 Set(OUTBOUND_GROUP=${exten}@agents);
487                 Dial(${device},300,t);
488                 switch(${DIALSTATUS})
489                 {
490                 case BUSY:
491                         Busy();
492                         break;
493                 case NOANSWER:
494                         Set(queue-announce-success=0);
495                         goto queues-manip,O${exten},1;
496                 default:
497                         Hangup();
498                         break;
499                 }
500         }
501         else
502         {
503                 Busy();
504         }
505 }
506 \end{verbatim}
507 \end{astlisting}
508
509 In the callagent macro above, the \$\{exten\} will
510 be 6121, or 6165, etc, which is the extension of the agent.
511
512 The use of the GROUP\_COUNT, and OUTBOUND\_GROUP follow this line
513 of thinking. Incoming calls can be queued to ring all agents in the
514 current priority. If some of those agents are already talking, they
515 would get bothersome call-waiting tones. To avoid this inconvenience,
516 when an agent gets a call, the OUTBOUND\_GROUP assigns that
517 conversation to the group specified, for instance 6171@agents.
518 The \$\{GROUP\_COUNT()\} variable on a subsequent call should return
519 "1" for that group. If GROUP\_COUNT returns 1, then the busy()
520 is returned without actually trying to dial the agent.
521
522 \subsection{Pre Acknowledgement Message}
523
524 If you would like to have a pre acknowledge message with option to reject the message
525 you can use the following dialplan Macro as a base with the 'M' dial argument.
526
527 \begin{astlisting}
528 \begin{verbatim}
529 [macro-screen]
530 exten=>s,1,Wait(.25)
531 exten=>s,2,Read(ACCEPT,screen-callee-options,1)
532 exten=>s,3,Gotoif($[${ACCEPT} = 1] ?50)
533 exten=>s,4,Gotoif($[${ACCEPT} = 2] ?30)
534 exten=>s,5,Gotoif($[${ACCEPT} = 3] ?40)
535 exten=>s,6,Gotoif($[${ACCEPT} = 4] ?30:30)
536 exten=>s,30,Set(MACRO_RESULT=CONTINUE)
537 exten=>s,40,Read(TEXTEN,custom/screen-exten,)
538 exten=>s,41,Gotoif($[${LEN(${TEXTEN})} = 3]?42:45)
539 exten=>s,42,Set(MACRO_RESULT=GOTO:from-internal^${TEXTEN}^1)
540 exten=>s,45,Gotoif($[${TEXTEN} = 0] ?46:4)
541 exten=>s,46,Set(MACRO_RESULT=CONTINUE)
542 exten=>s,50,Playback(after-the-tone)
543 exten=>s,51,Playback(connected)
544 exten=>s,52,Playback(beep)
545 \end{verbatim}
546 \end{astlisting}
547
548 \subsection{Caveats}
549
550 In the above examples, some of the possible error checking has been omitted,
551 to reduce clutter and make the examples clearer.