REAL billsec (after agent connect)

Hello Everybody,

first, I wish you all a happy and peaceful new year. :slight_smile:

As many of you know, asterisk starts counting billsec time in moment when call is answered. In many of our cases, this is way before call gets into queue and is answered by live agent due to the need to interact with caller (ivr, dtmfs, …).

We bill only time that live agents spend on the line, so we’d need to amend the time asterisk/freepbx starts to count billsecs.

Reading on the forum (and internet) it seems as we might be able to achieve what we want by using a combo of

QGOSUB=ResetCDR4Queue,s,1
+
[ResetCDR4Queue]
exten => s,1,ResetCDR(v)
exten => s,n,Return()

… which is (to my understanding) supposed to do a reset of call disposition and billsecs in the moment call is connected to a queue member (live agent).

Does anyone has any experience with that? Any insight? Is there any downsides, any cleaner, better solutions?

I am using Freepbx 15.0.37.1. We’d like to omit reading from CEL / Queue Log.

Big thanks and best regards,
Andrej

I came to an almost working solution. Missing piece is a scenario where queue agent takes the call and transfers it to an external party. Billsecs are measured for the whole duration of call, all until external party or the original caller hangup. It should only measure it for the time of live agent being involved.

What I am unable to do is to add a time stamp or induce an h extention for that queue call when agent transfers the call and disconnects the line.

Bounty of 1000 USD for a nice, working solution.

Override the Queue Transfer Context, adding what you need:
Context for For Queue Transfer - FreePBX / Development - FreePBX Community Forums

Or

Make a new feature code for staff to use and map accordingly:
How I set up my feature codes - Asterisk / Asterisk Endpoints - Asterisk Community

Another thought, If the PBX is not anchoring the media, you could use a REFERR command to transfer the call off box, which would effectively end the call as soon as the transfer occurs. IF the PBX has to be the anchor, this would not work and drop the caller.

To each their own, but I would set a variable called QuStart and populate it with ${EPOCH}, then add to the transfer context a SetCDRUserField(${EPOCH}-${QuStart}). The CDR should give you the seconds of the queue call in the usr field.

Using a TRANSFER_CONTEXT seems to be a very good idea. Will give it a spin.

I am adding timestamp with epoch in QGOSUB and it providing the time of queue talk time fine.

What you want can be complex. I would create an AMI listener that waits for the agent_connect event which occurs when an agent answers a call. You could put that datetime value of that in a custom CDR fields and use that value for a agent_billsec (I would not change the billsec field.)

Hello Jerry,

please note that I already found an elegant way of adding a time stamp on agentconnect, through QGOSUB, using shared variable. I am then calculating the difference between timestamp at QGOSUB and hangup (via freepbx override config file), getting the time caller was in queue speaking to agents.

That works well.

What I didn’t cover and don’t have a solution for is a situation where agent transfers the answered queue call to external party. There is no hangup event when agent transfers the call and clears out of the conversation… so in effect my approach calculates the time wrongly = it takes whole duration of the call from the moment agent answere the call (correct) till the original caller or third party hang up (wrong).

With other words, when a customer calls (party A) and agent answers the phone (party B), then transfers the call to external number (party C), time is measured for the whole duration of the call, from the time party B answered till the time when either party A or party C hangs up the phone.

Fun fact, queue log also shows the whole duration of the call, until call with party C is hanged up.

I was toying with the ideas of using subroutines with dial, explored predial hooks, overriding transfer_context, using hangup handlers, but don’t know how to implement properly. I also don’t know enough about agis and ami listeners.

Any ideas, suggestions appreciated.

This is what I have so far if somebody can benefit:

globals_custom.conf

QGOSUB=EQueueCDRVariables

extenstions_override_freepbx.conf

[macro-hangupcall]
include => macro-hangupcall-custom
exten => s,1(start),GotoIf($[“${USE_CONFIRMATION}”=“” | “${RINGGROUP_INDEX}”=“” | “${CHANNEL}”!=“${UNIQCHAN}”]?theend)
exten => s,n(delrgi),Noop(Deleting: RG/${RINGGROUP_INDEX}/${CHANNEL} ${DB_DELETE(RG/${RINGGROUP_INDEX}/${CHANNEL})})
exten => s,n(theend),ExecIf($[“${ONETOUCH_RECFILE}”!=“” & “${CDR(recordingfile)}”=“”]?Set(CDR(recordingfile)=${ONETOUCH_RECFILE}))

;START CDR Mod
;OUTBOUND
exten => s,n,GotoIf($[“${DIRECTION}”!=“OUTBOUND”]?inbound)
exten => s,n,Set(CDR(EDisposition)=${DIALSTATUS})
exten => s,n,Set(CDR(EBilling)=$[${EPOCH}-${EAGENTCONNECTOUT}])
exten => s,n,Set(CDR(EAgent)=${FROMEXTEN})
exten => s,n,Set(CDR(EDirection)=${DIRECTION})
exten => s,n,Goto(myend)
;INBOUND
exten => s,n(inbound),GotoIf($[“${MACRO_CONTEXT}” != “ext-queues”]?myend)
exten => s,n,GotoIf($[“${ABANDONED}”=“TRUE”]?abandoned)
;queue answered
exten => s,n,Set(EQUEUEWAIT=$[${SHARED(EAGENTCONNECT)}-${QUEUEJOINTIME}])
exten => s,n,Set(CDR(EDisposition)=ANSWER)
exten => s,n,Set(CDR(EBilling)=$[${EPOCH}-${SHARED(EAGENTCONNECT)}])
exten => s,n,Set(CDR(EAgent)=${SHARED(EAGENT)})
exten => s,n,Goto(common)
;queue abandoned
exten => s,n(abandoned),Set(EQUEUEWAIT=$[${EPOCH}-${QUEUEJOINTIME}])
exten => s,n,Set(CDR(EDisposition)=ABANDON)
;queue common
exten => s,n(common),Set(CDR(EDirection)=${DIRECTION})
exten => s,n,Set(CDR(EQPos)=${QUEUEPOSITION})
exten => s,n,Set(CDR(EQWait)=${EQUEUEWAIT})
;end
exten => s,n(nyend),NoOp(End of CDR Mod)
;END CDR Mod

exten => s,n,Hangup
exten => s,n,MacroExit()

extensions_custom.conf

[macro-dialout-trunk-predial-hook]
exten => s,1,Set(DIRECTION=OUTBOUND)
exten => s,n,Set(EAGENTCONNECTOUT=${EPOCH})
exten => s,n(done),MacroExit()

[EQueueCDRVariables]
exten => s,1,NoOp
exten => s,n,Set(SHARED(EAGENTCONNECT,${MASTER_CHANNEL(CHANNEL)})=${EPOCH})
exten => s,n,Set(SHARED(EAGENT,${MASTER_CHANNEL(CHANNEL)})=${CUT(DIALEDPEERNUMBER,@,1)})
exten => s,n,Return()

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.