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