Added SHARED_... campaign dial method auto-dial options, for more efficient agent multi-campaign dialing. Read the AGENT_MULTI-CAMPAIGN_DIALING.txt document for more information.

git-svn-id: svn://192.168.202.10@3339 3d104415-ff17-0410-8863-d5cf3c621b8a
This commit is contained in:
mattf
2021-01-02 22:05:07 +00:00
parent d23f5e1dbf
commit e8fff646ab
12 changed files with 600 additions and 73 deletions
+4
View File
@@ -556,6 +556,10 @@ OTHER CHANGES:
157. Added Transfer-Conf Button Launch campaign setting, allowing you to set a
webform window to open when an agent clicks on the Transfer-Conf button.
158. Added SHARED_... campaign dial method auto-dial options, for more efficient
agent multi-campaign dialing. Read the AGENT_MULTI-CAMPAIGN_DIALING.txt
document for more information.
+28 -1
View File
@@ -143,9 +143,10 @@
# 200425-0218 - Added purging of vicidial_lead_messages after 1 day
# 200623-2304 - Added Answer Signal options
# 201123-1651 - Added reset of vicidial_lead_call_daily_counts table
# 201218-2054 - Added reset of vicidial_agent_dial_campaigns table
#
$build = '201123-1651';
$build = '201218-2054';
$DB=0; # Debug flag
$teodDB=0; # flag to log Timeclock End of Day processes to log file
@@ -232,7 +233,18 @@ if ($SXsec < 10) {$SXsec = "0$SXsec";}
$SXSQLdate = "$SXyear-$SXmon-$SXmday $SXhour:$SXmin:$SXsec";
$SXdate = "$SXyear-$SXmon-$SXmday";
### calculate the date and time for 5 minutes ago
$FMtarget = ($secX - 300); # 5 minutes ago
($Fsec,$Fmin,$Fhour,$Fmday,$Fmon,$Fyear,$Fwday,$Fyday,$Fisdst) = localtime($FMtarget);
$Fyear = ($Fyear + 1900);
$Fmon++;
if ($Fmon < 10) {$Fmon = "0$Fmon";}
if ($Fmday < 10) {$Fmday = "0$Fmday";}
if ($Fhour < 10) {$Fhour = "0$Fhour";}
if ($Fmin < 10) {$Fmin = "0$Fmin";}
if ($Fsec < 10) {$Fsec = "0$Fsec";}
$FMSQLdate = "$Fyear-$Fmon-$Fmday $Fhour:$Fmin:$Fsec";
### begin parsing run-time options ###
if (length($ARGV[0])>1)
@@ -1297,6 +1309,21 @@ if ($timeclock_end_of_day_NOW > 0)
if ($DB) {print "|",$aryA[0],"|",$aryA[1],"|",$aryA[2],"|",$aryA[3],"|","\n";}
$sthA->finish();
$stmtA = "delete from vicidial_agent_dial_campaigns where validate_time < \"$FMSQLdate\";";
if($DBX){print STDERR "\n|$stmtA|\n";}
$affected_rows = $dbhA->do($stmtA);
if($DB){print STDERR "\n|$affected_rows vicidial_agent_dial_campaigns records deleted|\n";}
if ($teodDB) {$event_string = "vicidial_agent_dial_campaigns records reset: $affected_rows"; &teod_logger;}
$stmtA = "optimize table vicidial_agent_dial_campaigns;";
if($DBX){print STDERR "\n|$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@aryA = $sthA->fetchrow_array;
if ($DB) {print "|",$aryA[0],"|",$aryA[1],"|",$aryA[2],"|",$aryA[3],"|","\n";}
$sthA->finish();
if ($agents_calls_reset > 0)
{
$stmtA = "delete from vicidial_live_inbound_agents where last_call_finish < \"$TDSQLdate\";";
+209 -7
View File
@@ -53,6 +53,7 @@
# 190722-1004 - Added more logging and log-audit portions to Call Quotas log audit code
# 200811-1600 - Include live agents from other campaigns if they have the campaign Drop-InGroup selected and drop sec < 0
# 201106-2141 - Added calculation and caching of park_log stats per campaign/in-group
# 201214-0857 - Added SHARED_ campaign agent rotation functions
#
# constants
@@ -76,6 +77,7 @@ $SSofcom_uk_drop_calc=0;
$i=0;
$daily_stats=1;
$drop_count_updater=0;
$shared_agent_count_updater=0;
$stat_it=15;
$diff_ratio_updater=0;
$stat_count=1;
@@ -116,6 +118,8 @@ $cwu_any_on=0;
# set to 61 initially so that a baseline drop count is pulled
$drop_count_updater=61;
# set to 61 initially so that a baseline shared agent process is run
$shared_agent_count_updater=61;
$secT = time();
@@ -306,7 +310,7 @@ $dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VA
if ($DBX) {print "CONNECTED TO DATABASE: $VARDB_server|$VARDB_database\n";}
##### gather relevent system settings
$stmtA = "SELECT cache_carrier_stats_realtime,ofcom_uk_drop_calc,call_quota_lead_ranking,use_non_latin from system_settings;";
$stmtA = "SELECT cache_carrier_stats_realtime,ofcom_uk_drop_calc,call_quota_lead_ranking,use_non_latin,allow_shared_dial from system_settings;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -317,6 +321,7 @@ if ($sthArows > 0)
$SSofcom_uk_drop_calc = $aryA[1];
$SScall_quota_lead_ranking = $aryA[2];
$non_latin = $aryA[3];
$SSallow_shared_dial = $aryA[4];
}
$sthA->finish();
@@ -340,6 +345,16 @@ $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthA->finish();
$stmtA = "INSERT IGNORE into vicidial_campaign_stats_debug SET campaign_id='--ALL--',server_ip='SHARED';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthA->finish();
$stmtA = "INSERT IGNORE into vicidial_campaign_stats_debug (campaign_id,server_ip) select campaign_id,'SHARED' from vicidial_campaigns;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthA->finish();
&get_time_now;
@@ -540,14 +555,14 @@ while ($master_loop < $CLIloops)
### Find out how many agents are logged in to a specific campaign
# check if drop-in-group agents should be included ---NONE---
$drop_ingroup_SQL[$i]='';
if ( ($drop_call_seconds[$i] < 0) && ($drop_action[$i] =~ /IN_GROUP/i) && ($drop_inbound_group[$i] !~ /^---NONE---$/) && (length($drop_inbound_group[$i]) > 0) && ($new_agent_multicampaign > 0) )
if ( ($drop_call_seconds[$i] < 0) && ($drop_action[$i] =~ /IN_GROUP/i) && ($drop_inbound_group[$i] !~ /^---NONE---$/) && (length($drop_inbound_group[$i]) > 0) && ($new_agent_multicampaign > 0) && ($dial_method[$i] !~ /SHARED_/i) )
{
$SQL_group_id=$drop_inbound_group[$i]; $SQL_group_id =~ s/_/\\_/gi;
$drop_ingroup_SQL[$i] = " or ( (campaign_id!='$campaign_id[$i]') and (closer_campaigns LIKE \"% $SQL_group_id %\") )";
if ($DB) {print " $campaign_id[$i] Drop In-Group agents included from: $drop_inbound_group[$i]";}
$debug_camp_output .= " $campaign_id[$i] Drop In-Group agents included from: $drop_inbound_group[$i]\n";
}
$stmtA = "SELECT count(*) from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one';";
$stmtA = "SELECT count(*) from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') or (dial_campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -561,7 +576,7 @@ while ($master_loop < $CLIloops)
}
$sthA->finish();
$event_string = "|$campaign_id[$i]|$hopper_level[$i]|$hopper_ready_count|$local_call_time[$i]|$diff_ratio_updater|$drop_count_updater|";
$event_string = "|$campaign_id[$i]|$hopper_level[$i]|$hopper_ready_count|$local_call_time[$i]|$diff_ratio_updater|$drop_count_updater|$shared_agent_count_updater|";
if ($DBX) {print "$i $event_string\n";}
$debug_camp_output .= "$i $event_string\n";
&event_logger;
@@ -677,6 +692,12 @@ while ($master_loop < $CLIloops)
&launch_max_calls_gather;
}
### Update Drop counter every 60 seconds
if ($shared_agent_count_updater >= 60)
{
&shared_agent_process;
}
if ( (($stat_count =~ /00$|50$/) || ($stat_count==1)) )
{
$stmtA = "SELECT cache_carrier_stats_realtime,ofcom_uk_drop_calc from system_settings;";
@@ -698,8 +719,10 @@ while ($master_loop < $CLIloops)
if ($RESETdiff_ratio_updater > 0) {$RESETdiff_ratio_updater=0; $diff_ratio_updater=0;}
if ($RESETdrop_count_updater > 0) {$RESETdrop_count_updater=0; $drop_count_updater=0;}
if ($RESETshared_agent_count_updater > 0) {$RESETshared_agent_count_updater=0; $shared_agent_count_updater=0;}
$diff_ratio_updater = ($diff_ratio_updater + $CLIdelay);
$drop_count_updater = ($drop_count_updater + $CLIdelay);
$shared_agent_count_updater = ($shared_agent_count_updater + $CLIdelay);
@@ -2171,7 +2194,7 @@ sub count_agents_lines
$total_agents_avg[$i]=0;
$stat_differential[$i]=0;
$stmtA = "SELECT count(*),status from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one' group by status;";
$stmtA = "SELECT count(*),status from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') or (dial_campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one' group by status;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -2228,7 +2251,7 @@ sub count_agents_lines
# LIVE CAMPAIGN CALLS RIGHT NOW
if ($daily_stats > 0)
{
$stmtA = "SELECT count(*) from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one' and extension LIKE \"R/%\";";
$stmtA = "SELECT count(*) from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') or (dial_campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one' and extension LIKE \"R/%\";";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -2261,7 +2284,186 @@ sub count_agents_lines
sub shared_agent_process
{
$RESETshared_agent_count_updater++;
$SHARED_campaigns_ct=0;
$SHARED_agents_ct=0;
@SHARED_campaigns=@MT;
@SHARED_campaigns_drop_ig=@MT;
@SHARED_campaigns_agnt_ct=@MT;
@SHARED_campaigns_agnt_dl=@MT;
@SHARED_campaigns_dial_ct=@MT;
@SHARED_agents=@MT;
@SHARED_agents_cig=@MT;
@SHARED_agents_dig=@MT;
$debug_shared_output='';
if ($SSallow_shared_dial > 0)
{
$camp_SHARED_SQL='';
$drop_SHARED_SQL='';
# Get list of active SHARED_ campaigns
$stmtA = "SELECT campaign_id,drop_inbound_group from vicidial_campaigns where active='Y' and dial_method IN('SHARED_RATIO','SHARED_ADAPT_HARD_LIMIT','SHARED_ADAPT_TAPERED','SHARED_ADAPT_AVERAGE');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
while ($sthArows > $SHARED_campaigns_ct)
{
@aryA = $sthA->fetchrow_array;
$camp_SHARED_SQL .= "'$aryA[0]',";
$SHARED_campaigns[$SHARED_campaigns_ct] = $aryA[0];
$SHARED_campaigns_agnt_ct[$SHARED_campaigns_ct] = 0;
$SHARED_campaigns_agnt_dl[$SHARED_campaigns_ct] = 0;
$SHARED_campaigns_dial_ct[$SHARED_campaigns_ct] = 0;
if (length($aryA[1]) > 0)
{
$SHARED_campaigns_drop_ig[$SHARED_campaigns_ct] = $aryA[1];
$SQL_group_id=$aryA[1]; $SQL_group_id =~ s/_/\\_/gi;
$temp_drop_ingroup_SQL = "(closer_campaigns LIKE \"% $SQL_group_id %\")";
if (length($drop_SHARED_SQL) > 10) {$drop_SHARED_SQL .= " or ";}
$drop_SHARED_SQL .= "$temp_drop_ingroup_SQL";
}
else {if ($DBX) {print "Empty Drop In-Group for campaign: $aryA[0]\n";}}
$SHARED_campaigns_ct++;
}
$sthA->finish();
chop($camp_SHARED_SQL);
if (length($camp_SHARED_SQL)<2)
{$camp_SHARED_SQL="'-NONE-'";}
if (length($drop_SHARED_SQL)<2)
{$drop_SHARED_SQL="closer_campaigns='----------'";}
$drop_SHARED_SQL = "and ($drop_SHARED_SQL)";
$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";
$agent_SHARED_SQL='';
# Get list of active SHARED_ campaigns
$stmtA = "SELECT user,closer_campaigns,dial_campaign_id from vicidial_live_agents where last_update_time > '$BDtsSQLdate' $drop_SHARED_SQL;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($DBX) {print "$sthArows|$stmtA|\n";}
$SHARED_agents_ct=0;
while ($sthArows > $SHARED_agents_ct)
{
@aryA = $sthA->fetchrow_array;
$SHARED_agents[$SHARED_agents_ct] = $aryA[0];
$SHARED_agents_cig[$SHARED_agents_ct] = $aryA[1];
$SHARED_agents_dig[$SHARED_agents_ct] = $aryA[2];
$agent_SHARED_SQL .= "'$aryA[0]',";
$SHARED_agents_ct++;
}
$sthA->finish();
chop($agent_SHARED_SQL);
if (length($agent_SHARED_SQL)<2)
{$agent_SHARED_SQL="'-NONE-'";}
$event_string="SHARED CAMPAIGNS: $SHARED_campaigns_ct $SHARED_agents_ct";
$DBX_string="CAMP SQL: $camp_SHARED_SQL\nDROP SQL: $drop_SHARED_SQL\nAGNT SQL: $agent_SHARED_SQL\n";
if ($DBX) {print "$DBX_string";}
if ($DB) {print " $event_string\n";}
$DBX_string =~ s/'//gi;
$debug_shared_output .= "$event_string\n$DBX_string";
&event_logger;
# update debug output
$stmtA = "UPDATE vicidial_campaign_stats_debug SET entry_time='$now_date',debug_output='$debug_shared_output' where campaign_id='--ALL--' and server_ip='SHARED';";
$affected_rows = $dbhA->do($stmtA);
### If there are active SHARED_ campaigns and agents set to take calls from the drop-in-groups of those campaigns, then start processing SHARED_ agents
if ( ($SHARED_campaigns_ct > 0) and ($SHARED_agents_ct > 0) )
{
$agent_shared_output="Shared Agent Rotation process last ran: $now_date \n";
$sh_ct=0;
while($SHARED_agents_ct > $sh_ct)
{
$cp_ct=0;
while($SHARED_campaigns_ct > $cp_ct)
{
$temp_drop = $SHARED_campaigns_drop_ig[$cp_ct];
if ( ($SHARED_agents_cig[$sh_ct] =~ / $temp_drop /) && (length($temp_drop) > 0) )
{
$SHARED_campaigns_agnt_ct[$cp_ct]++;
# insert/update vicidial_agent_dial_campaigns record for this agent/campaign
$stmtA = "INSERT IGNORE INTO vicidial_agent_dial_campaigns SET validate_time='$now_date',group_id='$temp_drop',campaign_id='$SHARED_campaigns[$cp_ct]',user='$SHARED_agents[$sh_ct]',dial_time='2020-01-01 00:00:00' ON DUPLICATE KEY UPDATE validate_time='$now_date',group_id='$temp_drop';";
$affected_rows_vadc_up = $dbhA->do($stmtA);
}
$cp_ct++;
}
# delete old vicidial_agent_dial_campaigns entries for this agent
$stmtA = "DELETE FROM vicidial_agent_dial_campaigns WHERE validate_time < \"$now_date\" and user='$SHARED_agents[$sh_ct]';";
$affected_rows_vadc_del = $dbhA->do($stmtA);
# gather oldest dial campaign for this agent
$next_dial_campaign_id='';
$stmtA = "SELECT campaign_id from vicidial_agent_dial_campaigns where user='$SHARED_agents[$sh_ct]' order by dial_time asc limit 1;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($DBX) {print "$sthArows|$stmtA|\n";}
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$next_dial_campaign_id = $aryA[0];
$cp_ct=0;
while($SHARED_campaigns_ct > $cp_ct)
{
if ($SHARED_campaigns[$cp_ct] =~ /^$next_dial_campaign_id$/)
{
$SHARED_campaigns_agnt_dl[$cp_ct]++;
}
$cp_ct++;
}
}
$sthA->finish();
# update dial campaign for this agent vicidial_agent_dial_campaigns
$stmtA = "UPDATE vicidial_agent_dial_campaigns SET dial_time = \"$now_date\" where user='$SHARED_agents[$sh_ct]' and campaign_id='$next_dial_campaign_id';";
$affected_rows_vadc_dial = $dbhA->do($stmtA);
# update dial campaign for this agent in vicidial_live_agents
$stmtA = "UPDATE vicidial_live_agents SET dial_campaign_id='$next_dial_campaign_id' where user='$SHARED_agents[$sh_ct]';";
$affected_rows_vla_dial = $dbhA->do($stmtA);
$agent_temp = $SHARED_agents[$sh_ct];
$sh_ct++;
$agent_shared_output .= "Agent $sh_ct: $agent_temp |$next_dial_campaign_id|$affected_rows_vadc_up|$affected_rows_vadc_del|$affected_rows_vadc_dial|$affected_rows_vla_dial|\n";
}
$cp_ct=0;
$agent_shared_output .= "\nSHARED Campaigns:\n";
while($SHARED_campaigns_ct > $cp_ct)
{
$shared_camp_output="$SHARED_campaigns[$cp_ct] Drop In-Group: $SHARED_campaigns_drop_ig[$cp_ct] Shared Agents: $SHARED_campaigns_agnt_ct[$cp_ct] (Dial Agents: $SHARED_campaigns_agnt_dl[$cp_ct])";
$agent_shared_output .= "$shared_camp_output\n";
# update debug output for each campaign
$stmtA = "UPDATE vicidial_campaign_stats_debug SET entry_time='$now_date',adapt_output='$shared_camp_output' where campaign_id='$SHARED_campaigns[$cp_ct]' and server_ip='SHARED';";
$affected_rows = $dbhA->do($stmtA);
$cp_ct++;
}
# update debug output
$stmtA = "UPDATE vicidial_campaign_stats_debug SET entry_time='$now_date',adapt_output='$agent_shared_output' where campaign_id='--ALL--' and server_ip='SHARED';";
$affected_rows = $dbhA->do($stmtA);
}
}
}
sub calculate_drops
{
@@ -5998,7 +6200,7 @@ sub calculate_dial_level
$adaptive_string .= "CAMPAIGN: $campaign_id[$i] $i\n";
# COUNTS OF STATUSES OF AGENTS IN THIS CAMPAIGN
$stmtA = "SELECT count(*),status from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one' group by status;";
$stmtA = "SELECT count(*),status from vicidial_live_agents where ( (campaign_id='$campaign_id[$i]') or (dial_campaign_id='$campaign_id[$i]') $drop_ingroup_SQL[$i] ) and last_update_time > '$VDL_one' group by status;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
+128 -15
View File
@@ -135,6 +135,7 @@
# 200122-1851 - Added code for CID Group auto-rotate feature
# 200825-0032 - Include live agents from other campaigns if they have the campaign Drop-InGroup selected and drop sec < 0
# 201122-0928 - Added code for dialy call count limits
# 201218-2224 - Added code for SHARED agent campaigns
#
### begin parsing run-time options ###
@@ -367,6 +368,11 @@ if ($non_latin > 0)
$sthA->finish();
}
$stmtA = "INSERT IGNORE into vicidial_campaign_stats_debug SET campaign_id='-SHARE-',server_ip='$VARserver_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthA->finish();
$one_day_interval = 12; # 1 month loops for one year
while($one_day_interval > 0)
@@ -386,12 +392,19 @@ while($one_day_interval > 0)
@DBlive_user=@MT;
@DBlive_server_ip=@MT;
@DBlive_campaign=@MT;
@DBlive_campaign_rank=@MT;
@DBlive_campaign_sort=@MT;
@DBlive_campaign_sorted=@MT;
@DBlive_dial_campaign=@MT;
@DBlive_conf_exten=@MT;
@DBlive_status=@MT;
@DBlive_call_id=@MT;
@DBlive_last_call_epoch=@MT;
@DBcampaigns=@MT;
@DBIPaddress=@MT;
@DBIPcampaign=@MT;
@DBIPcampaign_sort=@MT;
@DBIPcampaign_sorted=@MT;
@DBIPactive=@MT;
@DBIPvdadexten=@MT;
@DBIPcount=@MT;
@@ -445,6 +458,8 @@ while($one_day_interval > 0)
@DBIPdrop_call_seconds=@MT;
@DBIPdrop_action=@MT;
@DBIPdrop_inbound_group=@MT;
@DBshare_camp=@MT;
@DBshare_camp_rank=@MT;
$active_line_counter=0;
$user_counter=0;
$user_campaigns = '|';
@@ -457,6 +472,7 @@ while($one_day_interval > 0)
$LUcount=0;
$campaigns_update = '';
$CPcount=0;
$shared_dial_camp_override=0;
##### Get maximum calls per second that this process can send out
$stmtA = "SELECT outbound_calls_per_second,vicidial_recording_limit FROM servers where server_ip='$server_ip';";
@@ -481,10 +497,9 @@ while($one_day_interval > 0)
#############################################
##### Check if auto-dialing is enabled
$stmtA = "SELECT outbound_autodial_active,noanswer_log,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db FROM system_settings;";
$stmtA = "SELECT outbound_autodial_active,noanswer_log,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,disable_auto_dial,allow_shared_dial FROM system_settings;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -499,12 +514,69 @@ while($one_day_interval > 0)
$alt_log_pass = $aryA[5];
$tables_use_alt_log_db = $aryA[6];
$disable_auto_dial = $aryA[7];
$allow_shared_dial = $aryA[8];
}
$sthA->finish();
#############################################
##### Gather SHARED campaigns info
$debug_shared_output='';
$shared_SQL='';
$shared_callsTOTAL=0;
$shared_callsSERVER=0;
if ($allow_shared_dial > 0)
{
$stmtA = "SELECT campaign_id,drop_inbound_group,shared_dial_rank FROM vicidial_campaigns where active='Y' and dial_method IN('SHARED_RATIO','SHARED_ADAPT_HARD_LIMIT','SHARED_ADAPT_TAPERED','SHARED_ADAPT_AVERAGE') order by shared_dial_rank desc;";
$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;
$DBshare_camp[$rec_count] = $aryA[0];
$DBshare_camp_rank[$rec_count] = $aryA[2];
if (length($DBshare_camp_rank[$rec_count])<2) {$DBshare_camp_rank[$rec_count] = "0$DBshare_camp_rank[$rec_count]";}
$shared_SQL .= "'$aryA[0]','$aryA[1]',";
$debug_shared_output .= "$aryA[0] Drop-In-Group: $aryA[1] Shared-Rank: $DBshare_camp_rank[$rec_count]\n";
$rec_count++;
}
chop($shared_SQL);
if (length($shared_SQL)<2)
{$shared_SQL="'-NONE-'";}
$stmtA = "SELECT count(*) FROM vicidial_auto_calls where campaign_id IN($shared_SQL);";
$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;
$shared_callsTOTAL = $aryA[0];
}
$stmtA = "SELECT count(*) FROM vicidial_auto_calls where campaign_id IN($shared_SQL) and server_ip='$VARserver_ip';";
$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;
$shared_callsSERVER = $aryA[0];
}
$event_string="SHARED-AGENT CAMPAIGNS ON SYSTEM: $rec_count TOTAL CALLS: $shared_callsTOTAL SERVER CALLS: $shared_callsSERVER";
&event_logger;
# update debug output
$stmtA = "UPDATE vicidial_campaign_stats_debug SET entry_time='$now_date',debug_output='$event_string\n$debug_shared_output' where campaign_id='-SHARE-' and server_ip='$VARserver_ip';";
$affected_rows = $dbhA->do($stmtA);
}
$debug_shared_output='';
##### Get a listing of the users that are active and ready to take calls
##### Also get a listing of the campaigns and campaigns/serverIP that will be used
$stmtA = "SELECT user,server_ip,campaign_id,conf_exten,status,callerid FROM vicidial_live_agents where status IN($active_agents) and outbound_autodial='Y' and server_ip='$server_ip' and last_update_time > '$BDtsSQLdate' order by last_call_time";
$stmtA = "SELECT user,server_ip,campaign_id,conf_exten,status,callerid,dial_campaign_id,UNIX_TIMESTAMP(last_call_time) FROM vicidial_live_agents where status IN($active_agents) and outbound_autodial='Y' and server_ip='$server_ip' and last_update_time > '$BDtsSQLdate' order by last_call_time";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -512,13 +584,40 @@ while($one_day_interval > 0)
while ($sthArows > $rec_count)
{
@aryA = $sthA->fetchrow_array;
$DBlive_user[$user_counter] = $aryA[0];
$DBlive_server_ip[$user_counter] = $aryA[1];
$DBlive_campaign[$user_counter] = $aryA[2];
$DBlive_conf_exten[$user_counter] = $aryA[3];
$DBlive_status[$user_counter] = $aryA[4];
$DBlive_call_id[$user_counter] = $aryA[5];
$DBlive_user[$user_counter] = $aryA[0];
$DBlive_server_ip[$user_counter] = $aryA[1];
$DBlive_campaign[$user_counter] = $aryA[2];
$DBlive_conf_exten[$user_counter] = $aryA[3];
$DBlive_status[$user_counter] = $aryA[4];
$DBlive_call_id[$user_counter] = $aryA[5];
$DBlive_dial_campaign[$user_counter] = $aryA[6];
$DBlive_last_call_epoch[$user_counter] = $aryA[7];
$DBlive_campaign_rank[$user_counter] = 0;
$DBlive_campaign_sort[$user_counter] = 0;
if (length($DBlive_dial_campaign[$user_counter]) > 0)
{
if ($DBlive_dial_campaign[$user_counter] ne $DBlive_campaign[$user_counter])
{
$shared_dial_camp_override++;
if ($DBX) {print "Shared-Dial-Agent Dial-Campaign Override: $shared_dial_camp_override/$rec_count - $DBlive_user[$user_counter] ($DBlive_campaign[$user_counter] -> $DBlive_dial_campaign[$user_counter])\n";}
$debug_shared_output .= "Agent Dial-Campaign Override: $shared_dial_camp_override/$rec_count - $DBlive_user[$user_counter] ($DBlive_campaign[$user_counter] -> $DBlive_dial_campaign[$user_counter])\n";
$DBlive_campaign[$user_counter] = $DBlive_dial_campaign[$user_counter];
}
else
{
$debug_shared_output .= "Agent Dial-Campaign No-Change: $rec_count - $DBlive_user[$user_counter] ($DBlive_campaign[$user_counter] -> $DBlive_dial_campaign[$user_counter])\n";
}
}
$temp_ct=0;
foreach(@DBshare_camp)
{
if ($DBlive_campaign[$user_counter] eq $DBshare_camp[$temp_ct])
{
$DBlive_campaign_rank[$user_counter] = $DBshare_camp_rank[$temp_ct];
}
$temp_ct++;
}
if ($user_campaigns !~ /\|$DBlive_campaign[$user_counter]\|/i)
{
if ($campaigns_update !~ /'$DBlive_campaign[$user_counter]'/) {$campaigns_update .= "'$DBlive_campaign[$user_counter]',"; $CPcount++;}
@@ -532,8 +631,12 @@ while($one_day_interval > 0)
$user_campaignIP .= "$DBlive_campaign[$user_counter]__$DBlive_server_ip[$user_counter]|";
$DBIPcampaign[$user_CIPct] = "$DBlive_campaign[$user_counter]";
$DBIPaddress[$user_CIPct] = "$DBlive_server_ip[$user_counter]";
$DBIPcampaign_sort[$user_CIPct] = $DBlive_campaign_rank[$user_counter].'_'.$DBlive_last_call_epoch[$user_counter].'_'.$DBlive_campaign[$user_counter].'_'.$user_CIPct;
if ($DBX) {print "Debug agent campaign sort: $DBIPcampaign_sort[$user_CIPct]\n";}
$user_CIPct++;
}
$DBlive_campaign_sort[$user_counter] = $DBlive_campaign_rank[$user_counter].'_'.$DBlive_last_call_epoch[$user_counter].'_'.$DBlive_campaign[$user_counter].'_'.$user_counter;
if ($DBX) {print "Debug live agent sort: $DBlive_campaign_sort[$user_counter]\n";}
$user_counter++;
$rec_count++;
}
@@ -561,9 +664,15 @@ while($one_day_interval > 0)
$event_string="OLD TRUNK SHORTS CLEARED: $UVCSSaffected_rows |$user_campaignsSQL|";
&event_logger;
}
$user_CIPct = 0;
foreach(@DBIPcampaign)
### sort campaigns by shared campaign rank, then last agent call handle time
@DBIPcampaign_sorted = sort { $a cmp $b } @DBIPcampaign_sort;
$user_CIPct_sort = 0;
foreach(@DBIPcampaign_sorted)
{
@camp_sort_line = split(/\n/,$DBIPcampaign_sorted[$user_CIPct_sort]);
$user_CIPct = $camp_sort_line[3];
$debug_string='';
$user_counter=0;
foreach(@DBlive_campaign)
@@ -607,7 +716,7 @@ while($one_day_interval > 0)
}
### get count of READY-status agents in this campaign
$stmtA = "SELECT count(*) FROM vicidial_live_agents where campaign_id='$DBIPcampaign[$user_CIPct]' and server_ip='$server_ip' and status='READY';";
$stmtA = "SELECT count(*) FROM vicidial_live_agents where ( (campaign_id='$DBIPcampaign[$user_CIPct]') or (dial_campaign_id='$DBIPcampaign[$user_CIPct]') ) and server_ip='$server_ip' and status='READY';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -741,7 +850,7 @@ while($one_day_interval > 0)
}
# BEGIN check if drop-in-group agents should be included ---NONE--- #
if ( ($DBIPdrop_call_seconds[$user_CIPct] < 0) && ($DBIPdrop_action[$user_CIPct] =~ /IN_GROUP/i) && ($DBIPdrop_inbound_group[$user_CIPct] !~ /^---NONE---$/) && (length($DBIPdrop_inbound_group[$user_CIPct]) > 0) && ($new_agent_multicampaign > 0) )
if ( ($DBIPdrop_call_seconds[$user_CIPct] < 0) && ($DBIPdrop_action[$user_CIPct] =~ /IN_GROUP/i) && ($DBIPdrop_inbound_group[$user_CIPct] !~ /^---NONE---$/) && (length($DBIPdrop_inbound_group[$user_CIPct]) > 0) && ($new_agent_multicampaign > 0) && ($DBIPdial_method[$user_CIPct] !~ /SHARED_/i) )
{
if ($DBIPcount[$user_CIPct] > 0) {$DBIPcount[$user_CIPct] = ($DBIPcount[$user_CIPct] - 1);}
if ($DBIPACTIVEcount[$user_CIPct] > 0) {$DBIPACTIVEcount[$user_CIPct] = ($DBIPACTIVEcount[$user_CIPct] - 1);}
@@ -1111,7 +1220,7 @@ while($one_day_interval > 0)
$waiting_calls_IN=0;
$waiting_calls_OUT=0;
$stmtA = "SELECT count(*),status from vicidial_live_agents where campaign_id='$DBIPcampaign[$user_CIPct]' and last_update_time > '$halfminSQLdate' group by status;";
$stmtA = "SELECT count(*),status from vicidial_live_agents where ( (campaign_id='$DBIPcampaign[$user_CIPct]') or (dial_campaign_id='$DBIPcampaign[$user_CIPct]') ) and last_update_time > '$halfminSQLdate' group by status;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
@@ -1264,7 +1373,7 @@ while($one_day_interval > 0)
$stmtA="INSERT IGNORE INTO vicidial_campaign_stats_debug SET server_ip='$server_ip',campaign_id='$DBIPcampaign[$user_CIPct]',entry_time='$now_date',debug_output='$debug_string' ON DUPLICATE KEY UPDATE entry_time='$now_date',debug_output='$debug_string';";
$affected_rows = $dbhA->do($stmtA);
$user_CIPct++;
$user_CIPct_sort++;
}
###############################################################################
@@ -4503,6 +4612,10 @@ while($one_day_interval > 0)
$bad_grabber_counter=0;
$stat_count++;
# update debug output
$stmtA = "UPDATE vicidial_campaign_stats_debug SET entry_time='$now_date',adapt_output='$debug_shared_output' where campaign_id='-SHARE-' and server_ip='$VARserver_ip';";
$affected_rows = $dbhA->do($stmtA);
}
+2 -1
View File
@@ -47,6 +47,7 @@
# 200108-1314 - Added CID Group type of NONE
# 200122-1850 - Added code for CID Group auto-rotate feature
# 201122-0932 - Added code for dialy call count limits
# 201220-1034 - Changes for shared agent campaigns
#
### begin parsing run-time options ###
@@ -602,7 +603,7 @@ while($one_day_interval > 0)
$event_string.=" Campaign Dial Fill tally: $DBfill_tally[$camp_CIPct]/$DBfill_needed[$camp_CIPct]";
&event_logger;
$stmtA = "SELECT count(*) FROM vicidial_live_agents where campaign_id='$DBfill_campaign[$camp_CIPct]' and status NOT IN('PAUSED');";
$stmtA = "SELECT count(*) FROM vicidial_live_agents where ( (campaign_id='$DBfill_campaign[$camp_CIPct]') or (dial_campaign_id='$DBfill_campaign[$camp_CIPct]') ) and status NOT IN('PAUSED');";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
+4 -3
View File
@@ -99,10 +99,11 @@
# 200814-2132 - Added support for Internation DNC scrubbing
# 201111-1359 - Added support for hopper_drop_run_trigger
# 201122-1039 - Added support for daily call count limits
# 201220-1032 - Changes for shared agent campaigns
#
# constants
$build = '201122-1039';
$build = '201220-1032';
$DB=0; # Debug flag, set to 0 for no debug messages. Can be overriden with CLI --debug flag
$US='__';
$MT[0]='';
@@ -1158,14 +1159,14 @@ while ($sthArows > $rec_count)
if ( $use_auto_hopper[$rec_count] =~ /Y/)
{
### Find the number of agents
$stmtB = "SELECT COUNT(*) FROM vicidial_live_agents WHERE campaign_id='$campaign_id[$rec_count]' and status IN ('READY','QUEUE','INCALL','CLOSER') and last_update_time >= '$VDL_tensec'";
$stmtB = "SELECT COUNT(*) FROM vicidial_live_agents WHERE ( (campaign_id='$campaign_id[$rec_count]') or (dial_campaign_id='$campaign_id[$rec_count]') ) and status IN ('READY','QUEUE','INCALL','CLOSER') and last_update_time >= '$VDL_tensec'";
$sthB = $dbhA->prepare($stmtB) or die "preparing: ",$dbhA->errstr;
$sthB->execute or die "executing: $stmtB ", $dbhA->errstr;
@aryAgent = $sthB->fetchrow_array;
$num_agents = $aryAgent[0];
$sthB->finish();
$stmtB = "SELECT COUNT(*) FROM vicidial_live_agents WHERE campaign_id='$campaign_id[$rec_count]' and status IN ('PAUSED') and last_update_time >= '$VDL_tensec' and last_state_change >= '$VDL_one'";
$stmtB = "SELECT COUNT(*) FROM vicidial_live_agents WHERE ( (campaign_id='$campaign_id[$rec_count]') or (dial_campaign_id='$campaign_id[$rec_count]') ) and status IN ('PAUSED') and last_update_time >= '$VDL_tensec' and last_state_change >= '$VDL_one'";
$sthB = $dbhA->prepare($stmtB) or die "preparing: ",$dbhA->errstr;
$sthB->execute or die "executing: $stmtB ", $dbhA->errstr;
@aryAgent = $sthB->fetchrow_array;
+75 -23
View File
@@ -1,7 +1,9 @@
AGENT MULTI-CAMPAIGN DIALING DOC Started: 2020-08-24 Updated: 2020-11-17
AGENT MULTI-CAMPAIGN DIALING DOC Started: 2020-08-24 Updated: 2021-01-02
NOTE: Requires VICIdial svn/trunk code revision 3284 or higher to work properly!!!
NOTE: The new SHARED campaign dial method requires VICIdial svn/trunk code revision 3339 or higher to work properly!!!
NOTE: THIS FEATURE IS OPTIONAL, AND SHOULD ONLY BE CONFIGURED AFTER YOUR SYSTEM
HAS BEEN INSTALLED AND TESTED!
@@ -35,7 +37,7 @@ First, a description of how to use List Overrides on multiple lists in a single
The above settings will allow calls to go out and back in with unique settings, allowing for unique calls paths and agent screens for each list. So if you have a set of services to perform on a customer list, you can define one per list and have the same group of agents call on all of those separate lists all in one single campaign.
In some cases, like different agent spoken language skills, the above approach will not work, so you have to set up different campaigns(and lists) for each spoken language. In the example below we will detail each of the settings that need to be configured in Campaigns and In-Groups for this to work. We will use the example of an outbound appointment confirmation program that calls people who speak both English and Spanish and have agents who speak one or both of those languages.
In some cases, like different agent spoken language skills, the above approach will not work, so you have to set up different campaigns(and lists) for each spoken language. In the example below we will detail each of the settings that need to be configured in Campaigns and In-Groups for this to work. We will use the example of an outbound appointment confirmation program that calls people who speak both English and Spanish and have agents who speak one or both of those languages. (There is also a newer and more efficient option for Shared Agent Multi-Campaign outbound dialing using the "SHARED_" Dial Methods that you can read about below this section.)
NOTE: The following instructions below assume that you already know how to set up and run an outbound auto-dialing campaign.
@@ -71,6 +73,7 @@ NOTE: The following instructions below assume that you already know how to set u
Dial Method: RATIO
Allow No-Hopper-Leads Logins: Y
Allowed Inbound Groups: select both "DROP_APPT_ENG" & "DROP_APPT_SPA"
* Do not assign any active lists to this campaign
6. Set the following settings on both the DROP_APPT_ENG & DROP_APPT_SPA inbound groups
Welcome Message Filename: ---NONE---
@@ -106,11 +109,9 @@ When "Drop Call Seconds" set to '-1' in a campaign, and a call is answered by a
THE PROBLEM OF "OVER-DIALING":
When you allow a single agent to have multiple calls placed for them, there can always be a problem with "over-dialing", even when only using a single campaign. This issue is more complicated though when that same level of dialing is happening across multiple campaigns. At a minimum, the campaign "Available Only Tally" settings should be the first things you check to see if they are active. Beyond that, there really are not any simple solutions for it.
When you allow a single agent to have multiple calls placed for them, there can always be a problem with "over-dialing", even when only using a single campaign. This issue is more complicated though when that same level of dialing is happening across multiple campaigns. At a minimum, the campaign "Available Only Tally" settings should be the first things you check to see if they are active. Beyond that, there really are not any simple solutions for it. Because of this, we added a new campaign feature, detailed below.
One possible development option would be allowing for campaigns to have their dial levels set to a value below "1.0", which would not dial any calls unless there were more agents available to take calls from a specific campaign. There are multiple issues with making this work on the back-end that will need to be programmed around, as well as the problem that some campaigns which can't get above the 1.0 threshold to place a call with the number of agents logged-in not being able to place any calls at all. But if you aren't planning on having single agents dialing by themselves for a campaign at any point, this would be the simplest and quickest solution to try. This option would be 12 hours of development time.
Another much more complex development option would be to add a new campaign dialing method "SHARED_RATIO" that would be specifically for shared agent campaigns that would operate somewhat like a round-robin system for shared campaign dialing. For instance, if only one agent is logged-in with dialing happening for that agent across 3 campaigns, each of those 3 campaigns would take turns dialing for that one agent. The number of calls would be calculated based on the number of agents that could take calls from each campaign, and the number of campaigns each agent is set to take calls from. This would be a very complex project to complete, but it would be the most efficient option with the best possibility for a balance between keeping agents on the phone and not dropping calls under all conditions(even single-agent dialing). This option would be 40 hours of development time.
We have added a new campaign dialing method "SHARED_..." that is specifically for shared agent campaigns that will operate somewhat like a round-robin system for shared agent campaign dialing. For instance, if only one agent is logged-in with dialing happening for that agent across 3 campaigns, each of those 3 campaigns would take turns dialing for that one agent. The number of calls would be calculated based on the number of agents that could take calls from each campaign, and the number of campaigns each agent is set to take calls from. This was a very complex project to complete, but it is the most efficient option with the best possibility for a balance between keeping agents on the phone and not dropping calls under all conditions(even single-agent dialing).
@@ -118,28 +119,78 @@ Another much more complex development option would be to add a new campaign dial
*********************** The following are notes for how this second option might work:
*********************** The following are notes for how the new "SHARED_..." campaign Dial Methods work:
How a "SHARED_RATIO" dial method would work:
1. New code added to the AST_VDadapt.pl and AST_VDauto_dial.pl(and FILL) scripts that would(for agents logged into shared-dialing campaigns, for dialing purposes only) rotate them among the campaigns that they are able to take calls from, while still allowing them to have calls from any of those campaigns sent to them any time they are available.
2. Change the dialing algorithm(for campaigns with a "SHARED_" dial method only) to use a count of calls placed by all shared campaigns on the system as a total, instead of only each campaign. This would prevent over-dialing as agents are rotated from dialing-campaign to dialing-campaign.
3. The agent-dialing-campaign-rotation process would attempt to balance agents by time(round-robin-like) across the campaigns that they are assigned to take calls from.
4. New database fields/tables to store the temporary dialing campaign designations for each agent and what other campaigns they had just been assigned to
5. New debug Admin Utilities report that would show everything that is going on for shared campaigns in the process of agent rotation and shared ratio dialing
How a "SHARED_..." dial methods work:
1. New code added to the AST_VDadapt.pl and AST_VDauto_dial.pl scripts that will(for agents logged into shared-dialing campaigns, for dialing purposes only) rotate them among the campaigns that they are able to take calls from, while still allowing them to have calls from any of those campaigns sent to them any time they are available.
2. Change the dialing algorithm(for campaigns with a "SHARED_" dial method only) to prevent over-dialing as agents are rotated from dialing-campaign to dialing-campaign.
3. The agent-dialing-campaign-rotation process attempts to balance agents by time(round-robin-like) across the campaigns that they are assigned to take calls from.
4. New database fields/tables were added to store the temporary dialing campaign designations for each agent and what other campaigns they had just been assigned to
5. Add shared debug output to existing Admin Utilities "Campaign Debug Report" that will show everything that is going on for shared campaigns in the process of agent rotation and shared outbound dialing
Agent rotation steps, added to the AST_VDadapt.pl script: (see new database changes below for details on the DB storage of this data)
- runs once every interval[2.5 sec, 15 sec, 1 minute] <- haven't decided this yet
- runs once every 1 minute
- for each agent, gather all campaigns they can dial for, and their current dial_campaign
- delete from vicidial_agent_dial_campaigns any campaigns agent is no longer dialing for, update validate_time for others
- set dial_campaign to ''(blank)
- grab oldest vicidial_agent_dial_campaigns.dial_time campaign_id for each agent and update vicidial_live_agents.dial_campaign_id then update dial_time
- set dial_campaign to ''(blank) if no active campaigns or agent had removed all drop in-groups
- at Timeclock-end-of-day, wipe out everything in vicidial_agent_dial_campaigns table older than 5 minutes and optimize table
Shared campaigns outbound dialing steps:
- gather all campaigns that are using a SHARED_ dial method, use that list to count current calls and calculate how many new calls can be placed for all shared campaigns
- when counting for agents in the campaign, use the vicidial_live_agents.dial_campaign_id field
- when allocating dials for each campaign, sort by oldest dial first(vicidial_campaigns.campaign_calldate) or by new ranking field(vicidial_campaigns.shared_dial_rank)
- gather all campaigns that are using a SHARED_ dial method, use that list to count current calls and calculate how many new calls can be placed for each of the shared campaigns
- when counting for agents in the campaign to dial for, use the vicidial_live_agents.dial_campaign_id field
- when allocating dials for each campaign, sort by:
- campaign shared agent dial ranking field(vicidial_campaigns.shared_dial_rank) *then*
- oldest agent call handled(vicidial_live_agents.last_call_time)
The following are instructions for how to set up a "SHARED_" set of campaigns:
1. Set up three campaigns:
SHIPENG(Shipping English)
SHIPFRE(Shipping French)
SHIPAGNT(Shipping All Agents)
2. Set up two lists:
1201(Shipping English List), assigned to the SHIPENG campaign
1202(Shipping French List), assigned to the SHIPFRE campaign
3. Set up two Inbound Groups to use as Drop In-Groups:
DROP_SHIP_ENG(Shipping English Drop InGroup)
DROP_SHIP_FRE(Shipping French Drop InGroup)
* RECOMMENDATIONS:
- You may want to set the In-Group "Drop Call Seconds" to a lower number and send the call to a Call Menu if no agent is available
4. Set the following settings on both the SHIPENG & SHIPFRE campaigns (these are your two outbound dialing campaigns)
* Start by setting these campaigns up as you would to be normal outbound auto-dialing campaigns
Dial Method: SHARED_ADAPT_AVERAGE or SHARED_RATIO
Available Only Tally: Y
Drop Call Seconds: -1
Drop Action: IN_GROUP
Drop Transfer Group: DROP_SHIP_ENG(for the SHIPENG campaign) or DROP_SHIP_FRE(for the SHIPFRE campaign)
5. Set the following settings on the SHIPAGNT campaign:
Allow Inbound and Blended: Y
Dial Method: RATIO
Allow No-Hopper-Leads Logins: Y
Allowed Inbound Groups: select both "DROP_SHIP_ENG" & "DROP_SHIP_FRE"
* Do not assign any active lists to this campaign
6. Set the following settings on both the DROP_SHIP_ENG & DROP_SHIP_FRE inbound groups
Welcome Message Filename: ---NONE---
Play Welcome Message: NEVER
No Delay Call Route: Y
7. All agents will log into the "SHIPAGNT" campaign and will select the "DROP_SHIP_ENG" and/or "DROP_SHIP_FRE" in-groups to take calls from as well as selecting the "BLENDED CALLING" checkbox when they log in, or managers can select those in-groups and the "Closer Default Blended" for the agents in the User Modify screen for those agents if they don't want their agents to have the ability to choose.
* NOTES:
- The "SHARED_..." campaign dial method does not require the use of Remote Agents at all, and the live agents do need to select to take blended (outbound) calls or no calls will be placed for them as they rotate through the shared agent campaigns.
- For SHARED agent campaigns, there will be an additional campaign setting: "Shared Dial Rank", which will allow you to prioritize the dialing of your shared campaigns as calls are placed for them.
@@ -147,8 +198,14 @@ DATABASE CHANGES: !!!!!! FOR DOCUMENTATION PURPOSES ONLY !!!!!
ALTER TABLE system_settings ADD allow_shared_dial ENUM('0','1') default '0';
ALTER TABLE vicidial_campaigns ADD shared_dial_rank TINYINT(3) default '99';
ALTER TABLE vicidial_campaigns MODIFY dial_method ENUM('MANUAL','RATIO','ADAPT_HARD_LIMIT','ADAPT_TAPERED','ADAPT_AVERAGE','INBOUND_MAN','SHARED_RATIO','SHARED_ADAPT_HARD_LIMIT','SHARED_ADAPT_TAPERED','SHARED_ADAPT_AVERAGE') default 'MANUAL';
ALTER TABLE vicidial_live_agents ADD dial_campaign_id VARCHAR(8) default '';
CREATE TABLE vicidial_agent_dial_campaigns (
campaign_id VARCHAR(8),
group_id VARCHAR(20),
user VARCHAR(20),
validate_time DATETIME,
dial_time DATETIME,
@@ -158,8 +215,3 @@ index (campaign_id)
CREATE UNIQUE INDEX vadc_key on vicidial_agent_dial_campaigns(campaign_id, user);
ALTER TABLE vicidial_live_agents ADD dial_campaign_id VARCHAR(8) default '';
ALTER TABLE vicidial_campaigns ADD shared_dial_rank TINYINT(3) default '0';
ALTER TABLE vicidial_campaigns MODIFY dial_method ENUM('MANUAL','RATIO','ADAPT_HARD_LIMIT','ADAPT_TAPERED','ADAPT_AVERAGE','INBOUND_MAN','SHARED_RATIO','SHARED_ADAPT_HARD_LIMIT','SHARED_ADAPT_TAPERED','SHARED_ADAPT_AVERAGE') default 'MANUAL';
+19 -4
View File
@@ -442,6 +442,7 @@ preview_lead_id INT(9) UNSIGNED default '0',
external_lead_id INT(9) UNSIGNED default '0',
last_inbound_call_time_filtered DATETIME,
last_inbound_call_finish_filtered DATETIME,
dial_campaign_id VARCHAR(8) default '',
index (random_id),
index (last_call_time),
index (last_update_time),
@@ -796,7 +797,7 @@ closer_campaigns TEXT,
use_internal_dnc ENUM('Y','N','AREACODE') default 'N',
allcalls_delay SMALLINT(3) UNSIGNED default '0',
omit_phone_code ENUM('Y','N') default 'N',
dial_method ENUM('MANUAL','RATIO','ADAPT_HARD_LIMIT','ADAPT_TAPERED','ADAPT_AVERAGE','INBOUND_MAN') default 'MANUAL',
dial_method ENUM('MANUAL','RATIO','ADAPT_HARD_LIMIT','ADAPT_TAPERED','ADAPT_AVERAGE','INBOUND_MAN','SHARED_RATIO','SHARED_ADAPT_HARD_LIMIT','SHARED_ADAPT_TAPERED','SHARED_ADAPT_AVERAGE') default 'MANUAL',
available_only_ratio_tally ENUM('Y','N') default 'N',
adaptive_dropped_percentage VARCHAR(4) default '3',
adaptive_maximum_level VARCHAR(6) default '3.0',
@@ -1051,7 +1052,8 @@ pause_max_exceptions VARCHAR(40) default '',
hopper_drop_run_trigger VARCHAR(1) default 'N',
daily_call_count_limit TINYINT(3) UNSIGNED default '0',
daily_limit_manual VARCHAR(20) default 'DISABLED',
transfer_button_launch VARCHAR(12) default 'NONE'
transfer_button_launch VARCHAR(12) default 'NONE',
shared_dial_rank TINYINT(3) default '99'
) ENGINE=MyISAM;
CREATE TABLE vicidial_lists (
@@ -1878,7 +1880,8 @@ inbound_answer_config ENUM('0','1','2','3','4','5') DEFAULT '0',
enable_international_dncs ENUM('0','1') default '0',
web_loader_phone_strip VARCHAR(10) default 'DISABLED',
manual_dial_phone_strip VARCHAR(10) default 'DISABLED',
daily_call_count_limit ENUM('0','1') default '0'
daily_call_count_limit ENUM('0','1') default '0',
allow_shared_dial ENUM('0','1') default '0'
) ENGINE=MyISAM;
CREATE TABLE vicidial_campaigns_list_mix (
@@ -4360,6 +4363,18 @@ unique index vlcdc_lead (lead_id),
index(list_id)
) ENGINE=MyISAM;
CREATE TABLE vicidial_agent_dial_campaigns (
campaign_id VARCHAR(8),
group_id VARCHAR(20),
user VARCHAR(20),
validate_time DATETIME,
dial_time DATETIME,
index (user),
index (campaign_id)
) ENGINE=MyISAM;
CREATE UNIQUE INDEX vadc_key on vicidial_agent_dial_campaigns(campaign_id, user);
ALTER TABLE vicidial_email_list MODIFY message text character set utf8;
@@ -4693,4 +4708,4 @@ INSERT INTO vicidial_settings_containers VALUES ('INTERNATIONAL_DNC_IMPORT','Pro
UPDATE system_settings set vdc_agent_api_active='1';
UPDATE system_settings SET db_schema_version='1613',db_schema_update_date=NOW(),reload_timestamp=NOW();
UPDATE system_settings SET db_schema_version='1614',db_schema_update_date=NOW(),reload_timestamp=NOW();
+21
View File
@@ -1364,3 +1364,24 @@ UPDATE system_settings SET db_schema_version='1612',db_schema_update_date=NOW()
ALTER TABLE vicidial_campaigns ADD transfer_button_launch VARCHAR(12) default 'NONE';
UPDATE system_settings SET db_schema_version='1613',db_schema_update_date=NOW() where db_schema_version < 1613;
ALTER TABLE system_settings ADD allow_shared_dial ENUM('0','1') default '0';
ALTER TABLE vicidial_campaigns ADD shared_dial_rank TINYINT(3) default '99';
ALTER TABLE vicidial_campaigns MODIFY dial_method ENUM('MANUAL','RATIO','ADAPT_HARD_LIMIT','ADAPT_TAPERED','ADAPT_AVERAGE','INBOUND_MAN','SHARED_RATIO','SHARED_ADAPT_HARD_LIMIT','SHARED_ADAPT_TAPERED','SHARED_ADAPT_AVERAGE') default 'MANUAL';
ALTER TABLE vicidial_live_agents ADD dial_campaign_id VARCHAR(8) default '';
CREATE TABLE vicidial_agent_dial_campaigns (
campaign_id VARCHAR(8),
group_id VARCHAR(20),
user VARCHAR(20),
validate_time DATETIME,
dial_time DATETIME,
index (user),
index (campaign_id)
) ENGINE=MyISAM;
CREATE UNIQUE INDEX vadc_key on vicidial_agent_dial_campaigns(campaign_id, user);
UPDATE system_settings SET db_schema_version='1614',db_schema_update_date=NOW() where db_schema_version < 1614;
+44 -14
View File
File diff suppressed because one or more lines are too long
+60 -2
View File
@@ -16,6 +16,7 @@
# 180201-1245 - Added live call and shortage counts per server tables
# 190716-0909 - Added Call Quota process output
# 201122-2249 - Added Hopper debug output
# 201219-2119 - Added SHARED campaign output
#
$startMS = microtime();
@@ -39,7 +40,7 @@ if (isset($_GET["SUBMIT"])) {$SUBMIT=$_GET["SUBMIT"];}
#############################################
##### START SYSTEM_SETTINGS LOOKUP #####
$stmt = "SELECT use_non_latin,webroot_writable,outbound_autodial_active,user_territories_active,enable_languages,language_method FROM system_settings;";
$stmt = "SELECT use_non_latin,webroot_writable,outbound_autodial_active,user_territories_active,enable_languages,language_method,allow_shared_dial FROM system_settings;";
$rslt=mysql_to_mysqli($stmt, $link);
if ($DB) {echo "$stmt\n";}
$qm_conf_ct = mysqli_num_rows($rslt);
@@ -52,6 +53,7 @@ if ($qm_conf_ct > 0)
$user_territories_active = $row[3];
$SSenable_languages = $row[4];
$SSlanguage_method = $row[5];
$SSallow_shared_dial = $row[6];
}
##### END SETTINGS LOOKUP #####
###########################################
@@ -279,7 +281,7 @@ else
echo "---------- "._QXZ("ADAPT DEBUG")."\n";
echo "\n";
$stmt="select campaign_name,closer_campaigns from vicidial_campaigns where campaign_id='" . mysqli_real_escape_string($link, $group) . "' limit 1;";
$stmt="select campaign_name,closer_campaigns,dial_method,shared_dial_rank from vicidial_campaigns where campaign_id='" . mysqli_real_escape_string($link, $group) . "' limit 1;";
$rslt=mysql_to_mysqli($stmt, $link);
if ($DB) {echo "$stmt\n";}
$camps_to_print = mysqli_num_rows($rslt);
@@ -287,6 +289,8 @@ else
{
$row=mysqli_fetch_row($rslt);
$closer_campaigns = $row[1];
$dial_method = $row[2];
$shared_dial_rank = $row[3];
echo _QXZ("Campaign Debug").": $group - $row[0] $NOW_TIME\n\n";
echo _QXZ("Total leads in hopper right now").": $TOTALcalls\n\n";
@@ -324,6 +328,60 @@ else
$i++;
}
if ($SSallow_shared_dial > 0)
{
$stmt="select update_time,debug_output,adapt_output from vicidial_campaign_stats_debug where campaign_id='" . mysqli_real_escape_string($link, $group) . "' and server_ip='SHARED' limit 1;";
$rslt=mysql_to_mysqli($stmt, $link);
if ($DB) {echo "$stmt\n";}
$debugs_to_print = mysqli_num_rows($rslt);
$i=0;
while ($debugs_to_print > $i)
{
$row=mysqli_fetch_row($rslt);
echo _QXZ("Shared Agent Campaign Debug").": $row[0]\n";
echo "$row[1]\n";
echo "$row[2]\n";
$i++;
}
if (preg_match("/SHARED/i",$dial_method))
{
$stmt="select update_time,debug_output,adapt_output from vicidial_campaign_stats_debug where campaign_id='--ALL--' and server_ip='SHARED' limit 1;";
$rslt=mysql_to_mysqli($stmt, $link);
if ($DB) {echo "$stmt\n";}
$debugs_to_print = mysqli_num_rows($rslt);
$i=0;
while ($debugs_to_print > $i)
{
$row=mysqli_fetch_row($rslt);
echo _QXZ("Shared Agent System-wide Debug").": $row[0]\n";
echo "$row[1]\n";
echo "$row[2]\n";
$i++;
}
$stmt="select update_time,debug_output,adapt_output,server_ip from vicidial_campaign_stats_debug where campaign_id='-SHARE-' and server_ip!='SHARED' limit 100;";
$rslt=mysql_to_mysqli($stmt, $link);
if ($DB) {echo "$stmt\n";}
$debugs_to_print = mysqli_num_rows($rslt);
$i=0;
while ($debugs_to_print > $i)
{
$row=mysqli_fetch_row($rslt);
echo _QXZ("Shared Agent Server Debug").": $row[3] $row[0]\n";
echo "$row[1]\n";
echo "$row[2]\n";
$i++;
}
}
}
$stmt="select update_time,server_ip,debug_output,adapt_output from vicidial_campaign_stats_debug where campaign_id='" . mysqli_real_escape_string($link, $group) . "' and server_ip NOT IN('ADAPT','CALLQUOTA') order by server_ip limit 100;";
$rslt=mysql_to_mysqli($stmt, $link);
if ($DB) {echo "$stmt\n";}
+5 -2
View File
@@ -1,4 +1,4 @@
# version: 20201201194401
# version: 20201219200201
users-user User ID <QXZ>This field is where you put the users ID number, can be up to 8 digits in length, Must be at least 2 characters in length.</QXZ>
users-pass Password <QXZ>This field is where you put the users password. Must be at least 2 characters in length. A medium strength user password will be at least 10 characters in length, and a strong user password will be at least 20 characters in length and have letters as well as at least one number. It is recommended that you use a longer password if possible, stringing together several unrelated words with no spaces, and a number somewhere in the string. The maximum size of a password is 100 characters.</QXZ>
users-force_change_password Force Change Password <QXZ>If this option is set to Y then the user will be prompted to change their password the next time they log in to the administration webpage or the agent screen. Default is N.</QXZ>
@@ -160,6 +160,7 @@ campaigns-adaptive_dl_diff_target Dial Level Difference Target <QXZ>This field i
campaigns-dl_diff_target_method Dial Level Difference Target Method <QXZ>This option allows you to define whether the dial level difference target setting is applied only to the calculation of the dial level or also to the actual dialing on each dialing server. If you are running a small campaign with agents logged in on many servers you may want to use the ADAPT_CALC_ONLY option, because the CALLS_PLACED option may result in fewer calls being placed than desired. This option is only active if Dial Level Difference Target is set to something other than 0. Default is ADAPT_CALC_ONLY.</QXZ>
campaigns-concurrent_transfers Concurrent Transfers <QXZ>This setting is used to define the number of calls that can be sent to agents at the same time. It is recommended that this setting is left at AUTO. This field is not used by the MANUAL dial method.</QXZ>
campaigns-queue_priority Queue Priority <QXZ>This setting is used to define the order in which the calls from this outbound campaign should be answered in relation to the inbound calls if this campaign is in blended mode. We do not recommend setting inbound calls to a higher priority than the outbound campaign calls because people calling in expect to wait and people being called expect for someone to be there on the phone.</QXZ>
campaigns-shared_dial_rank Shared Dial Rank <QXZ>For campaigns that are set to a SHARED dial method, this setting will indicate the dialing priority among all of the SHARED dial method campaigns in the system for this specific campaign. The smaller the Shared Dial Rank number for a campaign, the sooner a call will be placed for that campaign. Default is 99.</QXZ>
campaigns-drop_rate_group Multiple Campaign Drop Rate Group <QXZ>This feature allows you to set a campaign as a member of a Campaign Drop Rate Group, or a group of campaigns whose Human Answered calls and Drop calls for all campaigns in the group will be combined into a shared drop percentage, or abandon rate. This allows you to to run multiple campaigns at once and more easily control your drop rate. This is particularly useful in the UK where regulations permit this drop rate calculation method with campaign grouping for the same company even if there are several campaigns that company is running during the same day. To enable this for a campaign, just select a group from the list. There are 10 groups defined in the system by default, you can contact your system administrator to add more. Default is DISABLED.</QXZ>
campaigns-inbound_queue_no_dial Inbound Queue No Dial <QXZ>This feature if set to ENABLED allows you to prevent outbound auto-dialing of this campaign if there are any inbound calls waiting in queue that are part of the allowed inbound groups set in this campaign. Setting this to ALL_SERVERS will change the algorithm to calculate all inbound calls as active calls on this server even if they are on another server which will reduce the chance of placing unnecessary outbound calls if you have calls coming in on another server. Default is DISABLED.</QXZ> <QXZ>If the selected option includes CHAT, then no outbound auto-dialing will take place while an inbound customer chat is waiting.</QXZ>
campaigns-inbound_no_agents_no_dial_container Inbound No-Agents No-Dial <QXZ>If set to something other than ---DISABLED---, the selected INGROUP_LIST type of Settings Container will be used to determine if any agents are ready and waiting for phone calls from at least one of the listed In-Groups. If there are less inbound agents available than the Threshold setting below, then no outbound calls will be placed for this campaign. Default is DISABLED.</QXZ>
@@ -1042,6 +1043,7 @@ settings-agent_script Agent Screen Script <QXZ>This is the PHP script page of th
settings-active_voicemail_server Active Voicemail Server <QXZ>In multi-server systems, this is the server that will handle all voicemail boxes. This server is also where the dial-in generated prompts will be uploaded from, the 8168 recordings. It is important that this server is both Active and an Active Asterisk server.</QXZ>
settings-allow_voicemail_greeting Allow Voicemail Greeting Chooser <QXZ>If this setting is enabled it will allow you to choose an audio file from the audio store to be played as the voicemail greeting to a specific voicemail box. Default is 0 for disabled.</QXZ>
settings-outbound_autodial_active Outbound Auto-Dial Active <QXZ>This option allows you to enable or disable outbound auto-dialing within the system, setting this field to 0 will remove the LISTS and FILTERS sections and many fields from the Campaign Modification screens. Manual entry dialing will still be allowable from within the agent screen, but no list dialing will be possible. Default is 1 for active.</QXZ>
settings-allow_shared_dial Shared Agent Campaign Dialing <QXZ>This option will allow you to set SHARED campaign Dial Methods in order to share agents across multiple outbound campaigns. For more details on how to set this up properly, read the AGENT_MULTI-CAMPAIGN_DIALING.txt document. Default is 0 for disabled.</QXZ>
settings-ofcom_uk_drop_calc UK OFCOM Drop Calculation <QXZ>This option allows you to enable the new UK OFCOM Drop calculation formula for individual campaigns. As of December 2015, OFCOM in the UK changed their method for calculating the drop,or abandon, percentage for an outbound dialing campaign. The new formula includes an estimate of the number of drops that were answering machines. They do this by using the agent-answered percentage of answering machines and subtracting that percentage from the number of drops. Then that new drop number is divided by the total agent-answered human-answered calls PLUS the number of drops. This differs in several ways from the way it had been done, as well as the way the drop percentage has been calculated in the USA and Canada. This new UK drop calculation method can be activated as a system setting AND a campaign option. Both must be enabled for the campaign to use the new method. In order for agent-statused answering machines to be calculated properly, we have added an answering machine status flag that is used to gather those statuses. Default is 0 for inactive.</QXZ>
settings-disable_auto_dial Disable Auto-Dial <QXZ>This option is only editable by a system administrator. It will not remove any options from the management web interface, but it will prevent any auto-dialing of leads from happening on the system. Only Manual Dial outbound calls triggered directly by agents will function if this option is enabled. Default is 0 for inactive.</QXZ>
settings-auto_dial_limit Ratio Dial Limit <QXZ>This is the maximum limit of the auto dial level in the campaign screen.</QXZ>
@@ -1065,7 +1067,7 @@ settings-callcard_enabled Enable CallCard <QXZ>This setting enables the CallCard
settings-test_campaign_calls Enable Campaign Test Calls <QXZ>This setting enables the ability to enter a phone code and phone number into fields at the bottom of the Campaign Detail screen and place a phone call to that number as if it were a lead being auto-dialed in the system. The phone number will be stored as a new lead in the manual dial list ID list. The campaign must be active for this feature to be enabled, and it is recommended that the lists assigned to the campaign all be set to inactive. The dial prefix, dial timeout and all other dialing related features, except for DNC and call time options, will affect the dialing of the test number. The phone call will be placed on the server selected as the voicemail server in the system settings. Default is 0 for disabled.</QXZ>
settings-did_system_filter DID System Filter <QXZ>This setting enables the special did_system_filter DID entry. The filter settings in this DID entry will be applied to all incoming calls to the system, prior to any other actions on the call. This feature is commonly used for system-wide inbound blacklists, or filtering of do-not-contact phone numbers. Default is 0 for disabled.</QXZ>
settings-inbound_answer_config Inbound Answer Configuration <QXZ>If enabled, this allows you to override the default behavior with inbound calls automatically being answered when they are routed. After this is enabled, you will see options to define if an Answer signal is sent at the individual DID, In-Group or Call Menu level. Default is 0 for disabled.</QXZ>
settings-enable_international_dncs Enable Interational DNCs <QXZ>If enabled, this allows you to create DNC lists for individual companies and provides the option to scrub against these lists when loading lead files.</QXZ>
settings-enable_international_dncs Enable Interational DNCs <QXZ>If enabled, this allows you to create DNC lists for individual countries and provides the option to scrub against these lists when loading lead files.</QXZ>
settings-user_new_lead_limit New Leads Per List Limit <QXZ>This setting enables the new lead limits per list to be set on the list modify page and the user list new lead limit page. This feature will only work properly if the campaign is set to either the MANUAL or INBOUND_MAN Dial Method and No Hopper dialing is enabled. Default is 0 for disabled.</QXZ>
settings-daily_call_count_limit Enable Daily Called Count Limits <QXZ>Enabling this setting will allow you to define a daily called count limit on a per campaign basis. Default is 0 for disabled.</QXZ>
settings-call_quota_lead_ranking Call Quota Lead Ranking <QXZ>This setting allows you to use the campaign setting for Call Quota Lead Ranking, which allows for a complex set of recycle dialing priorities for non-contact calls. Default is 0 for disabled.</QXZ>
@@ -1299,6 +1301,7 @@ rt_whiteboard_report-start_date Start date/time <QXZ>If filled out, the starting
rt_whiteboard_report-show_results Show results for the past X hours <QXZ>If filled out and the start date-time is NOT filled out, the selected report will compile data starting at the time X hours ago up through the current time, which makes it a dynamic starting time as opposed to the set date-time used in the previous parameter.</QXZ>
api_log_report API Log report <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.</QXZ><BR><BR><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.</QXZ>
sip_event_report SIP Event Report <QXZ>This report is only useful if you have enabled SIP Event Logging on your system(see the SIP Event Logging description in the Campaigns section in this manual for more information). This report will allow you to sort the SIP-messages for calls by several criteria. This report was used during the development of the campaign SIP Actions feature to help determine what calls were False Answer Supervision, by sorting the Ring-Time UP and DOWN.</QXZ>
quality_control_report Quality Control Report <QXZ>This report shows quality control call activity within user-selected parameters. If displayed as HTML, it will output each individual call with a header row that shows things like the call date, agent, campaign, call status, QC scorecard and QC result. Underneath that, each checkpoint in the scorecard applied to call will be displayed as individual rows with scores and comments per checkpoint. The report can also be downloaded as a CSV where each call will be a row in the resulting file with the checkpoint data appended toe ach row.</QXZ><BR><BR><QXZ><U>CALL DATE</U> = The date range in which the call was originally made.</QXZ><BR><QXZ><U>FINISH DATE</U> = The date the QC agent who evaluated the call marked it as finished. This will automatically filter out unfinished calls if this is used, regardless of what QC statuses (see below) are selected.</QXZ><BR><QXZ><U>CAMPAIGNS</U> = The campaign the original call was made under.</QXZ><BR><QXZ><U>QC STATUS</U> = The current status of the call in the quality control system - this is NOT the call status from dialing.</QXZ><BR><QXZ><U>USERS</U> = The agent(s) who placed the original calls.</QXZ><BR><QXZ><U>QC AGENTS</U> = The agents who evaluated the call in the quality control system.</QXZ><BR><QXZ><U>SHOW %s</U> = If this box is checked, the scores given by the QC agents will be displayed as percentages instead of points.</QXZ><BR><QXZ><U>SEARCH ARCHIVED DATA</U> = If this is checked, the archived quality control log tables will be searched if they exist.</QXZ>
nanpa-running Currently running NANPA scrubs <QXZ>Displays a log of the currently running scrubs, including: Start Time, Leads Count, Filter Count, Status Line, Time to Complete, Field Updated, and Field excluded</QXZ>
nanpa-settings Inactive Lists <QXZ>Contains all the inactive lists, that are eligible to be scrubbed. A list can only be scrubbed if Active is set to N on the list.</QXZ><BR><B><QXZ>Field to Update</QXZ> -</B><QXZ>Indicates which lead field will contain the scrub result -Cellphone, Landline, or Invalid-. If NONE is selected it will use the default field Country_Code.</QXZ><BR><B><QXZ>Exclusion Field</QXZ> -</B><QXZ>In conjunction with Exclusion Value allows administrators to indicate leads that are not to be scanned. This field indicates which list field contains the scrub result.</QXZ><BR><B><QXZ>Exclusion Value</QXZ> -</B><QXZ>In conjunction with Exclusion Field allows administrators to indicate leads that are not to be scanned. This field indicates which scrub result -either Cellphone, Landline, or Invalid- should be ignored.</QXZ><BR><B><QXZ>List Conversions</QXZ> -</B><QXZ>Administrators can indicate a list ID in any of the fields -Cellphone, Landline, or Invalid- and the scrub will move all the corresponding stamped leads to that list.</QXZ><BR><B><QXZ>Time until Activation</QXZ> -</B><QXZ>allows The administrator to set how long, in the future, the scrub will occur.</QXZ>
nanpa-log View Past Scrubs <QXZ>-link at the bottom- Click to see a log of all previous scrubs, including: Start Time, Leads Count, Filter Count, Status Line, Time to Complete, Field updated, Field Excluded, and total leads in each category.</QXZ>