<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/7460">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Richard Mudgett: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_queue: Add feature to set wrapuptime on the queue member<br><br>This patch adds the ability to set the wrapuptime on the queue member<br>config.<br><br>When the option is set the wrapuptime on the queue member is used instead<br>of the queue's wrapuptime.<br><br>ASTERISK-27483 #close<br><br>Change-Id: I11c85809537f974eb44dc5bbf82bcedd8a458902<br>---<br>M CHANGES<br>M apps/app_queue.c<br>M configs/samples/queues.conf.sample<br>A contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py<br>4 files changed, 88 insertions(+), 8 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/CHANGES b/CHANGES<br>index bd1ca67..bd11c6c 100644<br>--- a/CHANGES<br>+++ b/CHANGES<br>@@ -37,6 +37,12 @@<br> * The ContactInfo event's contact_status field is now set to "NonQualified"<br> when a contact exists but has not been qualified.<br> <br>+app_queue<br>+------------------<br>+ * Added the ability to set the wrapuptime in the configuration of member.<br>+ When set the wrapuptime on the member is used instead of the wrapuptime<br>+ defined for the queue itself.<br>+<br> ------------------------------------------------------------------------------<br> --- Functionality changes from Asterisk 15.1.0 to Asterisk 15.2.0 ------------<br> ------------------------------------------------------------------------------<br>diff --git a/apps/app_queue.c b/apps/app_queue.c<br>index a140847..af8b3b8 100644<br>--- a/apps/app_queue.c<br>+++ b/apps/app_queue.c<br>@@ -1,7 +1,7 @@<br> /*<br> * Asterisk -- An open source telephony toolkit.<br> *<br>- * Copyright (C) 1999 - 2016, Digium, Inc.<br>+ * Copyright (C) 1999 - 2017, Digium, Inc.<br> *<br> * Mark Spencer <markster@digium.com><br> *<br>@@ -1586,6 +1586,7 @@<br> char reason_paused[80]; /*!< Reason of paused if member is paused */<br> int queuepos; /*!< In what order (pertains to certain strategies) should this member be called? */<br> int callcompletedinsl; /*!< Whether the current call was completed within service level */<br>+ int wrapuptime; /*!< Wrapup Time */<br> time_t starttime; /*!< The time at which the member answered the current caller. */<br> time_t lastcall; /*!< When last successful call was hungup */<br> time_t lastpause; /*!< When started the last pause */<br>@@ -1824,6 +1825,21 @@<br> {<br> struct call_queue *q = obj, *q2 = arg;<br> return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;<br>+}<br>+<br>+/*!<br>+ * \brief Return wrapuptime<br>+ *<br>+ * This function checks if wrapuptime in member is set and return this value.<br>+ * Otherwise return value the wrapuptime in the queue configuration<br>+ * \return integer value<br>+ */<br>+static int get_wrapuptime(struct call_queue *q, struct member *member)<br>+{<br>+ if (member->wrapuptime) {<br>+ return member->wrapuptime;<br>+ }<br>+ return q->wrapuptime;<br> }<br> <br> /*! \internal<br>@@ -2309,8 +2325,12 @@<br> if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {<br> ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);<br> break;<br>- } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {<br>- ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);<br>+ } else if ((conditions & QUEUE_EMPTY_WRAPUP)<br>+ && member->lastcall<br>+ && get_wrapuptime(q, member)<br>+ && (time(NULL) - get_wrapuptime(q, member) < member->lastcall)) {<br>+ ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n",<br>+ member->membername, (int) (time(NULL) - member->lastcall), get_wrapuptime(q, member));<br> break;<br> } else {<br> ao2_ref(member, -1);<br>@@ -2436,6 +2456,7 @@<br> static int is_member_available(struct call_queue *q, struct member *mem)<br> {<br> int available = 0;<br>+ int wrapuptime;<br> <br> switch (mem->status) {<br> case AST_DEVICE_INVALID:<br>@@ -2459,7 +2480,8 @@<br> }<br> <br> /* Let wrapuptimes override device state availability */<br>- if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) {<br>+ wrapuptime = get_wrapuptime(q, mem);<br>+ if (mem->lastcall && wrapuptime && (time(NULL) - wrapuptime < mem->lastcall)) {<br> available = 0;<br> }<br> return available;<br>@@ -3354,6 +3376,7 @@<br> int penalty = 0;<br> int paused = 0;<br> int found = 0;<br>+ int wrapuptime = 0;<br> int ringinuse = q->ringinuse;<br> <br> const char *config_val;<br>@@ -3363,6 +3386,7 @@<br> const char *state_interface = S_OR(ast_variable_retrieve(member_config, category, "state_interface"), interface);<br> const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty");<br> const char *paused_str = ast_variable_retrieve(member_config, category, "paused");<br>+ const char *wrapuptime_str = ast_variable_retrieve(member_config, category, "wrapuptime");<br> <br> if (ast_strlen_zero(rt_uniqueid)) {<br> ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));<br>@@ -3382,6 +3406,13 @@<br> paused = atoi(paused_str);<br> if (paused < 0) {<br> paused = 0;<br>+ }<br>+ }<br>+<br>+ if (wrapuptime_str) {<br>+ wrapuptime = atoi(wrapuptime_str);<br>+ if (wrapuptime < 0) {<br>+ wrapuptime = 0;<br> }<br> }<br> <br>@@ -3411,6 +3442,7 @@<br> }<br> m->penalty = penalty;<br> m->ringinuse = ringinuse;<br>+ m->wrapuptime = wrapuptime;<br> found = 1;<br> ao2_ref(m, -1);<br> break;<br>@@ -4343,6 +4375,8 @@<br> */<br> static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)<br> {<br>+ int wrapuptime;<br>+<br> if (call->member->paused) {<br> ast_debug(1, "%s paused, can't receive call\n", call->interface);<br> return 0;<br>@@ -4353,8 +4387,12 @@<br> return 0;<br> }<br> <br>- if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))<br>- || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {<br>+ if (call->lastqueue) {<br>+ wrapuptime = get_wrapuptime(call->lastqueue, call->member);<br>+ } else {<br>+ wrapuptime = get_wrapuptime(qe->parent, call->member);<br>+ }<br>+ if (wrapuptime && time(NULL) - call->lastcall < wrapuptime) {<br> ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",<br> (call->lastqueue ? call->lastqueue->name : qe->parent->name),<br> call->interface);<br>@@ -8554,7 +8592,7 @@<br> while ((m = ao2_iterator_next(&mem_iter))) {<br> /* Count the agents who are logged in, not paused and not wrapping up */<br> if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused) &&<br>- !(m->lastcall && q->wrapuptime && ((now - q->wrapuptime) < m->lastcall))) {<br>+ !(m->lastcall && get_wrapuptime(q, m) && ((now - get_wrapuptime(q, m)) < m->lastcall))) {<br> count++;<br> }<br> ao2_ref(m, -1);<br>@@ -9098,12 +9136,14 @@<br> struct member tmpmem;<br> int penalty;<br> int ringinuse;<br>+ int wrapuptime;<br> AST_DECLARE_APP_ARGS(args,<br> AST_APP_ARG(interface);<br> AST_APP_ARG(penalty);<br> AST_APP_ARG(membername);<br> AST_APP_ARG(state_interface);<br> AST_APP_ARG(ringinuse);<br>+ AST_APP_ARG(wrapuptime);<br> );<br> <br> if (ast_strlen_zero(memberdata)) {<br>@@ -9158,11 +9198,23 @@<br> ringinuse = q->ringinuse;<br> }<br> <br>+ if (!ast_strlen_zero(args.wrapuptime)) {<br>+ tmp = args.wrapuptime;<br>+ ast_strip(tmp);<br>+ wrapuptime = atoi(tmp);<br>+ if (wrapuptime < 0) {<br>+ wrapuptime = 0;<br>+ }<br>+ } else {<br>+ wrapuptime = 0;<br>+ }<br>+<br> /* Find the old position in the list */<br> ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));<br> cur = ao2_find(q->members, &tmpmem, OBJ_POINTER);<br> <br> if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse))) {<br>+ newm->wrapuptime = wrapuptime;<br> if (cur) {<br> /* Round Robin Queue Position must be copied if this is replacing an existing member */<br> ao2_lock(q->members);<br>diff --git a/configs/samples/queues.conf.sample b/configs/samples/queues.conf.sample<br>index 3e7cbd8..226a3a9 100644<br>--- a/configs/samples/queues.conf.sample<br>+++ b/configs/samples/queues.conf.sample<br>@@ -551,7 +551,7 @@<br> ; must also preload pbx_config.so and chan_local.so (or pbx_ael.so, pbx_lua.so,<br> ; or pbx_realtime.so, depending on how your dialplan is configured).<br> ;<br>-; syntax: member => interface,[,penalty][,membername][,state_interface][,ringinuse]<br>+; syntax: member => interface,[,penalty][,membername][,state_interface][,ringinuse][,wrapuptime]<br> ;<br> ;member => DAHDI/1<br> ;member => DAHDI/2,10<br>diff --git a/contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py b/contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py<br>new file mode 100644<br>index 0000000..fdb1416<br>--- /dev/null<br>+++ b/contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py<br>@@ -0,0 +1,22 @@<br>+"""add wrapuptime to queue_members<br>+<br>+Revision ID: e2f04d309071<br>+Revises: 041c0d3d1857<br>+Create Date: 2017-12-07 08:32:45.360857<br>+<br>+"""<br>+<br>+# revision identifiers, used by Alembic.<br>+revision = 'e2f04d309071'<br>+down_revision = '041c0d3d1857'<br>+<br>+from alembic import op<br>+import sqlalchemy as sa<br>+<br>+<br>+def upgrade():<br>+ op.add_column('queue_members', sa.Column('wrapuptime', sa.Integer))<br>+<br>+<br>+def downgrade():<br>+ op.drop_column('queue_members', 'wrapuptime')<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7460">change 7460</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7460"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I11c85809537f974eb44dc5bbf82bcedd8a458902 </div>
<div style="display:none"> Gerrit-Change-Number: 7460 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: Rodrigo Ramirez Norambuena <a@rodrigoramirez.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Rodrigo Ramirez Norambuena <a@rodrigoramirez.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sean Bright <sean.bright@gmail.com> </div>