This piece of dialplan should be final and address all concerns.
[queuedial]
; this piece of dialplan is just a calling hook into the [qm-queuedial] context that actually does the
; outbound dialing - replace as needed - just fill in the same variables.
exten => _XXX.,1,Set(QDIALER_QUEUE=q-${EXTEN:0:3})
exten => _XXX.,n,Set(QDIALER_NUMBER=${EXTEN:3})
exten => _XXX.,n,Set(QDIALER_AGENT=Agent/${CALLERID(num)})
exten => _XXX.,n,Set(QDIALER_CHANNEL=SIP/${QDIALER_NUMBER})
exten => _XXX.,n,Set(QueueName=${QDIALER_QUEUE})
exten => _XXX.,n,MixMonitor(Q-${QDIALER_QUEUE}-${UNIQUEID}.WAV|b|)
exten => _XXX.,n,Goto(qm-queuedial,s,1)
[qm-queuedial]
; We use a global variable to pass values back from the answer-detect macro.
; STATUS = U unanswered
; = A answered (plus CAUSECOMPLETE=C when callee hung up)
; The 'g' dial parameter must be used in order to track callee disconnecting.
; Note that we'll be using the 'h' hook in any case to do the logging when channels go down.
; We set the CDR(accountcode) for live monitoring by QM.
;
exten => s,1,NoOp,Outbound call -> A:${QDIALER_AGENT} N:${QDIALER_NUMBER} Q:${QDIALER_QUEUE} Ch:${QDIALER_CHANNEL}
exten => s,n,Set(CDR(accountcode)=QDIALAGI)
exten => s,n,Set(ST=${EPOCH})
exten => s,n,Set(GM=QDV-${QDIALER_AGENT})
exten => s,n,Set(GLOBAL(${GM})=U)
exten => s,n,Set(GLOBAL(${GM}ans)=0)
exten => s,n,Macro(queuelog,${ST},${UNIQUEID},${QDIALER_QUEUE},${QDIALER_AGENT},ENTERQUEUE,-,${QDIALER_NUMBER})
exten => s,n,Dial(${QDIALER_CHANNEL},30,gM(queuedial-answer^${UNIQUEID}^${GM}^${QDIALER_QUEUE}^${QDIALER_AGENT}^${ST}))
exten => s,n,Set(CAUSECOMPLETE=${IF($["${DIALSTATUS}" = "ANSWER"]?C)})
; Trapping call termination here
exten => h,1,NoOp( "Call exiting: status ${GLOBAL(${GM})} answered at: ${GLOBAL(${GM}ans)} DS: ${DIALSTATUS}" )
exten => h,n,Goto(case-${GLOBAL(${GM})})
exten => h,n,Hangup()
; Call unanswered
exten => h,n(case-U),Set(WT=$[${EPOCH} - ${ST}])
exten => h,n,Macro(queuelog,${EPOCH},${UNIQUEID},${QDIALER_QUEUE},${QDIALER_AGENT},ABANDON,1,1,${WT})
exten => h,n,Hangup()
; call answered: agent/callee hung
exten => h,n(case-A),Set(COMPLETE=${IF($["${CAUSECOMPLETE}" = "C"]?COMPLETECALLER:COMPLETEAGENT)})
exten => h,n,Set(WT=$[${GLOBAL(${GM}ans)} - ${ST}])
exten => h,n,Set(CT=$[${EPOCH} - ${GLOBAL(${GM}ans)}])
exten => h,n,Macro(queuelog,${EPOCH},${UNIQUEID},${QDIALER_QUEUE},${QDIALER_AGENT},${COMPLETE},${WT},${CT})
exten => h,n,Hangup()
[macro-queuedial-answer]
; Expecting $ARG1: uniqueid of the caller channel
; $ARG2: global variable to store the answer results
; $ARG3: queue name
; $ARG4: agent name
; $ARG5: enterqueue
;
exten => s,1,NoOp("Macro: queuedial-answer UID:${ARG1} GR:${ARG2} Q:${ARG3} A:${ARG4} E:${ARG5}")
exten => s,n,Set(NOW=${EPOCH})
exten => s,n,Set(WD=$[${NOW} - ${ARG5}])
exten => s,n,Macro(queuelog,${NOW},${ARG1},${ARG3},${ARG4},CONNECT,${WD})
exten => s,n,Set(GLOBAL(${ARG2})=A)
exten => s,n,Set(GLOBAL(${ARG2}ans)=${NOW})
exten => s,n,NoOp("Macro queuedial-answer terminating" )
[macro-queuelog]
; The advantage of using this macro is that you can choose whether to use the Shell version
; (where you have complete control of what gets written) or the Application version (where you
; do not need a shellout, so it's way faster).
;
; Expecting $ARG1: Timestamp
; $ARG2: Call-id
; $ARG3: Queue
; $ARG4: Agent
; $ARG5: Verb
; $ARG6: Param1
; $ARG7: Param2
; $ARG8: Param3
;
;exten => s,1,System( echo "${ARG1}|${ARG2}|${ARG3|${ARG4}|${ARG5}|${ARG6}|${ARG7}|${ARG8}" >> /var/log/asterisk/queue_log )
exten => s,1,QueueLog(${ARG3},${ARG2},${ARG4},${ARG5},${ARG6}|${ARG7}|${ARG8})
Please note we separated the [queuedial] context that prepares parameters, sets call recordings, etc., from the [qm-queuedial] context, that is the actual workhorse doing the calling and the logging. This makes it easy for you to change the calling parameters if you need to do so.
We now use a macro for logging so that you can easily switch between using the QueueLog asterisk application (way faster, but the timestamp is implicit, so it might be a second after the call completed) versus the standard echo to shellout. This also makes the code cleaner and neater.
We mark outbound calls under the CDR account code of QDIALAGI. This is needed for QueueMetrics to know that those channels are not "regular" channels but are actually outgoing calls and need to be shown as such on the Live page. If you se third-party CDR processing apps, you might need to configure them to accept this change.
We changed the function parameters to use commas instead of pipes, so we expect this to be compatible with 1.6 as well.
Overall, we expect this code to be quite an advancement in terms of speed, ease of setup and configuration and reporting over the old QueueDial.agi script, so using this pure.dialplan solution will be the preferred way to implement outbound campaigns in QM 1.4.5.