I put together a quick hack last night that will help with managing truant accounts on JKL5’s “Cloudphones” SMB VoIP PBX. Ostensibly, it’s a pre-paid service for small to medium businesses, as well as a couple of residential customers. However, we have a couple of problem accounts that require checking on the accounts payable report followed by a few nagging emails to get to pay their bills at the 45 day mark.
In each trunk and phone configuration, I have the customer’s company name set as the “Account Code” for any call they take or make. In an IAX2 trunk, it looks like this:
[example_incoming_trunk]
type=user
host=iax04.unlimitel.ca
username=1112223333
context=call_router
requirecalltoken=yes
accountcode=jkl5group
[example_outgoing_trunk]
type=peer
host=edge01.my_itsp.com
secret=some9797numbers
username=1112223333
accountcode=jkl5group
With something like a SIP phone, it’s just as easy:
[extension.5150.sip]
type=friend
secret=some7634secret
context=dialing_privledged
subscribecontext=devices_list
callerid=John Doe <5150>
mailbox=5150@jkl5group_com
host=dynamic
nat=yes
canreinvite=no
dtmfmode=RFC2833
disallow=all
allow=ulaw
allow=alaw
allow=gsm
language=en
;
qualify=yes
accountcode=jkl5group
So, when a call either comes or goes, we can recover the account call from the CDR data from the call, even as the call is progressing. An Asterisk dialplan example might look like:
[accounting_system_check] exten => s,1, NoOp(... Checking account status for [${CDR(accountcode)}] ) same => n, Set(__account_status=${SHELL(/opt/ check_account.rb ${CDR(accountcode)} )}) same => n, NoOp("Accounting: account_status is ${account_status}") same => n, Return()
“check_account.rb” uses the “ruby-freshbooks” Gem to open an API connection to the FreshBooks server. It pulls a list of “Cloudphones” customers, finds the customer ID # based on the name it is sent and then checks to see if there are invoices more than 30 days old and unpaid for that customer. It then returns a status indicator that can be used to make a “yes” or “no” decision if the customer’s call service needs to be impacted due to a truant account.
Note that the double-underscore at the start of the variable name means that the variable is kept and passed on from one context to another, so it is always accessible during the call.
Within the dialplan, code similar to the following before the call is delivered to the extension or to the outgoing trunk does the job:
same => n, Gosub(accounting_system_check,s,1) same => n, GotoIf($["${account_status}" = "OVERDUE"]?account_restricted,1)
Naturally, “account_restricted” should do something valuable, such as inform the outgoing caller about their account status, or send an incoming call directly to voicemail. Using a “Gosub()” avoids repeating the check code across multiple contexts
The best part about all of this is that as soon as the over due invoices are marked paid on FreshBooks, such as an online payment via credit card or PayPal, then the next call coming in or going out gets the “Green Light” and call flow behavior is normal.
We don’t have to waste time policing our Cloudphones accounts recievables, and we leverage a great functionality provided by FreshBooks. The customer status is always up to date, as fast as the payment arrives. It’s a “win” all the way around.