Added new PRESS_CALLBACK_QUEUE option to Hold Time and Wait Time In-Group settings, allowing for a customer to retain their place in line in the queue and be called back when their turn is reached.

Added new Closed Time features to In-Groups that allow all calls in queue to be presented with an option when the in-group closing time for the day has been reached. Also, an option was added to manually force the end of all queueing of calls for an in-group for the day.
Added dial_ingroup option to Agent API external_dial function.
Added In-Group option to look up timezone of customer when a new lead is added during the routing of the call.

git-svn-id: svn://192.168.202.10@2905 3d104415-ff17-0410-8863-d5cf3c621b8a
This commit is contained in:
mattf
2018-02-07 04:48:33 +00:00
parent a569a950d8
commit 4ab83a9e0c
16 changed files with 2904 additions and 81 deletions
+14
View File
@@ -253,6 +253,20 @@ OTHER CHANGES:
ready and waiting for phone calls from listed In-Groups before allowing
outbound auto-dialing.
67. Added new PRESS_CALLBACK_QUEUE option to Hold Time and Wait Time In-Group
settings, allowing for a customer to retain their place in line in the
queue and be called back when their turn is reached.
68. Added new Closed Time features to In-Groups that allow all calls in queue
to be presented with an option when the in-group closing time for the
day has been reached. Also, an option was added to manually force the
end of all queueing of calls for an in-group for the day.
69. Added dial_ingroup option to Agent API external_dial function.
70. Added In-Group option to look up timezone of customer when a new lead is
added during the routing of the call.
File diff suppressed because it is too large Load Diff
+33 -2
View File
@@ -15,7 +15,7 @@
# - Auto reset lists at defined times
# - Auto restarts Asterisk process if enabled in servers settings
#
# Copyright (C) 2017 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
# Copyright (C) 2018 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES
# 61011-1348 - First build
@@ -126,9 +126,10 @@
# 170920-2214 - Added expired_lists_inactive option, checks once per hour
# 171010-2254 - Added process debug with --DebugXXX flag and screen logging
# 171221-1628 - Added rolling of vicidial_ingroup_hour_counts records
# 180204-0931 - Added rolling of vicidial_inbound_callback_queue records
#
$build = '171221-1628';
$build = '180204-0931';
$DB=0; # Debug flag
$teodDB=0; # flag to log Timeclock End of Day processes to log file
@@ -1371,6 +1372,36 @@ if ($timeclock_end_of_day_NOW > 0)
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
}
# roll of SENT/EXPIRED vicidial_inbound_callback_queue records
if (!$Q) {print "\nProcessing vicidial_inbound_callback_queue table...\n";}
$stmtA = "INSERT IGNORE INTO vicidial_inbound_callback_queue_archive SELECT * from vicidial_inbound_callback_queue where icbq_status IN('SENT','EXPIRED','DNCL','DNCC','ORPHAN');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows = $sthA->rows;
if (!$Q) {print "$sthArows rows inserted into vicidial_inbound_callback_queue_archive table \n";}
$rv = $sthA->err();
if (!$rv)
{
$stmtA = "DELETE FROM vicidial_inbound_callback_queue WHERE icbq_status IN('SENT','EXPIRED','DNCL','DNCC','ORPHAN');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows = $sthA->rows;
if (!$Q) {print "$sthArows rows deleted from vicidial_inbound_callback_queue table \n";}
$stmtA = "optimize table vicidial_inbound_callback_queue;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
}
# reset in-group closing_time_now_trigger trigger flag
$stmtA = "UPDATE vicidial_inbound_groups SET closing_time_now_trigger='N' WHERE closing_time_now_trigger='Y';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows = $sthA->rows;
if (!$Q) {print "$sthArows vicidial_inbound_groups rows closing_time_now_trigger value reset \n";}
##### BEGIN max stats end of day process #####
# set OPEN max stats records to CLOSING for processing
$stmtA = "UPDATE vicidial_daily_max_stats SET stats_flag='CLOSING' where stats_flag='OPEN';";
+878 -1
View File
@@ -6,7 +6,7 @@
# adjusts the auto_dial_level for vicidial adaptive-predictive campaigns.
# gather call stats for campaigns and in-groups
#
# Copyright (C) 2017 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
# Copyright (C) 2018 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGELOG
# 60823-1302 - First build from AST_VDhopper.pl
@@ -46,6 +46,7 @@
# 161102-1029 - Fixed QM partition problem
# 170724-2352 - Added option for cached hour counts for vicidial_log entries per campaign and carrier log totals
# 171221-1049 - Added caching of inbound call stats
# 180203-1728 - Added function to check for inbound callback queue calls to be placed
#
@@ -670,6 +671,882 @@ while ($master_loop < $CLIloops)
$diff_ratio_updater = ($diff_ratio_updater + $CLIdelay);
$drop_count_updater = ($drop_count_updater + $CLIdelay);
##########################################################
##### BEGIN check for inbound callback queue entries #####
##########################################################
$stmtA = "SELECT count(*) from vicidial_inbound_callback_queue where icbq_status='LIVE';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsICBQ=$sthA->rows;
if ($sthArowsICBQ > 0)
{
@aryA = $sthA->fetchrow_array;
$ICBQcount = $aryA[0];
}
$sthA->finish();
if ($DB) {print "\nLive Inbound Callback Queue Entries: |$ICBQcount|$stat_count|$stmtA|\n";}
if ($ICBQcount > 0)
{
$now_epoch = time();
$BDtarget = ($now_epoch - 7);
($Bsec,$Bmin,$Bhour,$Bmday,$Bmon,$Byear,$Bwday,$Byday,$Bisdst) = localtime($BDtarget);
$Byear = ($Byear + 1900);
$Bmon++;
if ($Bmon < 10) {$Bmon = "0$Bmon";}
if ($Bmday < 10) {$Bmday = "0$Bmday";}
if ($Bhour < 10) {$Bhour = "0$Bhour";}
if ($Bmin < 10) {$Bmin = "0$Bmin";}
if ($Bsec < 10) {$Bsec = "0$Bsec";}
$BDtsSQLdate = "$Byear$Bmon$Bmday$Bhour$Bmin$Bsec";
@ICBQicbq_id=@MT;
@ICBQlead_id=@MT;
@ICBQicbq_date=@MT;
@ICBQgroup_id=@MT;
@ICBQcall_date=@MT;
@ICBQqueue_priority=@MT;
@ICBQicbq_phone_number=@MT;
@ICBQicbq_phone_code=@MT;
@ICBQicbq_date_epoch=@MT;
$routed_ingroup_list='|';
if ( (($stat_count =~ /0$|5$/) || ($stat_count==1)) )
{$routed_user_list='';}
$stmtA = "SELECT icbq_id,lead_id,icbq_date,group_id,call_date,queue_priority,icbq_phone_number,icbq_phone_code,UNIX_TIMESTAMP(icbq_date) from vicidial_inbound_callback_queue where icbq_status='LIVE' order by queue_priority desc,call_date limit 1000;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsICBQr=$sthA->rows;
$r=0;
while ($sthArowsICBQr > $r)
{
@aryA = $sthA->fetchrow_array;
$ICBQicbq_id[$r] = $aryA[0];
$ICBQlead_id[$r] = $aryA[1];
$ICBQicbq_date[$r] = $aryA[2];
$ICBQgroup_id[$r] = $aryA[3];
$ICBQcall_date[$r] = $aryA[4];
$ICBQqueue_priority[$r] = $aryA[5];
$ICBQicbq_phone_number[$r] = $aryA[6];
$ICBQicbq_phone_code[$r] = $aryA[7];
$ICBQicbq_date_epoch[$r] = $aryA[8];
$r++;
}
$sthA->finish();
$r=0;
while ($sthArowsICBQr > $r)
{
$temp_ingroup = $ICBQgroup_id[$r];
if ($routed_ingroup_list !~ /\|$temp_ingroup\|/)
{
$routed_ingroup_list .= "$temp_ingroup|";
if ($DBX) {print "Live Inbound Callback Queue Entry: $r|$ICBQicbq_id[$r]|$ICBQlead_id[$r]|$ICBQgroup_id[$r]|$ICBQcall_date[$r]|\n";}
### Grab inbound group settings from the database
$stmtA = "SELECT next_agent_call,queue_priority,active,dial_ingroup_cid,icbq_expiration_hours FROM vicidial_inbound_groups where group_id='$ICBQgroup_id[$r]';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsIG=$sthA->rows;
if ($sthArowsIG > 0)
{
@aryA = $sthA->fetchrow_array;
$CAMP_callorder = $aryA[0];
$queue_priority = $aryA[1];
$ingroup_active = $aryA[2];
$dial_ingroup_cid = $aryA[3];
$icbq_expiration_hours = $aryA[4];
$expire_epoch = ($now_epoch - ($icbq_expiration_hours * 3600));
}
$sthA->finish();
$agent_call_order='order by last_call_finish';
if ($CAMP_callorder =~ /longest_wait_time/i) {$agent_call_order = 'order by vicidial_live_agents.last_state_change';}
if ($CAMP_callorder =~ /overall_user_level/i) {$agent_call_order = 'order by user_level desc,last_call_finish';}
if ($CAMP_callorder =~ /oldest_call_start/i) {$agent_call_order = 'order by vicidial_live_agents.last_call_time';}
if ($CAMP_callorder =~ /oldest_call_finish/i) {$agent_call_order = 'order by vicidial_live_agents.last_call_finish';}
if ($CAMP_callorder =~ /oldest_inbound_call_start/i) {$agent_call_order = 'order by vicidial_live_agents.last_inbound_call_time';}
if ($CAMP_callorder =~ /oldest_inbound_call_finish/i) {$agent_call_order = 'order by vicidial_live_agents.last_inbound_call_finish';}
if ($CAMP_callorder =~ /random/i) {$agent_call_order = 'order by random_id';}
if ($CAMP_callorder =~ /campaign_rank/i) {$agent_call_order = 'order by campaign_weight desc,last_call_finish';}
if ($CAMP_callorder =~ /fewest_calls_campaign/i) {$agent_call_order = 'order by vicidial_live_agents.calls_today,vicidial_live_agents.last_call_finish';}
if ($CAMP_callorder =~ /inbound_group_rank/i) {$aco_sub=1; $agent_call_order = 'order by group_weight desc,vicidial_live_inbound_agents.last_call_finish';}
if ($CAMP_callorder =~ /ingroup_grade_random/i) {$aco_sub=1; $agent_call_order = 'order by random_id';}
if ($CAMP_callorder =~ /campaign_grade_random/i) {$aco_sub=1; $agent_call_order = 'order by random_id';}
if ($CAMP_callorder =~ /fewest_calls$/i) {$aco_sub=1; $agent_call_order = 'order by vicidial_live_inbound_agents.calls_today,vicidial_live_inbound_agents.last_call_finish';}
if ($CAMP_callorder =~ /ring_all$/i) {$aco_sub=0; $agent_call_order = 'order by vicidial_live_agents.last_state_change';}
$rec_countWAITrem=0;
### Get count of number of calls in this group that are ahead of this call
$stmtA = "SELECT count(*) FROM vicidial_auto_calls where status = 'LIVE' and campaign_id='$ICBQgroup_id[$r]' and call_time < \"$ICBQcall_date[$r]\" and lead_id != '$ICBQlead_id[$r]' and queue_priority >= '$ICBQqueue_priority[$r]' $ADfindSQL;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$rec_countWAITrem = $aryA[0];
}
$sthA->finish();
if ($DBX) {$agi_string = "$rec_countWAITrem|$stmtA|"; print "$agi_string\n";}
$rec_countWAITqueue=0;
### Get count of number of calls in the callback-queue for this group that are ahead of this call
$stmtA = "SELECT count(*) FROM vicidial_inbound_callback_queue where icbq_status IN('LIVE','SENDING') and group_id='$ICBQgroup_id[$r]' and call_date < \"$ICBQcall_date[$r]\" and lead_id != '$ICBQlead_id[$r]' and queue_priority >= '$ICBQqueue_priority[$r]';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$rec_countWAITqueue = $aryA[0];
}
$sthA->finish();
if ($DBX) {$agi_string = "$rec_countWAITqueue|$stmtA|"; print "$agi_string\n";}
if ( ($rec_countWAITrem < 1) && ($rec_countWAITqueue < 1) )
{
$sthArowsFA=0;
$qp_countWAIT=0;
### Get count of number of waiting calls in higher priority groups than this call or the same priority with longer wait time
$stmtA = "SELECT count(*) FROM vicidial_auto_calls where status = 'LIVE' and lead_id != '$ICBQlead_id[$r]' $ADfindSQL and ( (queue_priority > '$ICBQqueue_priority[$r]') or (queue_priority = '$ICBQqueue_priority[$r]' and call_time < \"$ICBQcall_date[$r]\") );";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$qp_countWAIT = $aryA[0];
}
$sthA->finish();
if ($DBX) {$agi_string = "$qp_countWAIT|$stmtA|"; print "$agi_string\n";}
$qp_countWAITqueue=0;
### Get count of number of waiting calls in higher priority groups than this call or the same priority with longer wait time
$stmtA = "SELECT count(*) FROM vicidial_inbound_callback_queue where icbq_status IN('LIVE','SENDING') and lead_id != '$ICBQlead_id[$r]' and ( (queue_priority > '$ICBQqueue_priority[$r]') or (queue_priority = '$ICBQqueue_priority[$r]' and call_date < \"$ICBQcall_date[$r]\") );";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$qp_countWAITqueue = $aryA[0];
}
$sthA->finish();
if ($DBX) {$agi_string = "$qp_countWAITqueue|$stmtA|"; print "$agi_string\n";}
$qp_groupWAIT='';
$qp_groupWAIT_SQL='';
$qp_groupWAIT_aco='';
$qp_groupWAIT_aco_SQL='';
$qp_groupWAIT_camp_SQL='';
if ( ($qp_countWAIT > 0) || ($qp_countWAITqueue > 0) )
{
### Get group/campaign ids of calls in higher priority groups than this call or the same priority with longer wait time
$qp_groupWAIT='';
$stmtA = "SELECT distinct campaign_id FROM vicidial_auto_calls where status = 'LIVE' and lead_id != '$ICBQlead_id[$r]' $ADfindSQL and ( (queue_priority > '$ICBQqueue_priority[$r]') or (queue_priority = '$ICBQqueue_priority[$r]' and call_time < \"$ICBQcall_date[$r]\") );";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$dbc=0;
while ($sthArows > $dbc)
{
@aryA = $sthA->fetchrow_array;
$qp_groupWAIT_aco .= "'$aryA[0]',";
if ($dbc > 0)
{
$qp_groupWAIT .= "and ";
}
$qp_groupWAIT .= "closer_campaigns NOT LIKE \"% $aryA[0] %\" ";
$dbc++;
}
$stmtA = "SELECT distinct group_id FROM vicidial_inbound_callback_queue where icbq_status IN('LIVE','SENDING') and lead_id != '$ICBQlead_id[$r]' $ADfindSQL and ( (queue_priority > '$ICBQqueue_priority[$r]') or (queue_priority = '$ICBQqueue_priority[$r]' and call_date < \"$ICBQcall_date[$r]\") );";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$dbcQ=0;
while ($sthArows > $dbcQ)
{
@aryA = $sthA->fetchrow_array;
$qp_groupWAIT_aco .= "'$aryA[0]',";
if ($dbc > 0)
{
$qp_groupWAIT .= "and ";
}
$qp_groupWAIT .= "closer_campaigns NOT LIKE \"% $aryA[0] %\" ";
$dbc++;
$dbcQ++;
}
if (length($qp_groupWAIT_aco)>2)
{chop($qp_groupWAIT_aco);}
else
{
$qp_groupWAIT_aco="''";
$qp_groupWAIT = "closer_campaigns != ''";
}
$qp_groupWAIT_SQL = "and ($qp_groupWAIT)";
$qp_groupWAIT_aco_SQL = "and vicidial_live_inbound_agents.group_id NOT IN($qp_groupWAIT_aco)";
$qp_groupWAIT_camp_SQL = "and campaign_id NOT IN($qp_groupWAIT_aco)";
if ($DBX) {$agi_string = "$qp_groupWAIT_SQL|$stmtA|"; print "$agi_string\n";}
$sthA->finish();
}
$VACagent_grab='|';
$stmtA = "SELECT agent_grab from vicidial_auto_calls where agent_grab!='';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsGRAB=$sthA->rows;
if ($sthArowsGRAB > 0)
{
@aryA = $sthA->fetchrow_array;
$VACagent_grab .= "$aryA[0]|";
}
$sthA->finish();
if ($DBX) {$agi_string = " AGENTS TAKING CALLS CHECK: $sthArowsGRAB|$VACagent_grab|$stmtA|"; print "$agi_string\n";}
if ($aco_sub > 0)
{
### BEGIN in-group-rank-based next-agent-call processing ###
$stmtA = "LOCK TABLES vicidial_live_agents WRITE, vicidial_live_inbound_agents WRITE;";
my $LOCKaffected_rows = $dbhA->do($stmtA);
if (length($qp_groupWAIT_aco)<2)
{$qp_groupWAIT_aco="''";}
### Get list of users that should take higher priority inbound calls first
$stmtA = "SELECT distinct user from vicidial_live_inbound_agents where group_id IN($qp_groupWAIT_aco);";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$dbc=0;
$vlia_users='';
while ($sthArows > $dbc)
{
@aryA = $sthA->fetchrow_array;
$vlia_users .= "'$aryA[0]',";
$dbc++;
}
if (length($vlia_users)>2)
{chop($vlia_users);}
else
{$vlia_users="''";}
### if ringing an agent, do not look for one, else, look for one
if ($RING_agent > 0)
{$sthArows=0;}
else
{
### BEGIN grade random next-agent-call routing ###
if ($CAMP_callorder =~ /grade/)
{
@GRADEuser=@MT;
@GRADEgrade=@MT;
@userGRADEarray=@MT;
$stmtA = "SELECT vicidial_live_agents.user,vicidial_live_inbound_agents.group_grade,vicidial_live_agents.campaign_grade from vicidial_live_agents, vicidial_live_inbound_agents WHERE vicidial_live_agents.user=vicidial_live_inbound_agents.user and status IN('CLOSER','READY') and lead_id<1 $ADUfindSQL and vicidial_live_inbound_agents.group_id='$ICBQgroup_id[$r]' and last_update_time > '$BDtsSQLdate' and vicidial_live_agents.user NOT IN($vlia_users) and ring_callerid='' $qp_groupWAIT_camp_SQL limit 1000;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$gg=0;
$ga=0;
while ($gg < $sthArows)
{
@aryA = $sthA->fetchrow_array;
$GRADEuser[$gg] = $aryA[0];
if ($CAMP_callorder =~ /ingroup_grade_random/)
{$GRADEgrade[$gg] = $aryA[1];}
else
{$GRADEgrade[$gg] = $aryA[2];}
if ($GRADEgrade[$gg] < 1)
{$GRADEgrade[$gg] = 1;}
$gi=0;
while ($gi < $GRADEgrade[$gg])
{
$userGRADEarray[$ga] = $GRADEuser[$gg];
# print STDERR " GRADE ENTRY: $userGRADEarray[$ga]|$ga|$gi|$GRADEgrade[$gg]\n";
$gi++;
$ga++;
}
$gg++;
}
$sthA->finish();
$sthArows=0;
if ($ga > 0)
{
$sthArowsFA=0;
$VDADuser='';
$GRADErandom = int( rand($ga));
$userGRADEchosen = $userGRADEarray[$GRADErandom];
if ($DBX) {$agi_string = "GRADE RANDOM: $userGRADEchosen|$GRADErandom|$CAMP_callorder|$gg|$ga|$callerid"; print "$agi_string\n";}
$stmtA = "SELECT vicidial_live_agents.conf_exten,vicidial_live_agents.user,vicidial_live_agents.extension,vicidial_live_agents.server_ip,vicidial_live_inbound_agents.group_weight,ra_user,vicidial_live_agents.campaign_id,on_hook_agent,on_hook_ring_time,vicidial_live_inbound_agents.group_grade,vicidial_live_agents.campaign_grade from vicidial_live_agents, vicidial_live_inbound_agents WHERE vicidial_live_agents.user='$userGRADEchosen' and vicidial_live_agents.user NOT IN($routed_user_list'') and status IN('CLOSER','READY') limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsFA=$sthA->rows;
if ($sthArowsFA > 0)
{
@aryA = $sthA->fetchrow_array;
$VDADconf_exten = $aryA[0];
$VDADuser = $aryA[1];
$VDADextension = $aryA[2];
$VDADserver_ip = $aryA[3];
$VDADgroup_weight = $aryA[4];
$ra_user = $aryA[5];
$log_campaign = $aryA[6];
$VDADon_hook_agent = $aryA[7];
$VDADon_hook_ring_time = $aryA[8];
$group_grade = $aryA[9];
$campaign_grade = $aryA[10];
}
$sthA->finish();
}
if ($DBX) {$agi_string = "$VDADuser|$VDADgroup_weight|$stmtA|"; print "$agi_string\n";}
}
### END grade random next-agent-call routing ###
else
{
$sthArowsFA=0;
$VDADuser='';
$stmtA = "SELECT vicidial_live_agents.conf_exten,vicidial_live_agents.user,vicidial_live_agents.extension,vicidial_live_agents.server_ip,vicidial_live_inbound_agents.group_weight,ra_user,vicidial_live_agents.campaign_id,on_hook_agent,on_hook_ring_time,vicidial_live_inbound_agents.group_grade,vicidial_live_agents.campaign_grade from vicidial_live_agents, vicidial_live_inbound_agents WHERE vicidial_live_agents.user=vicidial_live_inbound_agents.user and status IN('CLOSER','READY') and lead_id<1 $ADUfindSQL and vicidial_live_inbound_agents.group_id='$ICBQgroup_id[$r]' and last_update_time > '$BDtsSQLdate' and vicidial_live_agents.user NOT IN($routed_user_list$vlia_users) and ring_callerid='' $qp_groupWAIT_camp_SQL $agent_call_order limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsFA=$sthA->rows;
if ($sthArowsFA > 0)
{
@aryA = $sthA->fetchrow_array;
$VDADconf_exten = $aryA[0];
$VDADuser = $aryA[1];
$VDADextension = $aryA[2];
$VDADserver_ip = $aryA[3];
$VDADgroup_weight = $aryA[4];
$ra_user = $aryA[5];
$log_campaign = $aryA[6];
$VDADon_hook_agent = $aryA[7];
$VDADon_hook_ring_time = $aryA[8];
$group_grade = $aryA[9];
$campaign_grade = $aryA[10];
}
$sthA->finish();
if ($DBX) {$agi_string = "$VDADuser|$VDADgroup_weight|$stmtA|"; print "$agi_string\n";}
}
}
### END in-group-rank-based next-agent-call processing ###
}
else
{
### BEGIN standard next-agent-call processing ###
$stmtA = "LOCK TABLES vicidial_live_agents WRITE;";
my $LOCKaffected_rows = $dbhA->do($stmtA);
### if ringing an agent, do not look for one, else, look for one
if ($RING_agent > 0)
{$sthArowsFA=0;}
else
{
$sthArowsFA=0;
$stmtA = "SELECT conf_exten,user,extension,server_ip,last_call_time,ra_user,campaign_id,on_hook_agent,on_hook_ring_time FROM vicidial_live_agents where status IN('CLOSER','READY') and lead_id<1 $ADUfindSQL and campaign_id IN($INBOUNDcampsSQL) and closer_campaigns LIKE \"% $ICBQgroup_id[$r] %\" and last_update_time > '$BDtsSQLdate' and user NOT IN($routed_user_list'') $qp_groupWAIT_SQL $qp_groupWAIT_camp_SQL $agent_call_order limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsFA=$sthA->rows;
if ($sthArowsFA > 0)
{
@aryA = $sthA->fetchrow_array;
$VDADconf_exten = $aryA[0];
$VDADuser = $aryA[1];
$VDADextension = $aryA[2];
$VDADserver_ip = $aryA[3];
$VDADlast_call_time = $aryA[4];
$ra_user = $aryA[5];
$log_campaign = $aryA[6];
$VDADon_hook_agent = $aryA[7];
$VDADon_hook_ring_time = $aryA[8];
}
$sthA->finish();
if ($DBX) {$agi_string = "$VDADuser|$VDADlast_call_time|$stmtA|"; print "$agi_string\n";}
}
### END standard next-agent-call processing ###
}
if ( ($sthArowsFA > 0) && (length($VDADuser) > 0) )
{
$Faffected_rows=0;
if ($VACagent_grab !~ /\|$VDADuser\|/)
{
$stmtA = "UPDATE vicidial_live_agents set external_dial='$ICBQicbq_phone_number[$r]!$ICBQicbq_phone_code[$r]!NO!NO!NO!!$secX!!!$dial_ingroup_cid!!$ICBQlead_id[$r]!!$ICBQgroup_id[$r]' where user='$VDADuser' and status IN('CLOSER','READY');";
$Faffected_rows = $dbhA->do($stmtA);
if ($Faffected_rows > 0)
{
### clear the ringing hold on the ring agents
$stmtB = "UPDATE vicidial_live_agents SET ring_callerid='' where ring_callerid='$callerid';";
$CRHaffected_rows = $dbhA->do($stmtB);
$routed_user_list .= "'$VDADuser',";
}
if ($DBX) {$agi_string = "$Faffected_rows|$stmtA\n$CRHaffected_rows|$stmtB|$routed_user_list|"; print "$agi_string\n";}
}
else
{
if ($DBX) {$agi_string = " SELECTED AGENT GRABBING ANOTHER CALL: $VDADuser $VACagent_grab"; print "$agi_string\n";}
}
}
else
{
$Faffected_rows=0;
}
$found_agents=$Faffected_rows;
$stmtA = "UNLOCK TABLES;";
my $LOCKaffected_rows = $dbhA->do($stmtA);
if ($found_agents > 0)
{
### set the icbq record as SENT
$stmtC = "UPDATE vicidial_inbound_callback_queue SET icbq_status='SENDING' where icbq_id='$ICBQicbq_id[$r]';";
$ICBQaffected_rows = $dbhA->do($stmtC);
if ($DBX) {$agi_string = "$ICBQaffected_rows|$stmtC|"; print "$agi_string\n";}
}
}
if ($ICBQicbq_date_epoch[$r] < $expire_epoch)
{
### set the icbq record as EXPIRED
$stmtC = "UPDATE vicidial_inbound_callback_queue SET icbq_status='EXPIRED' where icbq_id='$ICBQicbq_id[$r]' and icbq_status!='SENT';";
$ICBQaffected_rowsEXP = $dbhA->do($stmtC);
if ($DBX) {$agi_string = "$ICBQaffected_rowsEXP|$stmtC|"; print "$agi_string\n";}
}
}
else
{
if ($DBX) {print " Already looked at ICBQ Entry for this In-Group: $r|$ICBQicbq_id[$r]|$ICBQgroup_id[$r]|$ICBQcall_date[$r]| ($routed_ingroup_list)\n";}
}
$r++;
}
}
$icbq_NEW_ct=0;
$stmtA = "SELECT count(*) from vicidial_inbound_callback_queue where icbq_status='NEW';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsICBQ=$sthA->rows;
if ($sthArowsICBQ > 0)
{
@aryA = $sthA->fetchrow_array;
$icbq_NEW_ct = $aryA[0];
}
$sthA->finish();
##########################################################
##### END check for inbound callback queue entries #####
##########################################################
##########################################################
##### BEGIN check if active inbound callback queue records are able to be dialed right now #####
##########################################################
if ( ($stat_count =~ /00$|20$|40$|60$|80$/) || ($stat_count==1) || ($icbq_NEW_ct > 0) )
{
$stmtA = "SELECT count(*) from vicidial_inbound_callback_queue where icbq_status IN('NEW','LIVE','NOCALLTIME');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsICBQa=$sthA->rows;
if ($sthArowsICBQa > 0)
{
@aryA = $sthA->fetchrow_array;
$ICBQcountA = $aryA[0];
}
$sthA->finish();
if ($DB) {print "\nActive Inbound Callback Queue Entries: |$ICBQcountA|$stmtA|\n";}
if ($ICBQcountA > 0)
{
@ICBQicbq_id=@MT;
@ICBQlead_id=@MT;
@ICBQgroup_id=@MT;
@ICBQicbq_phone_number=@MT;
@ICBQicbq_phone_code=@MT;
@ICBQgmt_offset_now=@MT;
@ICBQicbq_status=@MT;
$stmtA = "SELECT icbq_id,group_id,icbq_phone_number,icbq_phone_code,gmt_offset_now,icbq_status,lead_id from vicidial_inbound_callback_queue where icbq_status IN('NEW','LIVE','NOCALLTIME') order by group_id,call_date limit 1000;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsICBQr=$sthA->rows;
$r=0;
while ($sthArowsICBQr > $r)
{
@aryA = $sthA->fetchrow_array;
$ICBQicbq_id[$r] = $aryA[0];
$ICBQgroup_id[$r] = $aryA[1];
$ICBQicbq_phone_number[$r] = $aryA[2];
$ICBQicbq_phone_code[$r] = $aryA[3];
$ICBQgmt_offset_now[$r] = $aryA[4];
$ICBQicbq_status[$r] = $aryA[5];
$ICBQlead_id[$r] = $aryA[6];
$r++;
}
$sthA->finish();
$r=0;
while ($sthArowsICBQr > $r)
{
if ($DBX) {print "Active Inbound Callback Queue Entry: $r|$ICBQicbq_id[$r]|$ICBQicbq_status[$r]|$ICBQgroup_id[$r]|$ICBQicbq_phone_number[$r]|$ICBQicbq_phone_code[$r]|$ICBQgmt_offset_now[$r]|\n";}
### Grab inbound group settings from the database
$stmtA = "SELECT icbq_call_time_id,icbq_dial_filter FROM vicidial_inbound_groups where group_id='$ICBQgroup_id[$r]';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsIG=$sthA->rows;
if ($sthArowsIG > 0)
{
@aryA = $sthA->fetchrow_array;
$icbq_call_time_id = $aryA[0];
$icbq_dial_filter = $aryA[1];
}
$sthA->finish();
### BEGIN check of call time dialable for this record
$dialable=0;
$now_epoch = time();
$GMT_now = ($now_epoch - (($LOCAL_GMT_OFF - $ICBQgmt_offset_now[$r]) * 3600));
($Gsec,$Gmin,$Ghour,$Gmday,$Gmon,$Gyear,$Gwday,$Gyday,$Gisdst) = localtime($GMT_now);
$Gmon++;
$Gyear = ($Gyear + 1900);
if ($Gmon < 10) {$Gmon = "0$Gmon";}
if ($Gmday < 10) {$Gmday = "0$Gmday";}
if ($Ghour < 10) {$Ghour = "0$Ghour";}
if ($Gmin < 10) {$Gmin = "0$Gmin";}
if ($Gsec < 10) {$Gsec = "0$Gsec";}
$Ghourmin = "$Ghour$Gmin";
$YMD = "$Gyear-$Gmon-$Gmday";
$stmtA = "SELECT call_time_id,call_time_name,call_time_comments,ct_default_start,ct_default_stop,ct_sunday_start,ct_sunday_stop,ct_monday_start,ct_monday_stop,ct_tuesday_start,ct_tuesday_stop,ct_wednesday_start,ct_wednesday_stop,ct_thursday_start,ct_thursday_stop,ct_friday_start,ct_friday_stop,ct_saturday_start,ct_saturday_stop,ct_state_call_times,ct_holidays FROM vicidial_call_times where call_time_id='$icbq_call_time_id';";
if ($DBX) {print " |$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$rec_count=0;
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$Gct_default_start = $aryA[3];
$Gct_default_stop = $aryA[4];
$Gct_sunday_start = $aryA[5];
$Gct_sunday_stop = $aryA[6];
$Gct_monday_start = $aryA[7];
$Gct_monday_stop = $aryA[8];
$Gct_tuesday_start = $aryA[9];
$Gct_tuesday_stop = $aryA[10];
$Gct_wednesday_start = $aryA[11];
$Gct_wednesday_stop = $aryA[12];
$Gct_thursday_start = $aryA[13];
$Gct_thursday_stop = $aryA[14];
$Gct_friday_start = $aryA[15];
$Gct_friday_stop = $aryA[16];
$Gct_saturday_start = $aryA[17];
$Gct_saturday_stop = $aryA[18];
$Gct_state_call_times = $aryA[19];
$Gct_holidays = $aryA[20];
$rec_count++;
}
$sthA->finish();
### BEGIN Check for outbound call time holiday ###
$holiday_id = '';
if (length($Gct_holidays)>2)
{
$Gct_holidaysSQL = $Gct_holidays;
$Gct_holidaysSQL =~ s/^\||\|$//gi;
$Gct_holidaysSQL =~ s/\|/','/gi;
$Gct_holidaysSQL = "'$Gct_holidaysSQL'";
$stmtC = "SELECT holiday_id,holiday_date,holiday_name,ct_default_start,ct_default_stop from vicidial_call_time_holidays where holiday_id IN($Gct_holidaysSQL) and holiday_status='ACTIVE' and holiday_date='$YMD' order by holiday_id;";
if ($DBX) {print " |$stmtC|\n";}
$sthC = $dbhA->prepare($stmtC) or die "preparing: ",$dbhA->errstr;
$sthC->execute or die "executing: $stmtC ", $dbhA->errstr;
$sthCrows=$sthC->rows;
if ($sthCrows > 0)
{
@aryC = $sthC->fetchrow_array;
$holiday_id = $aryC[0];
$holiday_date = $aryC[1];
$holiday_name = $aryC[2];
if ( ($Gct_default_start < $aryC[3]) && ($Gct_default_stop > 0) ) {$Gct_default_start = $aryC[3];}
if ( ($Gct_default_stop > $aryC[4]) && ($Gct_default_stop > 0) ) {$Gct_default_stop = $aryC[4];}
if ( ($Gct_sunday_start < $aryC[3]) && ($Gct_sunday_stop > 0) ) {$Gct_sunday_start = $aryC[3];}
if ( ($Gct_sunday_stop > $aryC[4]) && ($Gct_sunday_stop > 0) ) {$Gct_sunday_stop = $aryC[4];}
if ( ($Gct_monday_start < $aryC[3]) && ($Gct_monday_stop > 0) ) {$Gct_monday_start = $aryC[3];}
if ( ($Gct_monday_stop > $aryC[4]) && ($Gct_monday_stop > 0) ) {$Gct_monday_stop = $aryC[4];}
if ( ($Gct_tuesday_start < $aryC[3]) && ($Gct_tuesday_stop > 0) ) {$Gct_tuesday_start = $aryC[3];}
if ( ($Gct_tuesday_stop > $aryC[4]) && ($Gct_tuesday_stop > 0) ) {$Gct_tuesday_stop = $aryC[4];}
if ( ($Gct_wednesday_start < $aryC[3]) && ($Gct_wednesday_stop > 0) ) {$Gct_wednesday_start = $aryC[3];}
if ( ($Gct_wednesday_stop > $aryC[4]) && ($Gct_wednesday_stop > 0) ) {$Gct_wednesday_stop = $aryC[4];}
if ( ($Gct_thursday_start < $aryC[3]) && ($Gct_thursday_stop > 0) ) {$Gct_thursday_start = $aryC[3];}
if ( ($Gct_thursday_stop > $aryC[4]) && ($Gct_thursday_stop > 0) ) {$Gct_thursday_stop = $aryC[4];}
if ( ($Gct_friday_start < $aryC[3]) && ($Gct_friday_stop > 0) ) {$Gct_friday_start = $aryC[3];}
if ( ($Gct_friday_stop > $aryC[4]) && ($Gct_friday_stop > 0) ) {$Gct_friday_stop = $aryC[4];}
if ( ($Gct_saturday_start < $aryC[3]) && ($Gct_saturday_stop > 0) ) {$Gct_saturday_start = $aryC[3];}
if ( ($Gct_saturday_stop > $aryC[4]) && ($Gct_saturday_stop > 0) ) {$Gct_saturday_stop = $aryC[4];}
if ($DBX) {print " CALL TIME HOLIDAY FOUND! $local_call_time[$i]|$holiday_id|$holiday_date|$holiday_name|$Gct_default_start|$Gct_default_stop|\n";}
}
$sthC->finish();
}
### END Check for outbound call time holiday ###
if ($Gwday==0) #### Sunday local time
{
if (($Gct_sunday_start==0) && ($Gct_sunday_stop==0))
{
if ( ($Ghourmin>=$Gct_default_start) && ($Ghourmin<$Gct_default_stop) )
{$dialable++;}
}
else
{
if ( ($Ghourmin>=$Gct_sunday_start) && ($Ghourmin<$Gct_sunday_stop) )
{$dialable++;}
}
}
if ($Gwday==1) #### Monday local time
{
if (($Gct_monday_start==0) && ($Gct_monday_stop==0))
{
if ( ($Ghourmin>=$Gct_default_start) && ($Ghourmin<$Gct_default_stop) )
{$dialable++;}
}
else
{
if ( ($Ghourmin>=$Gct_monday_start) && ($Ghourmin<$Gct_monday_stop) )
{$dialable++;}
}
}
if ($Gwday==2) #### Tuesday local time
{
if (($Gct_tuesday_start==0) && ($Gct_tuesday_stop==0))
{
if ( ($Ghourmin>=$Gct_default_start) && ($Ghourmin<$Gct_default_stop) )
{$dialable++;}
}
else
{
if ( ($Ghourmin>=$Gct_tuesday_start) && ($Ghourmin<$Gct_tuesday_stop) )
{$dialable++;}
}
}
if ($Gwday==3) #### Wednesday local time
{
if (($Gct_wednesday_start==0) && ($Gct_wednesday_stop==0))
{
if ( ($Ghourmin>=$Gct_default_start) && ($Ghourmin<$Gct_default_stop) )
{$dialable++;}
}
else
{
if ( ($Ghourmin>=$Gct_wednesday_start) && ($Ghourmin<$Gct_wednesday_stop) )
{$dialable++;}
}
}
if ($Gwday==4) #### Thursday local time
{
if (($Gct_thursday_start==0) && ($Gct_thursday_stop==0))
{
if ( ($Ghourmin>=$Gct_default_start) && ($Ghourmin<$Gct_default_stop) )
{$dialable++;}
}
else
{
if ( ($Ghourmin>=$Gct_thursday_start) && ($Ghourmin<$Gct_thursday_stop) )
{$dialable++;}
}
}
if ($Gwday==5) #### Friday local time
{
if (($Gct_friday_start==0) && ($Gct_friday_stop==0))
{
if ( ($Ghourmin>=$Gct_default_start) && ($Ghourmin<$Gct_default_stop) )
{$dialable++;}
}
else
{
if ( ($Ghourmin>=$Gct_friday_start) && ($Ghourmin<$Gct_friday_stop) )
{$dialable++;}
}
}
if ($Gwday==6) #### Saturday local time
{
if (($Gct_saturday_start==0) && ($Gct_saturday_stop==0))
{
if ( ($Ghourmin>=$Gct_default_start) && ($Ghourmin<$Gct_default_stop) )
{$dialable++;}
}
else
{
if ( ($Ghourmin>=$Gct_saturday_start) && ($Ghourmin<$Gct_saturday_stop) )
{$dialable++;}
}
}
if ($dialable > 0)
{$NEWstatus = 'LIVE';}
else
{$NEWstatus = 'NOCALLTIME';}
if ($DBX) {print " CALL TIME ICBQ DIALABLE CHECK $Ghourmin|$Gwday|$dialable|$NEWstatus|$Gct_default_start|$Gct_default_stop|\n";}
### END check of call time dialable for this record
### BEGIN check of DNC filtering for this record
$dnc_internal_match=0;
$dnc_campaign_match=0;
if ( ($icbq_dial_filter !~ /NONE/i) && (length($icbq_dial_filter) > 4) )
{
$alt_areacode='';
if ($icbq_dial_filter =~ /AREACODE/)
{
$alt_areacode = substr($ICBQicbq_phone_number[$r], 0, 3);
$alt_areacode .= "XXXXXXX";
$alt_areacode = ",'$alt_areacode'";
}
if ($icbq_dial_filter =~ /INTERNAL/)
{
$stmtA = "SELECT count(*) FROM vicidial_dnc where phone_number IN('$ICBQicbq_phone_number[$r]'$alt_areacode);";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$dnc_internal_match = $aryA[0];
}
$sthA->finish();
if ($DBX) {print " CALLBACK DIAL FILTER DNC INTERNAL: |$dnc_internal_match|$stmtA|\n";}
}
if ($icbq_dial_filter =~ /CAMPAIGN/)
{
$dnc_campaign_list='';
$stmtA = "SELECT list_id FROM vicidial_list where lead_id='$ICBQlead_id[$r]';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$dnc_campaign_list = $aryA[0];
}
$sthA->finish();
if (length($dnc_campaign_list) > 1)
{
$dnc_campaign='';
$stmtA = "SELECT campaign_id FROM vicidial_lists where list_id='$dnc_campaign_list';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$dnc_campaign = $aryA[0];
}
$sthA->finish();
if (length($dnc_campaign) > 0)
{
$stmtA = "SELECT count(*) FROM vicidial_campaign_dnc where campaign_id='$dnc_campaign' and phone_number IN('$ICBQicbq_phone_number[$r]'$alt_areacode);";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$dnc_campaign_match = $aryA[0];
}
$sthA->finish();
}
}
if ($DBX) {print " CALLBACK DIAL FILTER DNC CAMPAIGN: |$dnc_campaign_match|$dnc_campaign_list|$stmtA|\n";}
}
if ($dnc_internal_match > 0)
{$NEWstatus = 'DNCL';}
else
{
if ($dnc_campaign_match > 0)
{$NEWstatus = 'DNCC';}
}
}
### END check of DNC filtering for this record
if ($ICBQicbq_status[$r] !~ /$NEWstatus/)
{
### set the icbq record to new status
$stmtC = "UPDATE vicidial_inbound_callback_queue SET icbq_status='$NEWstatus' where icbq_id='$ICBQicbq_id[$r]' and icbq_status!='SENT';";
$ICBQaffected_rowsNEW = $dbhA->do($stmtC);
if ($DBX) {$agi_string = "$ICBQaffected_rowsNEW|$stmtC|"; print "$agi_string\n";}
}
$r++;
}
}
}
##########################################################
##### END check if active inbound callback queue records are able to be dialed right now #####
##########################################################
##########################################################
##### BEGIN check for stuck SENDING inbound callback queue records #####
##########################################################
if ( ($stat_count =~ /00$|10$|20$|30$|40$|50$|60$|70$|80$|90$/) || ($stat_count==1) )
{
$now_epoch = time();
$BDtarget = ($now_epoch - 10);
($Bsec,$Bmin,$Bhour,$Bmday,$Bmon,$Byear,$Bwday,$Byday,$Bisdst) = localtime($BDtarget);
$Byear = ($Byear + 1900);
$Bmon++;
if ($Bmon < 10) {$Bmon = "0$Bmon";}
if ($Bmday < 10) {$Bmday = "0$Bmday";}
if ($Bhour < 10) {$Bhour = "0$Bhour";}
if ($Bmin < 10) {$Bmin = "0$Bmin";}
if ($Bsec < 10) {$Bsec = "0$Bsec";}
$BDtsSQLdate = "$Byear-$Bmon-$Bmday $Bhour:$Bmin:$Bsec";
$ICBQcountS=0;
$stmtA = "SELECT count(*) from vicidial_inbound_callback_queue where icbq_status IN('SENDING') and modify_date < \"$BDtsSQLdate\";";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArowsICBQs=$sthA->rows;
if ($sthArowsICBQs > 0)
{
@aryA = $sthA->fetchrow_array;
$ICBQcountS = $aryA[0];
}
$sthA->finish();
if ($DB) {print "\nOrphan SENDING Inbound Callback Queue Entries: |$ICBQcountS|$stmtA|\n";}
if ($ICBQcountS > 0)
{
### set the icbq record to new status
$stmtC = "UPDATE vicidial_inbound_callback_queue SET icbq_status='ORPHAN' where icbq_status IN('SENDING') and modify_date < \"$BDtsSQLdate\";";
$ICBQaffected_rowsORPHAN = $dbhA->do($stmtC);
if ($DBX) {$agi_string = "$ICBQaffected_rowsORPHAN|$stmtC|"; print "$agi_string\n";}
}
}
##########################################################
##### END check for stuck SENDING inbound callback queue records #####
##########################################################
usleep($CLIdelay*1000*1000);
$stat_count++;
+4 -1
View File
@@ -1,4 +1,4 @@
AGENT API DOCUMENT Started: 2008-07-03 Updated: 2018-01-24
AGENT API DOCUMENT Started: 2008-07-03 Updated: 2018-02-05
This document describes the functions of an API(Application Programming Interface)
for the VICIDIAL Agent screen. This functionality will be rather limited at first
@@ -253,6 +253,8 @@ alt_dial -
OPTIONAL, if using lead_id you can set this flag to dial the ALT number or the ADDR3 number or SEARCH a phone_number within the lead
if SEARCH is used and the phone_number is not matched with the lead's phone_number, alt_phone or address3 field
an ERROR will be returned
dial_ingroup -
OPTIONAL, place the call as an in-group outbound calls
EXAMPLE URLS:
http://server/agc/api.php?source=test&user=6666&pass=1234&agent_user=1000&function=external_dial&value=7275551212&phone_code=1&search=YES&preview=NO&focus=YES
@@ -263,6 +265,7 @@ ERROR: external_dial not valid - 7275551212|1|YES|6666
ERROR: no user found - 6666
ERROR: agent_user is not logged in - 6666
ERROR: agent_user is not allowed to place manual dial calls - 6666
ERROR: defined dial_ingroup not found - FAKE_INGROUP
ERROR: caller_id_number from group_alias is not valid - 6666|TESTING|123
ERROR: group_alias is not valid - 6666|TESTING
ERROR: vtiger callback activity does not exist in vtiger system - 12345
+62
View File
@@ -0,0 +1,62 @@
INBOUND CALLBACK QUEUE Started: 2018-01-15 Updated: 2018-02-06
The purpose of this feature is to allow for callers to leave the queue and be called back when their place in line is reached. Included in this new set of features are the new Closed Time features to In-Groups that allow all callers in queue to be presented with a press-1 option when the in-group closing time for the day has been reached. Also, an in-group feature was added to manually force the end of all queueing of calls for an in-group for the rest of the day.
REQUIREMENTS:
- svn/trunk revision 2905 or higher
- VICIdial servers should be restarted after performing upgrade
- Campaign must be set to "In-Group Manual Dial" = 'MANUAL_DIAL' or 'BOTH'
- One of the following In-Group options should be set to "PRESS_CALLBACK_QUEUE": 'Wait Time Option(s)','Estimated Hold Time Option(s)','Closing Time Action'
- Read about all of the new settings below so you understand how this complex feature works!
The AST_VDadapt.pl script already runs on one server in a cluster, and it has had three new processes added to it to facilitate the monitoring of the callback queued entries, as well as initiating the triggering of the outbound calls once the callers' places in line have been reached. This process also will set the inbound callback queue records that are past the Callback Queue Expire Hours old to EXPIRED status, as well as verifying that the inbound callback queue records are within the set Callbacks Queue Call Time and are not within the Internal and/or Campaign DNC lists, as defined in the In-Group settings.
The agi-VDAD_ALL_inbound.agi inbound call routing process has also been modified to allow for the insertion of inbound callback queue entries as well as the preservation of the place in line of the callers that choose to enter the callback queue.
The ADMIN_keepalive_ALL.pl now has an added process to take care of archiving once per day the old inbound callback queue records that are of SENT, EXPIRED and ORPHAN status. This process will also reset the Closing-Time-Now-Trigger if it has been used during the previous day.
The Real-Time report also has a new "Callback Queue Calls" top header in HTML view mode, so you can see how many LIVE entries there are in the inbound callback queue. If you want to see what in-groups those LIVE records are in, you can click on the "SHOW IN-GROUP STATS" link at the top of the Real-Time report.
Admin Web page changes:
Added the following Inbound Group "Hold Time" and "Wait Time" options:
The PRESS_CALLBACK_QUEUE option will preserve the caller place in line and will call the customer back when their place is the next one to go to an agent, this inbound callback queue entry will last until the call is placed back to the customer or as long as the Callback Queue Expire Hours setting below.
Added the following new Inbound Group Settings:
Callback Queue Expire Hours - If a Hold Time or Wait Time Option is set to PRESS_CALLBACK_QUEUE, this is the maximum number of hours that an entry can stay in the inbound callback queue before it is removed without dialing it. Default is 96 hours.
Callback Queue Call Time - For any inbound callback queue outbound calls to be placed, this is the local call time used to determine if the number can be dialed right now or not.
Callback Queue Dial Filter - This option allows you to remove DNC numbers from your Callback Queue. You can use any combination of: Internal DNC List, Campaign DNC List tied to campaign of the list where the lead is, and Areacode DNC wildcard
Closing Time Action - This allows you to specify the routing of the call if the closing time of the in-group is reached while the call is still waiting for an agent, Closing time is the end of the Call Time that is defined for this in-group. Default is DISABLED. If one of the PRESS_ options is selected, it will play the Press Filename defined below and give the customer the option to press 1 on their phone to leave the queue and run the selected option. The PRESS_CALLBACK_QUEUE option will preserve the caller place in line and will call the customer back when their place is the next one to go to an agent, this inbound callback queue entry will last until the call is placed back to the customer or as long as the Callback Queue Expire Hours setting above.
Closing Time Now Trigger - If Closing Time Action is enabled, this flag allows you to send all customers waiting in the queue to the Closing Time Action as defined above, before the actual closing time is reached for the day.
Closing Time Press Filename - If Closing Time Option is set to one of the PRESS_ options, this is the filename prompt that is played if the in-group has reached the closing time for the day. It is very important that this audio file is 10 seconds or less or there will be problems.
Closing Time End Filename - If Closing Time Option is set to one of the PRESS_ options or PRESS_CID_CALLBACK or PRESS_CALLBACK_QUEUE, this is the filename prompt that is played after the customer has pressed 1 or the call has been added to the callback list or queue.
Closing Time Option Lead Reset - This option if set to Y, will set the lead called-since-last-reset field to N when the Closing Time Option is triggered and the call is sent to an action like Message, Voicemail or Hangup. Default is N for disabled.
Closing Time Option Extension - If Closing Time Option is set to EXTENSION, this is the dialplan extension that the call will be sent to if the Closing Time is reached. For AGENTDIRECT in-groups, you can put AGENTEXT in this field and the system will look up the user custom five field and send the call to that dialplan number.
Closing Time Option Callmenu - If Closing Time Option is set to CALL_MENU, this is the Call Menu that the call will be sent to if the Closing Time is reached.
Closing Time Option Voicemail - If Closing Time Option is set to VOICEMAIL, this is the voicemail box that the call will be sent to if the Closing Time is reached. In an AGENTDIRECT in-group, setting this to AGENTVMAIL will select the User voicemail ID to use.
Closing Time Option Transfer In-Group - If Closing Time Option is set to IN_GROUP, this is the inbound group that the call will be sent to if the Closing Time is reached.
Closing Time Option Callback List ID - If Closing Time Option is set to CALLERID_CALLBACK, this is the List ID the call is added to as a new lead if the Closing Time is reached.
+1
View File
@@ -74,3 +74,4 @@ UNKXFR - CPD Unknown result Transfer to Call Menu or In-Group
UNKAM - CPD Unknown call sent to a message to be played
UNKAL - CPD Unknown call sent to a message and message has been played
NVAINS - Default status for new inserted lead on phone NVA call
CLOSOP - In-Group Closing-Time option selected
+36 -3
View File
@@ -510,7 +510,7 @@ processed ENUM('Y','N'),
queue_seconds DECIMAL(7,2) default '0',
user_group VARCHAR(20),
xfercallid INT(9) UNSIGNED,
term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER') default 'NONE',
term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER','CLOSETIME') default 'NONE',
uniqueid VARCHAR(20) NOT NULL default '',
agent_only VARCHAR(20) default '',
queue_position SMALLINT(4) UNSIGNED default '1',
@@ -1237,7 +1237,21 @@ inbound_survey ENUM('DISABLED','ENABLED') default 'DISABLED',
inbound_survey_filename TEXT,
inbound_survey_accept_digit VARCHAR(1) default '',
inbound_survey_question_filename TEXT,
inbound_survey_callmenu TEXT
inbound_survey_callmenu TEXT,
icbq_expiration_hours SMALLINT(5) default '96',
closing_time_action VARCHAR(30) default 'DISABLED',
closing_time_now_trigger ENUM('Y','N') default 'N',
closing_time_filename TEXT,
closing_time_end_filename TEXT,
closing_time_lead_reset ENUM('Y','N') default 'N',
closing_time_option_exten VARCHAR(20) default '8300',
closing_time_option_callmenu VARCHAR(50) default '',
closing_time_option_voicemail VARCHAR(20) default '',
closing_time_option_xfer_group VARCHAR(20) default '---NONE---',
closing_time_option_callback_list_id BIGINT(14) UNSIGNED default '999',
add_lead_timezone ENUM('SERVER','PHONE_CODE_AREACODE') default 'SERVER',
icbq_call_time_id VARCHAR(20) default '24hours',
icbq_dial_filter VARCHAR(50) default 'NONE'
) ENGINE=MyISAM;
CREATE TABLE vicidial_stations (
@@ -3851,6 +3865,22 @@ index (serial_id),
index (run_time)
) ENGINE=MyISAM;
CREATE TABLE vicidial_inbound_callback_queue (
icbq_id INT(9) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
icbq_date DATETIME,
icbq_status VARCHAR(10),
icbq_phone_number VARCHAR(20),
icbq_phone_code VARCHAR(10),
icbq_nextday_choice ENUM('Y','N','U') default 'U',
lead_id INT(9) UNSIGNED NOT NULL,
group_id VARCHAR(20) NOT NULL,
queue_priority TINYINT(2) default '0',
call_date DATETIME,
gmt_offset_now DECIMAL(4,2) DEFAULT '0.00',
modify_date TIMESTAMP,
index (icbq_status)
) ENGINE=MyISAM;
ALTER TABLE vicidial_email_list MODIFY message text character set utf8;
@@ -4056,6 +4086,9 @@ ALTER TABLE user_call_log_archive MODIFY user_call_log_id INT(9) UNSIGNED NOT NU
CREATE TABLE vicidial_inbound_survey_log_archive LIKE vicidial_inbound_survey_log;
CREATE UNIQUE INDEX visla_key on vicidial_inbound_survey_log_archive(uniqueid, call_date, campaign_id, lead_id);
CREATE TABLE vicidial_inbound_callback_queue_archive LIKE vicidial_inbound_callback_queue;
ALTER TABLE vicidial_inbound_callback_queue_archive MODIFY icbq_id INT(9) UNSIGNED NOT NULL;
GRANT RELOAD ON *.* TO cron@'%';
GRANT RELOAD ON *.* TO cron@localhost;
@@ -4132,4 +4165,4 @@ INSERT INTO vicidial_settings_containers(container_id,container_notes,container_
UPDATE system_settings set vdc_agent_api_active='1';
UPDATE system_settings SET db_schema_version='1533',db_schema_update_date=NOW(),reload_timestamp=NOW();
UPDATE system_settings SET db_schema_version='1534',db_schema_update_date=NOW(),reload_timestamp=NOW();
+41 -2
View File
@@ -70,8 +70,8 @@ areacode VARCHAR(6) NOT NULL,
index(group_id)
) ENGINE=MyISAM;
ALTER TABLE vicidial_closer_log MODIFY term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER') default 'NONE';
ALTER TABLE vicidial_closer_log_archive MODIFY term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER') default 'NONE';
ALTER TABLE vicidial_closer_log MODIFY term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER','CLOSETIME') default 'NONE';
ALTER TABLE vicidial_closer_log_archive MODIFY term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER','CLOSETIME') default 'NONE';
UPDATE system_settings SET db_schema_version='1490',db_schema_update_date=NOW() where db_schema_version < 1490;
@@ -501,3 +501,42 @@ ALTER TABLE vicidial_campaigns ADD inbound_no_agents_no_dial_threshold SMALLINT(
ALTER TABLE vicidial_settings_containers MODIFY container_type VARCHAR(40) default 'OTHER';
UPDATE system_settings SET db_schema_version='1533',db_schema_update_date=NOW() where db_schema_version < 1533;
CREATE TABLE vicidial_inbound_callback_queue (
icbq_id INT(9) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
icbq_date DATETIME,
icbq_status VARCHAR(10),
icbq_phone_number VARCHAR(20),
icbq_phone_code VARCHAR(10),
icbq_nextday_choice ENUM('Y','N','U') default 'U',
lead_id INT(9) UNSIGNED NOT NULL,
group_id VARCHAR(20) NOT NULL,
queue_priority TINYINT(2) default '0',
call_date DATETIME,
gmt_offset_now DECIMAL(4,2) DEFAULT '0.00',
modify_date TIMESTAMP,
index (icbq_status)
) ENGINE=MyISAM;
CREATE TABLE vicidial_inbound_callback_queue_archive LIKE vicidial_inbound_callback_queue;
ALTER TABLE vicidial_inbound_callback_queue_archive MODIFY icbq_id INT(9) UNSIGNED NOT NULL;
ALTER TABLE vicidial_inbound_groups ADD icbq_expiration_hours SMALLINT(5) default '96';
ALTER TABLE vicidial_inbound_groups ADD closing_time_action VARCHAR(30) default 'DISABLED';
ALTER TABLE vicidial_inbound_groups ADD closing_time_now_trigger ENUM('Y','N') default 'N';
ALTER TABLE vicidial_inbound_groups ADD closing_time_filename TEXT;
ALTER TABLE vicidial_inbound_groups ADD closing_time_end_filename TEXT;
ALTER TABLE vicidial_inbound_groups ADD closing_time_lead_reset ENUM('Y','N') default 'N';
ALTER TABLE vicidial_inbound_groups ADD closing_time_option_exten VARCHAR(20) default '8300';
ALTER TABLE vicidial_inbound_groups ADD closing_time_option_callmenu VARCHAR(50) default '';
ALTER TABLE vicidial_inbound_groups ADD closing_time_option_voicemail VARCHAR(20) default '';
ALTER TABLE vicidial_inbound_groups ADD closing_time_option_xfer_group VARCHAR(20) default '---NONE---';
ALTER TABLE vicidial_inbound_groups ADD closing_time_option_callback_list_id BIGINT(14) UNSIGNED default '999';
ALTER TABLE vicidial_inbound_groups ADD add_lead_timezone ENUM('SERVER','PHONE_CODE_AREACODE') default 'SERVER';
ALTER TABLE vicidial_inbound_groups ADD icbq_call_time_id VARCHAR(20) default '24hours';
ALTER TABLE vicidial_inbound_groups ADD icbq_dial_filter VARCHAR(50) default 'NONE';
ALTER TABLE vicidial_closer_log MODIFY term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER','CLOSETIME') default 'NONE';
ALTER TABLE vicidial_closer_log_archive MODIFY term_reason ENUM('CALLER','AGENT','QUEUETIMEOUT','ABANDON','AFTERHOURS','HOLDRECALLXFER','HOLDTIME','NOAGENT','NONE','MAXCALLS','ACFILTER','CLOSETIME') default 'NONE';
UPDATE system_settings SET db_schema_version='1534',db_schema_update_date=NOW() where db_schema_version < 1534;
+21 -5
View File
@@ -92,10 +92,11 @@
# 170527-2250 - Fix for rare inbound logging issue #1017, Added variable filtering
# 170815-1314 - Added HTTP error code 418
# 180124-1608 - Added calls_in_queue_count function
# 180204-2350 - Added dial_ingroup external_dial option
#
$version = '2.14-58';
$build = '180124-1608';
$version = '2.14-59';
$build = '180204-2350';
$startMS = microtime();
@@ -234,6 +235,8 @@ if (isset($_GET["qm_dispo_code"])) {$qm_dispo_code=$_GET["qm_dispo_code"];}
elseif (isset($_POST["qm_dispo_code"])) {$qm_dispo_code=$_POST["qm_dispo_code"];}
if (isset($_GET["agent_debug"])) {$agent_debug=$_GET["agent_debug"];}
elseif (isset($_POST["agent_debug"])) {$agent_debug=$_POST["agent_debug"];}
if (isset($_GET["dial_ingroup"])) {$dial_ingroup=$_GET["dial_ingroup"];}
elseif (isset($_POST["dial_ingroup"])) {$dial_ingroup=$_POST["dial_ingroup"];}
header ("Content-type: text/html; charset=utf-8");
@@ -357,6 +360,7 @@ if ($non_latin < 1)
$postal_code = preg_replace("/[^- \.\_0-9a-zA-Z]/","",$postal_code);
$agent_debug = preg_replace("/[^- \.\:\|\_0-9a-zA-Z]/","",$agent_debug);
$status = preg_replace("/[^-\_0-9a-zA-Z]/","",$status);
$dial_ingroup = preg_replace("/[^-\_0-9a-zA-Z]/","",$dial_ingroup);
}
else
{
@@ -1618,7 +1622,19 @@ if ($function == 'external_dial')
{
$agent_ready=1;
}
if ($agent_ready > 0)
$stmt = "select count(*) from vicidial_inbound_groups where group_id='$dial_ingroup';";
if ($DB) {echo "$stmt\n";}
$rslt=mysql_to_mysqli($stmt, $link);
$row=mysqli_fetch_row($rslt);
if ($row[0] < 1)
{
$result = _QXZ("ERROR");
$result_reason = _QXZ("defined dial_ingroup not found");
echo "$result: $result_reason - $dial_ingroup\n";
api_log($link,$api_logging,$api_script,$user,$agent_user,$function,$value,$result,$result_reason,$source,$data);
$dial_ingroup='';
}
if ( ($agent_ready > 0) or (strlen($dial_ingroup)>0) )
{
$stmt = "select count(*) from vicidial_users where user='$agent_user' and agentcall_manual='1';";
if ($DB) {echo "$stmt\n";}
@@ -1829,7 +1845,7 @@ if ($function == 'external_dial')
### If no errors, run the update to place the call ###
if ($api_manual_dial=='STANDARD')
{
$stmt="UPDATE vicidial_live_agents set external_dial='$value!$phone_code!$search!$preview!$focus!$vendor_id!$epoch!$dial_prefix!$group_alias!$caller_id_number!$vtiger_callback_id!$lead_id!$alt_dial' where user='$agent_user';";
$stmt="UPDATE vicidial_live_agents set external_dial='$value!$phone_code!$search!$preview!$focus!$vendor_id!$epoch!$dial_prefix!$group_alias!$caller_id_number!$vtiger_callback_id!$lead_id!$alt_dial!$dial_ingroup' where user='$agent_user';";
$success=1;
}
else
@@ -1840,7 +1856,7 @@ if ($function == 'external_dial')
$row=mysqli_fetch_row($rslt);
if ($row[0] < 1)
{
$stmt="INSERT INTO vicidial_manual_dial_queue set user='$agent_user',phone_number='$value',entry_time=NOW(),status='READY',external_dial='$value!$phone_code!$search!$preview!$focus!$vendor_id!$epoch!$dial_prefix!$group_alias!$caller_id_number!$vtiger_callback_id!$lead_id!$alt_dial';";
$stmt="INSERT INTO vicidial_manual_dial_queue set user='$agent_user',phone_number='$value',entry_time=NOW(),status='READY',external_dial='$value!$phone_code!$search!$preview!$focus!$vendor_id!$epoch!$dial_prefix!$group_alias!$caller_id_number!$vtiger_callback_id!$lead_id!$alt_dial!$dial_ingroup';";
$success=1;
}
else
+11 -4
View File
@@ -445,13 +445,14 @@
# 171224-1222 - Added List default_xfer_group override
# 180108-2048 - Added next_dial_my_callbacks feature
# 180131-1116 - Fixed ereg issue
# 180204-1651 - Added update for inbound callback queue functionality
#
$version = '2.14-339';
$build = '180131-1116';
$version = '2.14-340';
$build = '180204-1651';
$php_script = 'vdc_db_query.php';
$mel=1; # Mysql Error Log enabled = 1
$mysql_log_count=708;
$mysql_log_count=709;
$one_mysql_log=0;
$DB=0;
$VD_login=0;
@@ -7897,6 +7898,12 @@ if ($ACTION == 'VDADcheckINCOMING')
$retry_count++;
}
### update vicidial_inbound_callback_queue record to SENT if one exists in SENDING state for this lead_id
$stmt = "UPDATE vicidial_inbound_callback_queue set icbq_status='SENT' where lead_id='$lead_id' and icbq_status='SENDING' order by icbq_date limit 1;";
if ($DB) {echo "$stmt\n";}
$rslt=mysql_to_mysqli($stmt, $link);
if ($mel > 0) {mysql_error_logging($NOW_TIME,$link,$mel,$stmt,'00709',$user,$server_ip,$session_name,$one_mysql_log);}
$stmt = "UPDATE vicidial_campaign_agents set calls_today='$calls_today' where user='$user' and campaign_id='$campaign';";
if ($DB) {echo "$stmt\n";}
$rslt=mysql_to_mysqli($stmt, $link);
@@ -9368,7 +9375,7 @@ if ($ACTION == 'VDADcheckINCOMINGother')
$row=mysqli_fetch_row($rslt);
$get_call_launch = $row[0];
}
if (!preg_match("/EMAIL|SCRIPT/",$get_call_launch))
if (!preg_match("/EMAIL|SCRIPT|WEBFORM/",$get_call_launch))
{$get_call_launch='EMAIL';}
# Change to better suit the output processed by the agent interface
echo "1\n" . $lead_id . '|'.$uniqueid.'|' . $email_from . '|' . $get_call_launch . '|' . $email_row_id . '|' . $email_row_id . "|EMAIL\n"; # VDIC_data_VDAC
+5 -3
View File
@@ -577,10 +577,11 @@
# 171224-1244 - Added List default_xfer_group override
# 180105-1543 - Small javascript fixes, and more debug logging, change to 2018
# 180126-0855 - Added more agent api pause debug output
# 180204-2304 - Added API dial_ingroup option to external_dial
#
$version = '2.14-547c';
$build = '180126-0855';
$version = '2.14-548c';
$build = '180204-2304';
$mel=1; # Mysql Error Log enabled = 1
$mysql_log_count=87;
$one_mysql_log=0;
@@ -5875,6 +5876,7 @@ function set_length(SLnumber,SLlength_goal,SLdirection)
vtiger_callback_id = APIDiaL_array_detail[10];
document.vicidial_form.MDLeadID.value = APIDiaL_array_detail[11];
document.vicidial_form.MDType.value = APIDiaL_array_detail[12];
active_ingroup_dial = APIDiaL_array_detail[13];
// alert(APIDiaL_array_detail[1] + "-----" + APIDiaL + "-----" + document.vicidial_form.MDDiaLCodE.value + "-----" + document.vicidial_form.phone_code.value);
if (APIDiaL_array_detail[2] == 'YES') // lookup lead in system
@@ -11094,7 +11096,7 @@ function set_length(SLnumber,SLlength_goal,SLdirection)
VDIC_web_form_address_three = VICIDiaL_web_form_address_three;
CalL_AutO_LauncH = VDIC_data_VDAC[3];
if( document.images ) { document.images['livecall'].src = image_livecall_ON.src;}
if ( (CalL_AutO_LauncH=='EMAIL') || (CalL_AutO_LauncH=='SCRIPT') )
if ( (CalL_AutO_LauncH=='EMAIL') || (CalL_AutO_LauncH=='SCRIPT') || (CalL_AutO_LauncH=='WEBFORM') )
{
document.vicidial_form.email_row_id.value= VDIC_data_VDAC[4];
document.getElementById("EmailAudioAlertFile").play();
+72 -26
View File
@@ -1,7 +1,7 @@
<?php
# AST_timeonVDADall.php
#
# Copyright (C) 2017 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
# Copyright (C) 2018 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# live real-time stats for the VICIDIAL Auto-Dialer all servers
#
@@ -107,10 +107,11 @@
# 170321-1145 - Added pause code time limits colors
# 170409-1556 - Added IP List validation code
# 170615-0023 - Added DIAL status for manual dial agent calls that have not been answered
# 180204-1538 - Added display of LIVE Inbound Callback Queue Calls
#
$version = '2.14-95';
$build = '170615-0023';
$version = '2.14-96';
$build = '180204-1538';
header ("Content-type: text/html; charset=utf-8");
@@ -1270,10 +1271,8 @@ if ($droppedOFtotal > 0)
##### SHOW IN-GROUP STATS OR INBOUND ONLY WITH VIEW-MORE ###
if ( ($ALLINGROUPstats > 0) or ( (preg_match('/O/',$with_inbound)) and ($adastats > 1) ) )
{
$stmtB="SELECT calls_today,drops_today,$answers_singleSQL,status_category_1,status_category_count_1,status_category_2,status_category_count_2,status_category_3,status_category_count_3,status_category_4,status_category_count_4,hold_sec_stat_one,hold_sec_stat_two,hold_sec_answer_calls,hold_sec_drop_calls,hold_sec_queue_calls,campaign_id from vicidial_campaign_stats where campaign_id IN ($closer_campaignsSQL) order by campaign_id;";
$stmtB="SELECT campaign_id from vicidial_campaign_stats where campaign_id IN ($closer_campaignsSQL) order by campaign_id;";
if ($DB > 0) {echo "\n|$stmtB|\n";}
$r=0;
$rslt=mysql_to_mysqli($stmtB, $link);
$ingroups_to_print = mysqli_num_rows($rslt);
@@ -1282,23 +1281,41 @@ if ( ($ALLINGROUPstats > 0) or ( (preg_match('/O/',$with_inbound)) and ($adastat
while ($ingroups_to_print > $r)
{
$row=mysqli_fetch_row($rslt);
$callsTODAY = $row[0];
$dropsTODAY = $row[1];
$answersTODAY = $row[2];
$VSCcat1 = $row[3];
$VSCcat1tally = $row[4];
$VSCcat2 = $row[5];
$VSCcat2tally = $row[6];
$VSCcat3 = $row[7];
$VSCcat3tally = $row[8];
$VSCcat4 = $row[9];
$VSCcat4tally = $row[10];
$hold_sec_stat_one = $row[11];
$hold_sec_stat_two = $row[12];
$hold_sec_answer_calls = $row[13];
$hold_sec_drop_calls = $row[14];
$hold_sec_queue_calls = $row[15];
$ingroupdetail = $row[16];
$ARYingroupdetail[$r] = $row[0];
$r++;
}
$r=0;
while ($ingroups_to_print > $r)
{
$stmtB="SELECT calls_today,drops_today,$answers_singleSQL,status_category_1,status_category_count_1,status_category_2,status_category_count_2,status_category_3,status_category_count_3,status_category_4,status_category_count_4,hold_sec_stat_one,hold_sec_stat_two,hold_sec_answer_calls,hold_sec_drop_calls,hold_sec_queue_calls,campaign_id from vicidial_campaign_stats where campaign_id='$ARYingroupdetail[$r]';";
if ($DB > 0) {echo "\n|$stmtB|\n";}
$rslt=mysql_to_mysqli($stmtB, $link);
$ingroup_to_print = mysqli_num_rows($rslt);
if ($ingroup_to_print > 0)
{
$row=mysqli_fetch_row($rslt);
$callsTODAY = $row[0];
$dropsTODAY = $row[1];
$answersTODAY = $row[2];
$VSCcat1 = $row[3];
$VSCcat1tally = $row[4];
$VSCcat2 = $row[5];
$VSCcat2tally = $row[6];
$VSCcat3 = $row[7];
$VSCcat3tally = $row[8];
$VSCcat4 = $row[9];
$VSCcat4tally = $row[10];
$hold_sec_stat_one = $row[11];
$hold_sec_stat_two = $row[12];
$hold_sec_answer_calls = $row[13];
$hold_sec_drop_calls = $row[14];
$hold_sec_queue_calls = $row[15];
$ingroupdetail = $row[16];
}
$drpctTODAY = ( MathZDC($dropsTODAY, $answersTODAY) * 100);
$drpctTODAY = round($drpctTODAY, 2);
$drpctTODAY = sprintf("%01.2f", $drpctTODAY);
@@ -1321,6 +1338,19 @@ if ( ($ALLINGROUPstats > 0) or ( (preg_match('/O/',$with_inbound)) and ($adastat
$AVG_ANSWERagent_non_pause_sec = round($AVG_ANSWERagent_non_pause_sec, 2);
$AVG_ANSWERagent_non_pause_sec = sprintf("%01.2f", $AVG_ANSWERagent_non_pause_sec);
$Dicbq_stmt="SELECT count(*) from vicidial_inbound_callback_queue where icbq_status='LIVE' and group_id='$ARYingroupdetail[$r]';";
$Dicbq_rslt=mysql_to_mysqli($Dicbq_stmt, $link);
$Dicbq_ct = mysqli_num_rows($Dicbq_rslt);
$Dicbq_live=0;
if ($Dicbq_ct > 0)
{
$Dicbq_ARY=mysqli_fetch_row($Dicbq_rslt);
if ($Dicbq_ARY[0] > 0)
{
$Dicbq_live = "<font color=red><b>$Dicbq_ARY[0]</b></font>";
}
}
if (preg_match('/0$|2$|4$|6$|8$/',$r)) {$bgcolor='#E6E6E6';}
else {$bgcolor='white';}
$ingroup_detail .= "<TR bgcolor=\"$bgcolor\">";
@@ -1329,18 +1359,21 @@ if ( ($ALLINGROUPstats > 0) or ( (preg_match('/O/',$with_inbound)) and ($adastat
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("CALLS TODAY").":</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $callsTODAY&nbsp; &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("TMA")." 1</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $PCThold_sec_stat_one% &nbsp; &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("Average Hold time for Answered Calls").":</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $AVGhold_sec_answer_calls &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'> &nbsp; "._QXZ("LIVE Inbound Callback Queue Calls").":</font><font class='top_settings_val'>&nbsp; $Dicbq_live &nbsp; </TD>";
$ingroup_detail .= "</TR>";
$ingroup_detail .= "<TR bgcolor=\"$bgcolor\">";
$ingroup_detail .= "<TD ALIGN=RIGHT bgcolor=white><font class='top_settings_val'></TD><TD ALIGN=LEFT><font class='top_settings_val'></TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("DROPS TODAY").":</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $dropsTODAY&nbsp; &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("TMA")." 2:</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $PCThold_sec_stat_two% &nbsp; &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("Average Hold time for Dropped Calls").":</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $AVGhold_sec_drop_calls &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT bgcolor=white><font class='top_settings_val'></TD><TD ALIGN=LEFT><font class='top_settings_val'></TD>";
$ingroup_detail .= "</TR>";
$ingroup_detail .= "<TR bgcolor=\"$bgcolor\">";
$ingroup_detail .= "<TD ALIGN=RIGHT bgcolor=white><font class='top_settings_val'></TD><TD ALIGN=LEFT><font class='top_settings_val'></TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("ANSWERS TODAY").":</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $answersTODAY&nbsp; &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("DROP PERCENT").":</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $drpctTODAY%&nbsp; &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT><font class='top_settings_key'>"._QXZ("Average Hold time for All Calls").":</font></TD><TD ALIGN=LEFT><font class='top_settings_val'>&nbsp; $AVGhold_sec_queue_calls &nbsp; </TD>";
$ingroup_detail .= "<TD ALIGN=RIGHT bgcolor=white><font class='top_settings_val'></TD><TD ALIGN=LEFT><font class='top_settings_val'></TD>";
$ingroup_detail .= "</TR>";
$r++;
@@ -2338,6 +2371,14 @@ if ($allow_chats)
}
}
$icbq_stmt="SELECT count(*) from vicidial_inbound_callback_queue where icbq_status='LIVE' and group_id IN($closer_campaignsSQL);";
$icbq_rslt=mysql_to_mysqli($icbq_stmt, $link);
$icbq_ct = mysqli_num_rows($icbq_rslt);
if ($icbq_ct > 0)
{
$icbq_ARY=mysqli_fetch_row($icbq_rslt);
$icbq_live = $icbq_ARY[0];
}
##### BEGIN HTML output for calls #####
if ( ($report_display_type=='HTML') or ($report_display_type=='WALL_2') )
@@ -2378,8 +2419,13 @@ if ( ($report_display_type=='HTML') or ($report_display_type=='WALL_2') )
echo "<td align='center' valign='middle' rowspan=2>&nbsp;</td>";
echo "<td align='center' valign='middle'><font style=\"font-family:HELVETICA;font-size:11;color:white;font-weight:bold;\">&nbsp;</font></td>";
}
echo "<td align='center' valign='middle' rowspan=2>&nbsp;</td>";
echo "<td align='center' valign='middle'><font style=\"font-family:HELVETICA;font-size:11;color:white;font-weight:bold;\">&nbsp;</font></td>";
# echo "<td align='center' valign='middle' rowspan=2>&nbsp;</td>";
echo "<td width=6 rowspan=2> &nbsp; </td>";
echo "<td align='center' valign='middle' bgcolor='#015b91' rowspan=2><img src=\"images/icon_callswaiting.png\" width=42 height=42></td>";
echo "<td align='center' valign='middle' bgcolor='#015b91'><font style=\"font-family:HELVETICA;font-size:11;color:white;font-weight:bold;\">"._QXZ("callback queue calls")."</font></td>";
echo "</tr>";
echo "<tr>";
echo "<td align='center' valign='middle' bgcolor='#015b91'><font style=\"font-family:HELVETICA;font-size:18;color:white;font-weight:bold;\">$out_total</font></td>";
@@ -2406,7 +2452,7 @@ if ( ($report_display_type=='HTML') or ($report_display_type=='WALL_2') )
{
echo "<td align='center' valign='middle'><font style=\"font-family:HELVETICA;font-size:18;color:white;font-weight:bold;\">&nbsp;</font></td>";
}
# echo "<td align='center' valign='middle'><font style=\"font-family:HELVETICA;font-size:18;color:white;font-weight:bold;\">&nbsp;</font></td>";
echo "<td align='center' valign='middle' bgcolor='#015b91'><font style=\"font-family:HELVETICA;font-size:18;color:white;font-weight:bold;\">$icbq_live</font></td>";
echo "</tr>";
echo "<tr><td colspan=17><font style=\"font-family:HELVETICA;font-size:6;color:white;\">&nbsp;</font></td></tr>";
# echo "</TABLE>";
+172 -18
View File
File diff suppressed because one or more lines are too long
+16
View File
@@ -1333,6 +1333,22 @@ function use_archive_table($table_name)
}
}
function table_exists($table_name)
{
global $link;
$tbl_stmt="show tables like '".$table_name."'";
$tbl_rslt=mysql_to_mysqli($tbl_stmt, $link);
if (mysqli_num_rows($tbl_rslt)>0)
{
$tbl_row=mysqli_fetch_row($tbl_rslt);
return $tbl_row[0];
}
else
{
return false;
}
}
# function to print/echo content, options for length, alignment and ordered internal variables are included
function _QXZ($English_text, $sprintf=0, $align="l", $v_one='', $v_two='', $v_three='', $v_four='', $v_five='', $v_six='', $v_seven='', $v_eight='', $v_nine='')
{
+90 -4
View File
@@ -149,6 +149,7 @@
# 180108-2115 - Added campaigns-next_dial_my_callbacks entry
# 180111-1547 - Added settings-anyone_callback_inactive_lists entry
# 180130-2303 - Added inbound_no_agents_no_dial entries
# 180204-0213 - Added inbound_groups-icbq_expiration_hours and closed-time entries
#
require("dbconnect_mysqli.php");
@@ -2488,6 +2489,11 @@ if ($SSqc_features_active > 0)
<BR>
<B><?php echo _QXZ("Admin User Group"); ?> -</B><?php echo _QXZ("This is the administrative user group for this inbound group, this allows admin viewing of this in-group restricted by user group. Default is --ALL-- which allows any admin user to view this in-group."); ?>
<BR>
<A NAME="inbound_groups-callback_queue_calls">
<BR>
<B><?php echo _QXZ("Callback Queue Calls"); ?> -</B><?php echo _QXZ("This will only show up if there are LIVE inbound callback queue calls waiting to be called back by agents when their turn arrives."); ?>
<BR>
<A NAME="inbound_groups-group_calldate">
<BR>
@@ -2792,7 +2798,7 @@ if ($SSqc_features_active > 0)
<BR>
<A NAME="inbound_groups-wait_time_option">
<BR>
<B><?php echo _QXZ("Wait Time Option"); ?> -</B><?php echo _QXZ("This allows you to give customers options to leave the queue if their wait time is over the amount of seconds specified below. Default is NONE. If one of the PRESS_ options is selected, it will play the Press Filename defined below and give the customer the option to press 1 on their phone to leave the queue and run the selected option. The PRESS_STAY option will send the customer back to the queue without loosing their place in line."); ?>
<B><?php echo _QXZ("Wait Time Option"); ?> -</B><?php echo _QXZ("This allows you to give customers options to leave the queue if their wait time is over the amount of seconds specified below. Default is NONE. If one of the PRESS_ options is selected, it will play the Press Filename defined below and give the customer the option to press 1 on their phone to leave the queue and run the selected option. The PRESS_STAY option will send the customer back to the queue without loosing their place in line. The PRESS_CALLBACK_QUEUE option will preserve the caller place in line and will call the customer back when their place is the next one to go to an agent, this inbound callback queue entry will last until the call is placed back to the customer or as long as the Callback Queue Expire Hours setting below."); ?>
<BR>
<A NAME="inbound_groups-wait_time_second_option">
@@ -2867,7 +2873,7 @@ if ($SSqc_features_active > 0)
<BR>
<A NAME="inbound_groups-hold_time_option">
<BR>
<B><?php echo _QXZ("Estimated Hold Time Option"); ?> -</B><?php echo _QXZ("This allows you to specify the routing of the call if the estimated hold time is over the amount of seconds specified below. Default is NONE. If one of the PRESS_ options is selected, it will play the Press Filename defined below and give the customer the option to press 1 on their phone to leave the queue and run the selected option."); ?>
<B><?php echo _QXZ("Estimated Hold Time Option"); ?> -</B><?php echo _QXZ("This allows you to specify the routing of the call if the estimated hold time is over the amount of seconds specified below. Default is NONE. If one of the PRESS_ options is selected, it will play the Press Filename defined below and give the customer the option to press 1 on their phone to leave the queue and run the selected option. The PRESS_CALLBACK_QUEUE option will preserve the caller place in line and will call the customer back when their place is the next one to go to an agent, this inbound callback queue entry will last until the call is placed back to the customer or as long as the Callback Queue Expire Hours setting below."); ?>
<BR>
<A NAME="inbound_groups-hold_time_second_option">
@@ -2939,6 +2945,71 @@ if ($SSqc_features_active > 0)
<BR>
<B><?php echo _QXZ("Hold Time Option Callback List ID"); ?> -</B><?php echo _QXZ("If Hold Time Option is set to CALLERID_CALLBACK, this is the List ID the call is added to as a new lead if the estimated hold time exceeds the Hold Time Option Seconds."); ?>
<BR>
<A NAME="inbound_groups-icbq_expiration_hours">
<BR>
<B><?php echo _QXZ("Callback Queue Expire Hours"); ?> -</B><?php echo _QXZ("If a Hold Time or Wait Time Option is set to PRESS_CALLBACK_QUEUE, this is the maximum number of hours that an entry can stay in the inbound callback queue before it is removed without dialing it. Default is 96 hours."); ?>
<BR>
<A NAME="inbound_groups-icbq_call_time_id">
<BR>
<B><?php echo _QXZ("Callback Queue Call Time"); ?> -</B><?php echo _QXZ("For any inbound callback queue outbound calls to be placed, this is the local call time used to determine if the number can be dialed right now or not."); ?>
<BR>
<A NAME="inbound_groups-icbq_dial_filter">
<BR>
<B><?php echo _QXZ("Callback Queue Dial Filter"); ?> -</B><?php echo _QXZ("This option allows you to remove DNC numbers from your Callback Queue. You can use any combination of: Internal DNC List, Campaign DNC List tied to campaign of the list where the lead is, and Areacode DNC wildcard"); ?>
<BR>
<A NAME="inbound_groups-closing_time_action">
<BR>
<B><?php echo _QXZ("Closing Time Action"); ?> -</B><?php echo _QXZ("This allows you to specify the routing of the call if the closing time of the in-group is reached while the call is still waiting for an agent, Closing time is the end of the Call Time that is defined for this in-group. Default is DISABLED. If one of the PRESS_ options is selected, it will play the Press Filename defined below and give the customer the option to press 1 on their phone to leave the queue and run the selected option. The PRESS_CALLBACK_QUEUE option will preserve the caller place in line and will call the customer back when their place is the next one to go to an agent, this inbound callback queue entry will last until the call is placed back to the customer or as long as the Callback Queue Expire Hours setting above."); ?>
<BR>
<A NAME="inbound_groups-closing_time_now_trigger">
<BR>
<B><?php echo _QXZ("Closing Time Now Trigger"); ?> -</B><?php echo _QXZ("If Closing Time Action is enabled, this flag allows you to send all customers waiting in the queue to the Closing Time Action as defined above, before the actual closing time is reached for the day."); ?>
<BR>
<A NAME="inbound_groups-closing_time_filename">
<BR>
<B><?php echo _QXZ("Closing Time Press Filename"); ?> -</B><?php echo _QXZ("If Closing Time Option is set to one of the PRESS_ options, this is the filename prompt that is played if the in-group has reached the closing time for the day. It is very important that this audio file is 10 seconds or less or there will be problems."); ?>
<BR>
<A NAME="inbound_groups-closing_time_end_filename">
<BR>
<B><?php echo _QXZ("Closing Time End Filename"); ?> -</B><?php echo _QXZ("If Closing Time Option is set to one of the PRESS_ options or PRESS_CID_CALLBACK or PRESS_CALLBACK_QUEUE, this is the filename prompt that is played after the customer has pressed 1 or the call has been added to the callback list or queue."); ?>
<BR>
<A NAME="inbound_groups-closing_time_lead_reset">
<BR>
<B><?php echo _QXZ("Closing Time Option Lead Reset"); ?> -</B><?php echo _QXZ("This option if set to Y, will set the lead called-since-last-reset field to N when the Closing Time Option is triggered and the call is sent to an action like Message, Voicemail or Hangup. Default is N for disabled."); ?>
<BR>
<A NAME="inbound_groups-closing_time_option_exten">
<BR>
<B><?php echo _QXZ("Closing Time Option Extension"); ?> -</B><?php echo _QXZ("If Closing Time Option is set to EXTENSION, this is the dialplan extension that the call will be sent to if the Closing Time is reached. For AGENTDIRECT in-groups, you can put AGENTEXT in this field and the system will look up the user custom five field and send the call to that dialplan number."); ?>
<BR>
<A NAME="inbound_groups-closing_time_option_callmenu">
<BR>
<B><?php echo _QXZ("Closing Time Option Callmenu"); ?> -</B><?php echo _QXZ("If Closing Time Option is set to CALL_MENU, this is the Call Menu that the call will be sent to if the Closing Time is reached."); ?>
<BR>
<A NAME="inbound_groups-closing_time_option_voicemail">
<BR>
<B><?php echo _QXZ("Closing Time Option Voicemail"); ?> -</B><?php echo _QXZ("If Closing Time Option is set to VOICEMAIL, this is the voicemail box that the call will be sent to if the Closing Time is reached. In an AGENTDIRECT in-group, setting this to AGENTVMAIL will select the User voicemail ID to use."); ?>
<BR>
<A NAME="inbound_groups-closing_time_option_xfer_group">
<BR>
<B><?php echo _QXZ("Closing Time Option Transfer In-Group"); ?> -</B><?php echo _QXZ("If Closing Time Option is set to IN_GROUP, this is the inbound group that the call will be sent to if the Closing Time is reached."); ?>
<BR>
<A NAME="inbound_groups-closing_time_option_callback_list_id">
<BR>
<B><?php echo _QXZ("Closing Time Option Callback List ID"); ?> -</B><?php echo _QXZ("If Closing Time Option is set to CALLERID_CALLBACK, this is the List ID the call is added to as a new lead if the Closing Time is reached."); ?>
<BR>
<A NAME="inbound_groups-agent_alert_exten">
<BR>
@@ -3034,15 +3105,20 @@ if ($SSqc_features_active > 0)
<BR>
<B><?php echo _QXZ("Dispo Call URL"); ?> -</B><?php echo _QXZ("This web URL address is not seen by the agent, but it is called every time a call is dispositioned by an agent if it is populated. Uses the same variables as the web form fields and scripts. dispo and talk_time are the variables you can use to retrieve the agent-defined disposition for the call and the actual talk time in seconds of the call. Default is blank.") . " " . _QXZ("If you put ALT into this field and submit this form, you will be able to go to a separate page where you can define multiple URLs for this action as well as specific statuses that will trigger them.") . " " . _QXZ("If you want the campaign Dispo Call URL to be used for inbound calls, then put CAMP into this field."); ?>
<BR>
<A NAME="inbound_groups-na_call_url">
<BR>
<B><?php echo _QXZ("No Agent Call URL"); ?> -</B><?php echo _QXZ("This web URL address is not seen by the agent, but if it is populated it is called every time a call that is not handled by an agent is hung up or transferred. Uses the same variables as the web form fields and scripts. dispo can be used to retrieve the system-defined disposition for the call. This URL can NOT be a relative path. Default is blank."); ?> <?php echo _QXZ("Custom Fields are not available with this feature."); ?>
<BR>
<A NAME="inbound_groups-add_lead_url">
<BR>
<B><?php echo _QXZ("Add Lead URL"); ?> -</B><?php echo _QXZ("This web URL address is not seen by the agent, but it is called every time a lead is added to the system through the inbound process. Default is blank. You must begin this URL with VAR if you want to use variables, and of course --A-- and --B-- around the actual variable in the URL where you want to use it. Here is the list of variables that are available for this function. lead_id, vendor_lead_code, list_id, phone_number, phone_code, did_id, did_extension, did_pattern, did_description, uniqueid"); ?>
<BR>
<A NAME="inbound_groups-na_call_url">
<A NAME="inbound_groups-add_lead_timezone">
<BR>
<B><?php echo _QXZ("No Agent Call URL"); ?> -</B><?php echo _QXZ("This web URL address is not seen by the agent, but if it is populated it is called every time a call that is not handled by an agent is hung up or transferred. Uses the same variables as the web form fields and scripts. dispo can be used to retrieve the system-defined disposition for the call. This URL can NOT be a relative path. Default is blank."); ?> <?php echo _QXZ("Custom Fields are not available with this feature."); ?>
<B><?php echo _QXZ("Add Lead Timezone"); ?> -</B><?php echo _QXZ("This is the method that the system will use to determine the current timezone when a lead is created when a call is being routed through this in-group. SERVER will use the current timezone of the server. PHONE_CODE_AREACODE will look up the timezone based on the phone code set in the lead and the areacode of the phone number. Default is SERVER."); ?>
<BR>
<A NAME="inbound_groups-default_group_alias">
@@ -6845,6 +6921,16 @@ if ($SSqc_features_active > 0)
<BR><BR><BR><BR>
<A NAME="api_log_report">
<BR>
<B><?php echo _QXZ("API Log report"); ?> -</B><?php echo _QXZ("This report shows all records in the API logging table that meet the report criteria. Reports can be run by date range that the API was accessed, the user, agent user, the API function called, and the API result. The report can also be run to include the actual URL of the API that was called and the IP address the request came from."); ?>
<BR><BR>
<?php echo _QXZ("Additionally, if this extended version of the report is run, the variables used in the API call can be listed separately if the user creates a system container in the System Containers settings by the name of API_LOG_URL_COLUMNS <B>(name must be exact)</B>. In this container, variable names are listed individually per line, and each listed variable is given it's own column in the detailed URL report."); ?><BR><BR>
<A NAME="api_log_report-parameters">
<BR><BR><BR><BR>
<B><FONT SIZE=3><?php echo _QXZ("Nanpa cellphone filtering"); ?></FONT></B><BR><BR>