app_queue: Add QueueUpdate application.
authorSebastian Gutierrez <sgutierrez@integraccs.com>
Sun, 6 Nov 2016 12:30:07 +0000 (09:30 -0300)
committerJoshua Colp <jcolp@digium.com>
Tue, 17 Jan 2017 12:29:34 +0000 (12:29 +0000)
Add an application that allows tracking outbound calls
using app_queue.

ASTERISK-19862

Change-Id: Ia0ab64aed934c25b2a25022adcc7c0624224346e

CHANGES
apps/app_queue.c

diff --git a/CHANGES b/CHANGES
index d843848..5921e9b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -74,6 +74,11 @@ CLI Commands
    [registrar] when that information is available. Currently only extensions
    registered by pbx_config when loading/reloading will use this format.
 
+app_queue
+------------------
+ * Add 'QueueUpdate' application which can be used to track outbound calls
+   using app_queue.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.2.0 to Asterisk 14.3.0 ------------
 ------------------------------------------------------------------------------
index 9176f93..9b3912f 100644 (file)
                        <ref type="function">QUEUE_MEMBER_PENALTY</ref>
                </see-also>
        </application>
+       <application name="QueueUpdate" language="en_US">
+               <synopsis>
+                       Writes to the queue_log file for OutBound calls and updates Realtime Data.
+            Is used at h extension to be able to have all the parameters.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+                       <parameter name="uniqueid" required="true" />
+                       <parameter name="agent" required="true" />
+                       <parameter name="status" required="true" />
+            <parameter name="talktime" required="true" />
+            <parameter name="params" required="false" />
+               </syntax>
+               <description>
+                       <para>Allows you to write Outbound events into the queue log.</para>
+                       <para>Example: exten => h,1,QueueUpdate(${QUEUE}, ${UNIQUEID}, ${AGENT}, ${DIALSTATUS}, ${ANSWEREDTIME}, ${DIALEDTIME} | ${DIALEDNUMBER})</para>
+               </description>
+       </application>
        <function name="QUEUE_VARIABLES" language="en_US">
                <synopsis>
                        Return Queue information in variables.
@@ -1403,6 +1421,8 @@ static char *app_upqm = "UnpauseQueueMember" ;
 
 static char *app_ql = "QueueLog" ;
 
+static char *app_qupd = "QueueUpdate";
+
 /*! \brief Persistent Members astdb family */
 static const char * const pm_family = "Queue/PersistentMembers";
 
@@ -10703,6 +10723,86 @@ static char *handle_queue_reload(struct ast_cli_entry *e, int cmd, struct ast_cl
        return CLI_SUCCESS;
 }
 
+/*!
+ * \brief Update Queue with data of an outgoing call
+*/
+static int qupd_exec(struct ast_channel *chan, const char *data)
+{
+       int oldtalktime;
+       char *parse;
+       struct call_queue *q;
+       struct member *mem;
+       int newtalktime = 0;
+
+       AST_DECLARE_APP_ARGS(args,
+                       AST_APP_ARG(queuename);
+                       AST_APP_ARG(uniqueid);
+                       AST_APP_ARG(agent);
+                       AST_APP_ARG(status);
+                       AST_APP_ARG(talktime);
+                       AST_APP_ARG(params););
+
+       if (ast_strlen_zero(data)) {
+               ast_log(LOG_WARNING, "QueueUpdate requires arguments (queuename,uniqueid,agent,status,talktime,params[totaltime,callednumber])\n");
+               return -1;
+       }
+
+       parse = ast_strdupa(data);
+
+       AST_STANDARD_APP_ARGS(args, parse);
+
+       if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.uniqueid) || ast_strlen_zero(args.agent) || ast_strlen_zero(args.status)) {
+               ast_log(LOG_WARNING, "Missing argument to QueueUpdate (queuename,uniqueid,agent,status,talktime,params[totaltime|callednumber])\n");
+               return -1;
+       }
+
+       if (!ast_strlen_zero(args.talktime)) {
+               newtalktime = atoi(args.talktime);
+       }
+
+       q = find_load_queue_rt_friendly(args.queuename);
+       if (!q) {
+               ast_log(LOG_WARNING, "QueueUpdate could not find requested queue '%s'\n", args.queuename);
+               return 0;
+       }
+
+       ao2_lock(q);
+       if (q->members) {
+               struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
+               while ((mem = ao2_iterator_next(&mem_iter))) {
+                       if (!strcasecmp(mem->membername, args.agent)) {
+                               if (!strcasecmp(args.status, "ANSWER")) {
+                                       oldtalktime = q->talktime;
+                                       q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
+                                       time(&mem->lastcall);
+                                       mem->calls++;
+                                       mem->lastqueue = q;
+                                       q->callscompleted++;
+
+                                       if (newtalktime <= q->servicelevel) {
+                                               q->callscompletedinsl++;
+                                       }
+                               } else {
+
+                                       time(&mem->lastcall);
+                                       q->callsabandoned++;
+                               }
+
+                               ast_queue_log(args.queuename, args.uniqueid, args.agent, "OUTCALL", "%s|%s|%s", args.status, args.talktime, args.params);
+                       }
+
+                       ao2_ref(mem, -1);
+               }
+
+               ao2_iterator_destroy(&mem_iter);
+       }
+
+       ao2_unlock(q);
+       queue_t_unref(q, "Done with temporary pointer");
+
+       return 0;
+}
+
 static struct ast_cli_entry cli_queue[] = {
        AST_CLI_DEFINE(queue_show, "Show status of a specified queue"),
        AST_CLI_DEFINE(handle_queue_rule_show, "Show the rules defined in queuerules.conf"),
@@ -11020,6 +11120,7 @@ static int unload_module(void)
        ast_manager_unregister("QueueRemove");
        ast_manager_unregister("QueuePause");
        ast_manager_unregister("QueueLog");
+       ast_manager_unregister("QueueUpdate");
        ast_manager_unregister("QueuePenalty");
        ast_manager_unregister("QueueReload");
        ast_manager_unregister("QueueReset");
@@ -11029,6 +11130,7 @@ static int unload_module(void)
        ast_unregister_application(app_pqm);
        ast_unregister_application(app_upqm);
        ast_unregister_application(app_ql);
+       ast_unregister_application(app_qupd);
        ast_unregister_application(app);
        ast_custom_function_unregister(&queueexists_function);
        ast_custom_function_unregister(&queuevar_function);
@@ -11128,6 +11230,7 @@ static int load_module(void)
        err |= ast_register_application_xml(app_pqm, pqm_exec);
        err |= ast_register_application_xml(app_upqm, upqm_exec);
        err |= ast_register_application_xml(app_ql, ql_exec);
+       err |= ast_register_application_xml(app_qupd, qupd_exec);
        err |= ast_manager_register_xml("Queues", 0, manager_queues_show);
        err |= ast_manager_register_xml("QueueStatus", 0, manager_queues_status);
        err |= ast_manager_register_xml("QueueSummary", 0, manager_queues_summary);