diff --git a/UPGRADE b/UPGRADE index 53a86d99..4d4cbb65 100644 --- a/UPGRADE +++ b/UPGRADE @@ -117,6 +117,11 @@ NOTE: Upgrading from 1.1.12-3 to 2.0.1 is at the bottom 24. Added Calls in Queue counter to agent vicidial.php screen +25. Added ability to use calltime scheme for calls not yet in an in-group(queue) + as well as display in real-time stats. See Inbound_VDAC_IVR.txt doc for + more information + + diff --git a/agi/agi-VDAD_ALL_inbound.agi b/agi/agi-VDAD_ALL_inbound.agi index 0d4d027d..afe85bc1 100644 --- a/agi/agi-VDAD_ALL_inbound.agi +++ b/agi/agi-VDAD_ALL_inbound.agi @@ -60,6 +60,7 @@ # 80402-0142 - added code for manual dial transfer duplicate check # 80430-1144 - added term_reason to vicidial_closer_log, QUEUETIMEOUT, AFTERHOURS # 80501-0515 - added after hours transfer in-group +# 80525-1040 - added ability to convert IVR status inbound calls to LIVE in-group calls # $script = 'agi-VDAD_ALL_inbound.agi'; @@ -700,10 +701,32 @@ if ($call_handle_method =~ /CLOSER|DIGITID$/) if ($AGILOG) {$agi_string = "-- VDXL : |$insert_lead_id|$insert_xfer_id|insert to vicidial_xfer_log"; &agi_output;} } -### insert a LIVE record to the vicidial_auto_calls table -$stmtA = "INSERT INTO vicidial_auto_calls (server_ip,campaign_id,status,lead_id,uniqueid,callerid,channel,phone_code,phone_number,call_time,call_type,stage,queue_priority) values('$VARserver_ip','$channel_group','LIVE','$insert_lead_id','$uniqueid','$callerid','$channel','$phone_code','$phone_number','$SQLdate','IN','LIVE-0','$queue_priority')"; - if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} -$affected_rows = $dbhA->do($stmtA); + +### check for an IVR status record in vicidial_auto_calls +$Uaffected_rows=0; +$stmtA = "select auto_call_id from vicidial_auto_calls where uniqueid='$uniqueid' 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; + $auto_call_id = "$aryA[0]"; + + ### UPDATE existing record to LIVE in the vicidial_auto_calls table + $stmtA = "UPDATE vicidial_auto_calls SET campaign_id='$channel_group',status='LIVE',lead_id='$insert_lead_id',callerid='$callerid',channel='$channel',phone_code='$phone_code',phone_number='$phone_number',call_time='$SQLdate',call_type='IN',stage='LIVE-0',queue_priority='$queue_priority' WHERE auto_call_id='$auto_call_id';"; + if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} + $Uaffected_rows = $dbhA->do($stmtA); + } +$sthA->finish(); + +if ($Uaffected_rows < 1) + { + ### insert a LIVE record to the vicidial_auto_calls table + $stmtA = "INSERT INTO vicidial_auto_calls (server_ip,campaign_id,status,lead_id,uniqueid,callerid,channel,phone_code,phone_number,call_time,call_type,stage,queue_priority) values('$VARserver_ip','$channel_group','LIVE','$insert_lead_id','$uniqueid','$callerid','$channel','$phone_code','$phone_number','$SQLdate','IN','LIVE-0','$queue_priority')"; + if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} + $affected_rows = $dbhA->do($stmtA); + } $stmtA = "INSERT INTO vicidial_closer_log (lead_id,campaign_id,call_date,start_epoch,status,phone_code,phone_number,user,processed,xfercallid) values('$insert_lead_id','$channel_group','$SQLdate','$now_date_epoch','QUEUE','$phone_code','$phone_number','VDCL','N','$insert_xfer_id')"; if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} diff --git a/agi/agi-VDAD_inbound_calltime_check.agi b/agi/agi-VDAD_inbound_calltime_check.agi new file mode 100644 index 00000000..4614b5bd --- /dev/null +++ b/agi/agi-VDAD_inbound_calltime_check.agi @@ -0,0 +1,463 @@ +#!/usr/bin/perl +# +# agi-VDAD_inbound_calltime_check.agi version 2.0.5 +# +# runs when a call comes in from an inbound call. This script will check the +# settings of the defined calltime scheme in VICIDIAL and either send the call +# to the after-hours method for the defined IN-GROUP or exit to let the call +# continue +# +# You need to put lines similar to those below in your extensions.conf file: +# ; Below are the parameters needed for the script to be run properly +# ; 1. the in-group to take settings from +# ; 2. whether to log the call into the vicidial_auto_calls table: +# ; - YES - insert the call as status IVR +# ; - NO - do not insert call into vac table +# +# ;inbound calls check calltime: +#exten => 1234,1,Answer ; Answer the line +#exten => 1234,2,AGI(agi-VDAD_inbound_calltime_check.agi,INBOUND-----YES) +#exten => 1234,3,Hangup +# +# Copyright (C) 2008 Matt Florell LICENSE: AGPLv2 +# +# changes: +# 80525-0144 - First Build +# + +$script = 'agi-VDAD_inbound_calltime_check.agi'; + +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +$year = ($year + 1900); +$mon++; +if ($mon < 10) {$mon = "0$mon";} +if ($mday < 10) {$mday = "0$mday";} +if ($hour < 10) {$Fhour = "0$hour";} +if ($min < 10) {$min = "0$min";} +if ($sec < 10) {$sec = "0$sec";} + +$hm = "$hour$min"; +$hm = ($hm + 0); + +$now_date_epoch = time(); +$now_date = "$year-$mon-$mday $hour:$min:$sec"; +$CLInow_date = "$year-$mon-$mday\\ $hour:$min:$sec"; +$start_time=$now_date; + $CIDdate = "$mon$mday$hour$min$sec"; + $tsSQLdate = "$year$mon$mday$hour$min$sec"; + $SQLdate = "$year-$mon-$mday $hour:$min:$sec"; + $SQLdateBEGIN = $SQLdate; + +$BDtarget = ($now_date_epoch + 600); +($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";} + $last_update_time = "$Byear$Bmon$Bmday$Bhour$Bmin$Bsec"; + +# default path to astguiclient configuration file: +$PATHconf = '/etc/astguiclient.conf'; + +open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n"; +@conf = ; +close(conf); +$i=0; +foreach(@conf) + { + $line = $conf[$i]; + $line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi; + if ( ($line =~ /^PATHhome/) && ($CLIhome < 1) ) + {$PATHhome = $line; $PATHhome =~ s/.*=//gi;} + if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) ) + {$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;} + if ( ($line =~ /^PATHagi/) && ($CLIagi < 1) ) + {$PATHagi = $line; $PATHagi =~ s/.*=//gi;} + if ( ($line =~ /^PATHweb/) && ($CLIweb < 1) ) + {$PATHweb = $line; $PATHweb =~ s/.*=//gi;} + if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) ) + {$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;} + if ( ($line =~ /^PATHmonitor/) && ($CLImonitor < 1) ) + {$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;} + if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) ) + {$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) ) + {$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) ) + {$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) ) + {$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) ) + {$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;} + if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) ) + {$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;} + $i++; + } + +if (!$VARDB_port) {$VARDB_port='3306';} +if (!$AGILOGfile) {$AGILOGfile = "$PATHlogs/agiout.$year-$mon-$mday";} +if (!$PRSLOGfile) {$PRSLOGfile = "$PATHlogs/prsout.$year-$mon-$mday";} +if (!$PRSTESTfile) {$PRSTESTfile = "$PATHlogs/prstest.$year-$mon-$mday";} + +use DBI; +use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second +use Asterisk::AGI; +$AGI = new Asterisk::AGI; + +$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass") + or die "Couldn't connect to database: " . DBI->errstr; + +### Grab Server values from the database +$stmtA = "SELECT agi_output FROM servers where server_ip = '$VARserver_ip';"; +$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) + { + $AGILOG = '0'; + @aryA = $sthA->fetchrow_array; + $DBagi_output = "$aryA[0]"; + if ($DBagi_output =~ /STDERR/) {$AGILOG = '1';} + if ($DBagi_output =~ /FILE/) {$AGILOG = '2';} + if ($DBagi_output =~ /BOTH/) {$AGILOG = '3';} + $rec_count++; + } +$sthA->finish(); + + +### begin parsing run-time options ### +if (length($ARGV[0])>1) +{ + if ($AGILOG) {$agi_string = "Perl Environment Dump:"; &agi_output;} + $i=0; + while ($#ARGV >= $i) + { + $args = "$args $ARGV[$i]"; + if ($AGILOG) {$agi_string = "$i|$ARGV[$i]"; &agi_output;} + $i++; + } + + ### list of command-line array arguments: + @ARGV_vars = split(/-----/, $ARGV[0]); + + $channel_group = $ARGV_vars[0]; + $log_to_vac = $ARGV_vars[1]; +} + +$|=1; +while() +{ + chomp; + last unless length($_); + if ($AGILOG) + { + if (/^agi_(\w+)\:\s+(.*)$/) + { + $AGI{$1} = $2; + } + } + + if (/^agi_uniqueid\:\s+(.*)$/) {$unique_id = $1; $uniqueid = $unique_id;} + if (/^agi_channel\:\s+(.*)$/) {$channel = $1;} + if (/^agi_extension\:\s+(.*)$/) {$extension = $1;} + if (/^agi_type\:\s+(.*)$/) {$type = $1;} + if (/^agi_callerid\:\s+(.*)$/) {$callerid = $1;} + if (/^agi_calleridname\:\s+(.*)$/) {$calleridname = $1;} +} + + +if ( ($callerid =~ /\".*\"/) && ( (!$calleridname) or ($calleridname =~ /unknown/) ) ) + { + $calleridname = $callerid; + $calleridname =~ s/\<\d\d\d\d\d\d\d\d\d\d\>//gi; + $calleridname =~ s/\"|\" //gi; + } + + $callerid =~ s/\D//gi; + $calleridname =~ s/unknown//gi; +if ( (!$callerid) or ($callerid =~ /unknown/) ) + {$callerid = $calleridname;} + + +if (length($callerid)>0) {$phone_number = $callerid;} + else {$phone_number = '';} +if (length($calleridname)>0) {$VLcomments = $calleridname;} + else {$VLcomments = '';} +if (length($callerid)<8) {$callerid = $parked_by;} +if (length($pin)>0) {$callerid = $pin;} + + +foreach $i (sort keys %AGI) +{ + if ($AGILOG) {$agi_string = " -- $i = $AGI{$i}"; &agi_output;} +} + +if ($AGILOG) {$agi_string = "AGI Variables: |$unique_id|$channel|$extension|$type|$callerid|"; &agi_output;} + + +if (length($pin) < 1) {$pin=$inbound_number;} + +$fronter = $pin; + +if ($AGILOG) {$agi_string = "+++++ INBOUND CALL VDCL STARTED : |$channel_group|$callerid-$pin|$now_date"; &agi_output;} + +$VDADphone=''; +$VDADphone_code=''; + +if ($channel =~ /Local/i) +{ + if ($AGILOG) {$agi_string = "+++++ VDAD START LOCAL CHANNEL: EXITING- $priority"; &agi_output;} + exit; +} + +### Grab Server values from the database +$cbc=0; +$stmtA = "SELECT voicemail_dump_exten,ext_context,answer_transfer_agent,local_gmt,asterisk_version,max_vicidial_trunks FROM servers where server_ip = '$VARserver_ip';"; +$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; +$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; +$sthArows=$sthA->rows; +while ($sthArows > $cbc) + { + @aryA = $sthA->fetchrow_array; + + $DBvoicemail_dump_exten = "$aryA[0]"; + $DBext_context = "$aryA[1]"; + $DBanswer_transfer_agent = "$aryA[2]"; + $DBSERVER_GMT = "$aryA[3]"; + $DBasterisk_version = "$aryA[4]"; + $DBmax_vicidial_trunks = "$aryA[5]"; + if ($DBvoicemail_dump_exten) {$voicemail_dump_exten = $DBvoicemail_dump_exten;} + if ($DBext_context) {$ext_context = $DBext_context;} + if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;} + if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;} + if ($DBasterisk_version) {$AST_ver = $DBasterisk_version;} + if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;} + $cbc++; + } +$sthA->finish(); + +### Grab inbound groups values from the database +$cbc=0; +$stmtA = "SELECT call_time_id,after_hours_action,after_hours_message_filename,after_hours_exten,after_hours_voicemail,welcome_message_filename,moh_context,onhold_prompt_filename,prompt_interval,agent_alert_exten,agent_alert_delay,drop_call_seconds,drop_action,drop_exten,next_agent_call,voicemail_ext,queue_priority,drop_inbound_group,afterhours_xfer_group FROM vicidial_inbound_groups where group_id = '$channel_group';"; +$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; +$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; +$sthArows=$sthA->rows; +while ($sthArows > $cbc) + { + @aryA = $sthA->fetchrow_array; + + $call_time_id = "$aryA[0]"; + $after_hours_action = "$aryA[1]"; + $after_hours_message_filename = "$aryA[2]"; + $after_hours_exten = "$aryA[3]"; + $after_hours_voicemail = "$aryA[4]"; + $welcome_message_filename = "$aryA[5]"; + $moh_context = "$aryA[6]"; + $onhold_prompt_filename = "$aryA[7]"; + $prompt_interval = "$aryA[8]"; + $agent_alert_exten = "$aryA[9]"; + $agent_alert_delay = "$aryA[10]"; + $drop_call_seconds = "$aryA[11]"; + $DROP_TIME = $drop_call_seconds; + $drop_action = "$aryA[12]"; + $drop_exten = "$aryA[13]"; + $CAMP_callorder = "$aryA[14]"; + $VDADvoicemail_ext = "$aryA[15]"; + $VDADvoicemail_ext =~ s/\D//gi; + $queue_priority = "$aryA[16]"; + $drop_inbound_group = "$aryA[17]"; + $afterhours_xfer_group = "$aryA[18]"; + $cbc++; + } +$sthA->finish(); + +if ($wday==0) {$daySQL=',ct_sunday_start,ct_sunday_stop';} +if ($wday==1) {$daySQL=',ct_monday_start,ct_monday_stop';} +if ($wday==2) {$daySQL=',ct_tuesday_start,ct_tuesday_stop';} +if ($wday==3) {$daySQL=',ct_wednesday_start,ct_wednesday_stop';} +if ($wday==4) {$daySQL=',ct_thursday_start,ct_thursday_stop';} +if ($wday==5) {$daySQL=',ct_friday_start,ct_friday_stop';} +if ($wday==6) {$daySQL=',ct_saturday_start,ct_saturday_stop';} + +### Grab call_times values from the database +$stmtA = "SELECT ct_default_start,ct_default_stop $daySQL FROM vicidial_call_times where call_time_id = '$call_time_id';"; +$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; +$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; +$sthArows=$sthA->rows; +@aryA = $sthA->fetchrow_array; +$ct_default_start = "$aryA[0]"; +$ct_default_stop = "$aryA[1]"; +$ct_day_start = "$aryA[2]"; +$ct_day_stop = "$aryA[3]"; +$sthA->finish(); + +if ( ($ct_day_start > 0) || ($ct_day_stop > 0) ) + { + $ct_default_start = $ct_day_start; + $ct_default_stop = $ct_day_stop; + } + +$AGI->stream_file('beep'); + + + + +##### BEGIN AFTER HOURS CHECK ##### +if ( ($hm < $ct_default_start) || ($hm > $ct_default_stop) ) + { + $VHqueryCID = "VA$CIDdate$hour$min$sec$sec"; + + if ($after_hours_action =~ /EXTENSION|VOICEMAIL|IN_GROUP/) + { + if ($after_hours_action =~ /EXTENSION/) + { + $DROPexten = "$after_hours_exten"; + } + if ($after_hours_action =~ /VOICEMAIL/) + { + $DROPexten = "$voicemail_dump_exten$after_hours_voicemail"; + } + if ($after_hours_action =~ /IN_GROUP/) + { # 90009*CL_uk3survy_*8301*10000123*universal*7275551212*1234*" + $S='*'; + $DROPexten = "90009*$afterhours_xfer_group$S$S$insert_lead_id$S$S$phone_number$S$fronter$S"; + } + if (length($DROPexten)>0) + { ### if DROP extension is defined then send the dropped call there instead of hangup + + $AGI->stream_file('ding'); # stop music-on-hold process + + sleep(1); + + if ($AGILOG) {$agi_string = "exiting the VDAD app after hours, transferring call to $DROPexten"; &agi_output;} + print "SET CONTEXT $ext_context\n"; + checkresult($result); + print "SET EXTENSION $DROPexten\n"; + checkresult($result); + print "SET PRIORITY 1\n"; + checkresult($result); + } + } + $stmtA = "DELETE FROM vicidial_auto_calls where callerid='$callerid' and uniqueid='$uniqueid' and server_ip='$VARserver_ip' order by call_time desc limit 1;"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "-- VDCL vac record deleted: |$affected_rows| $uniqueid|$callerid|"; &agi_output;} + + $stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,start_time) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$SQLdate')"; + if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} + $affected_rowsL = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "-- LIL : |$affected_rowsL|$uniqueid|$callerid|$extension|"; &agi_output;} + + if ($after_hours_action =~ /HANGUP/) + { + ### insert a NEW record to the vicidial_manager table to hangup the channel + $stmtA = "INSERT INTO vicidial_manager values('','','$SQLdate','NEW','N','$VARserver_ip','','Hangup','$VHqueryCID','Channel: $channel','','','','','','','','','')"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "-- VDCL call_hungup after hours: |$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;} + } + if ($after_hours_action =~ /MESSAGE/) + { + $AGI->stream_file('sip-silence'); + $AGI->stream_file("$after_hours_message_filename"); + sleep(1); + + ### insert a NEW record to the vicidial_manager table to hangup the channel + $stmtA = "INSERT INTO vicidial_manager values('','','$SQLdate','NEW','N','$VARserver_ip','','Hangup','$VHqueryCID','Channel: $channel','','','','','','','','','')"; + $affected_rows = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "-- VDCL call_hungup after hours: |$VHqueryCID|$VDADconf_exten|$channel|insert to vicidial_manager"; &agi_output;} + } + + $dbhA->disconnect(); + + exit; + + } +##### END AFTER HOURS CHECK ##### + + + +### insert an IVR record to the vicidial_auto_calls table +if ($log_to_vac == 'YES') + { + $stmtA = "INSERT INTO vicidial_auto_calls (server_ip,campaign_id,lead_id,status,uniqueid,callerid,channel,phone_code,phone_number,call_time,call_type,stage,queue_priority,last_update_time) values('$VARserver_ip','$channel_group','0','IVR','$uniqueid','$callerid','$channel','$phone_code','$phone_number','$SQLdate','IN','IVR-0','$queue_priority','$last_update_time')"; + if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} + $affected_rowsV = $dbhA->do($stmtA); + if ($AGILOG) {$agi_string = "-- VAC : |$affected_rowsV|$uniqueid|$callerid|$extension|"; &agi_output;} + } + +$stmtA = "INSERT INTO live_inbound_log (uniqueid,channel,server_ip,caller_id,extension,start_time) values('$uniqueid','$channel','$VARserver_ip','$callerid','$extension','$SQLdate')"; + if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} +$affected_rowsL = $dbhA->do($stmtA); +if ($AGILOG) {$agi_string = "-- LIL : |$affected_rowsL|$uniqueid|$callerid|$extension|"; &agi_output;} + + +$dbhA->disconnect(); + +exit; + + + + + + + +sub checkresult { + my ($res) = @_; + my $retval; + $tests++; + chomp $res; + if ($res =~ /^200/) { + $res =~ /result=(-?\d+)/; + if (!length($1)) { + # print STDERR "FAIL ($res)\n"; + $fail++; + } else { + # print STDERR "PASS ($1)\n"; + $pass++; + } + } else { + # print STDERR "FAIL (unexpected result '$res')\n"; + $fail++; + } +} + + +sub agi_output +{ +if ($AGILOG >=2) + { + ### open the log file for writing ### + open(Lout, ">>$AGILOGfile") + || die "Can't open $AGILOGfile: $!\n"; + print Lout "$now_date|$script|$agi_string\n"; + close(Lout); + } + ### send to STDERR writing ### +if ( ($AGILOG == '1') || ($AGILOG == '3') ) + {print STDERR "$now_date|$script|$agi_string\n";} +$agi_string=''; +} + + +sub trigger_transfer_process +{ +# $DS='--'; +# $BEGIN='BEGIN'; +# +# $CLI = "/usr/bin/date >> $PRSTESTfile &"; +# $CLI = "/root/phone.pl $insert_lead_id$DS$insert_close_id$DS$CLInow_date$DS$VDADuser$DS$phone_number$DS$DS$BEGIN$DS >> $PRSTESTfile &"; +# +# `$CLI`; +# +# if ($AGILOG >=2) +# { +# ### open the log file for writing ### +# open(Pout, ">>$PRSLOGfile") +# || die "Can't open $AGILOGfile: $!\n"; +# print Pout "$now_date|$VDADconf_exten|$VDADuser|$VDADextension|$insert_lead_id|$phone_number|$insert_close_id|$channel_group|$drop_timer|$CLI|\n"; +# close(Pout); +# } +} diff --git a/bin/AST_VDauto_dial.pl b/bin/AST_VDauto_dial.pl index 1f91f5de..3b541a15 100644 --- a/bin/AST_VDauto_dial.pl +++ b/bin/AST_VDauto_dial.pl @@ -66,6 +66,7 @@ # 71029-1909 - Changed CLOSER-type campaign_id restriction # 71030-2054 - Added hopper priority sorting # 80227-0406 - added queue_priority +# 80525-1040 - Added IVR vac status compatibility for inbound calls # @@ -340,7 +341,7 @@ while($one_day_interval > 0) $sthA->finish(); ### see how many total VDAD calls are going on right now for max limiter - $stmtA = "SELECT count(*) FROM vicidial_auto_calls where server_ip='$server_ip' and status IN('SENT','RINGING','LIVE','XFER','CLOSER');"; + $stmtA = "SELECT count(*) FROM vicidial_auto_calls where server_ip='$server_ip' and status IN('SENT','RINGING','LIVE','XFER','CLOSER','IVR');"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; @@ -883,7 +884,7 @@ while($one_day_interval > 0) @KLchannel = @MT; $kill_vac=0; - $stmtA = "SELECT callerid,server_ip,channel,uniqueid FROM vicidial_auto_calls where server_ip='$server_ip' order by call_time;"; + $stmtA = "SELECT callerid,server_ip,channel,uniqueid,status FROM vicidial_auto_calls where server_ip='$server_ip' order by call_time;"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; @@ -897,6 +898,7 @@ while($one_day_interval > 0) $KLserver_ip[$kill_vac] = "$aryA[1]"; $KLchannel[$kill_vac] = "$aryA[2]"; $KLuniqueid[$kill_vac] = "$aryA[3]"; + $KLstatus[$kill_vac] = "$aryA[4]"; $kill_vac++; $rec_count++; } @@ -908,23 +910,28 @@ while($one_day_interval > 0) if (length($KLserver_ip[$kill_vac]) > 7) { $end_epoch=0; $CLuniqueid=''; + $KLcalleridCHECK[$kill_vac]=$KLcallerid[$kill_vac]; + $KLcalleridCHECK[$kill_vac] =~ s/\W//gi; - $stmtA = "SELECT end_epoch,uniqueid FROM call_log where caller_code='$KLcallerid[$kill_vac]' and server_ip='$KLserver_ip[$kill_vac]' order by end_epoch, start_time desc limit 1;"; - $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; - $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; - $sthArows=$sthA->rows; - $rec_count=0; - $rec_countCUSTDATA=0; - while ($sthArows > $rec_count) + if ( (length($KLcalleridCHECK[$kill_vac]) > 17) && ($KLcalleridCHECK[$kill_vac] =~ /\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) ) { - @aryA = $sthA->fetchrow_array; - $end_epoch = "$aryA[0]"; - $CLuniqueid = "$aryA[1]"; - $rec_count++; + $stmtA = "SELECT end_epoch,uniqueid FROM call_log where caller_code='$KLcallerid[$kill_vac]' and server_ip='$KLserver_ip[$kill_vac]' order by end_epoch, start_time desc limit 1;"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthArows=$sthA->rows; + $rec_count=0; + $rec_countCUSTDATA=0; + while ($sthArows > $rec_count) + { + @aryA = $sthA->fetchrow_array; + $end_epoch = "$aryA[0]"; + $CLuniqueid = "$aryA[1]"; + $rec_count++; + } + $sthA->finish(); } - $sthA->finish(); - if ( (length($KLuniqueid[$kill_vac]) > 15) && (length($CLuniqueid) < 15) ) + if ( (length($KLuniqueid[$kill_vac]) > 11) && (length($CLuniqueid) < 12) ) { $stmtA = "SELECT end_epoch,uniqueid FROM call_log where uniqueid='$KLuniqueid[$kill_vac]' and server_ip='$KLserver_ip[$kill_vac]' order by end_epoch, start_time desc limit 1;"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; @@ -996,11 +1003,14 @@ while($one_day_interval > 0) } - $stmtA = "UPDATE vicidial_list set status='$CLnew_status' where lead_id='$CLlead_id'"; - $affected_rows = $dbhA->do($stmtA); + if ($CLlead_id > 0) + { + $stmtA = "UPDATE vicidial_list set status='$CLnew_status' where lead_id='$CLlead_id'"; + $affected_rows = $dbhA->do($stmtA); - $event_string = "| dead call vac lead marked $CLnew_status|$CLlead_id|$CLphone_number|$CLstatus|"; - &event_logger; + $event_string = "| dead call vac lead marked $CLnew_status|$CLlead_id|$CLphone_number|$CLstatus|"; + &event_logger; + } $stmtA = "UPDATE vicidial_live_agents set status='PAUSED',random_id='10' where callerid='$KLcallerid[$kill_vac]';"; $affected_rows = $dbhA->do($stmtA); @@ -1039,7 +1049,7 @@ while($one_day_interval > 0) $epc_countCAMPDATA++; } $sthA->finish(); - if ($VD_auto_alt_dial_statuses =~ / $CLnew_status /) + if ( ($VD_auto_alt_dial_statuses =~ / $CLnew_status /) && ($CLlead_id > 0) ) { if ( ($VD_auto_alt_dial =~ /(ALT_ONLY|ALT_AND_ADDR3)/) && ($CLalt_dial =~ /NONE|MAIN/) ) { @@ -1171,7 +1181,7 @@ while($one_day_interval > 0) ### delete call records that are SENT for over 2 minutes - $stmtA = "DELETE FROM vicidial_auto_calls where server_ip='$server_ip' and call_time < '$XDSQLdate' and status NOT IN('XFER','CLOSER','LIVE')"; + $stmtA = "DELETE FROM vicidial_auto_calls where server_ip='$server_ip' and call_time < '$XDSQLdate' and status NOT IN('XFER','CLOSER','LIVE','IVR')"; $affected_rows = $dbhA->do($stmtA); $event_string = "| lagged call vac agent DELETED $affected_rows|$XDSQLdate|"; @@ -1197,7 +1207,7 @@ while($one_day_interval > 0) } ### find call records that are LIVE and not updated for over 10 seconds - $stmtA = "SELECT auto_call_id,lead_id,phone_number,status,campaign_id,phone_code,alt_dial,stage,callerid,uniqueid from vicidial_auto_calls where server_ip='$server_ip' and last_update_time < '$BDtsSQLdate' and status IN('LIVE');"; + $stmtA = "SELECT auto_call_id,lead_id,phone_number,status,campaign_id,phone_code,alt_dial,stage,callerid,uniqueid from vicidial_auto_calls where server_ip='$server_ip' and last_update_time < '$BDtsSQLdate' and status IN('LIVE','IVR');"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; @@ -1229,7 +1239,7 @@ while($one_day_interval > 0) $event_string = "| lagged call vdac call DELETED $affected_rows|$BDtsSQLdate|"; &event_logger; - if ($affected_rows > 0) + if ( ($affected_rows > 0) && ($CLlead_id > 0) ) { $jam_string = "| lagged call vdac call DELETED $affected_rows|$BDtsSQLdate|"; &jam_event_logger; @@ -1342,7 +1352,7 @@ while($one_day_interval > 0) ##### END QUEUEMETRICS LOGGING LOOKUP ##### ########################################### - ### delete call records that are LIVE for over 10 minutes + ### delete call records that are LIVE for over 100 minutes $stmtA = "DELETE FROM vicidial_auto_calls where server_ip='$server_ip' and call_time < '$TDSQLdate' and status NOT IN('XFER','CLOSER')"; $affected_rows = $dbhA->do($stmtA); @@ -1506,7 +1516,7 @@ if ($Xmin < 10) {$Xmin = "0$Xmin";} if ($Xsec < 10) {$Xsec = "0$Xsec";} $XDSQLdate = "$Xyear-$Xmon-$Xmday $Xhour:$Xmin:$Xsec"; -$TDtarget = ($secX - 600); +$TDtarget = ($secX - 6000); ($Tsec,$Tmin,$Thour,$Tmday,$Tmon,$Tyear,$Twday,$Tyday,$Tisdst) = localtime($TDtarget); $Tyear = ($Tyear + 1900); $Tmon++; diff --git a/bin/FastAGI_log.pl b/bin/FastAGI_log.pl index 53360210..056568e5 100644 --- a/bin/FastAGI_log.pl +++ b/bin/FastAGI_log.pl @@ -38,6 +38,7 @@ # 80507-1138 - Fixed vicidial_closer_log CALLER hangups # 80510-0414 - Fixed crossover logging bugs # 80510-2058 - Fixed status override bug +# 80525-1040 - Added IVR vac status compatibility for inbound calls # @@ -606,7 +607,7 @@ sub process_request { ########## FIND AND DELETE vicidial_auto_calls ########## $VD_alt_dial = 'NONE'; - $stmtA = "SELECT lead_id,callerid,campaign_id,alt_dial,stage,UNIX_TIMESTAMP(call_time),uniqueid FROM vicidial_auto_calls where uniqueid = '$uniqueid' or callerid = '$callerid' limit 1;"; + $stmtA = "SELECT lead_id,callerid,campaign_id,alt_dial,stage,UNIX_TIMESTAMP(call_time),uniqueid,status FROM vicidial_auto_calls where uniqueid = '$uniqueid' or callerid = '$callerid' limit 1;"; if ($AGILOG) {$agi_string = "|$stmtA|"; &agi_output;} $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; @@ -622,6 +623,7 @@ sub process_request { $VD_stage = "$aryA[4]"; $VD_start_epoch = "$aryA[5]"; $VD_uniqueid = "$aryA[6]"; + $VD_status = "$aryA[7]"; $rec_countCUSTDATA++; } $sthA->finish(); @@ -632,9 +634,9 @@ sub process_request { } else { - $stmtA = "DELETE FROM vicidial_auto_calls where uniqueid='$uniqueid' or callerid = '$callerid' order by call_time desc limit 1;"; + $stmtA = "DELETE FROM vicidial_auto_calls where ( ( (status!='IVR') and (uniqueid='$uniqueid' or callerid = '$callerid') ) or ( (status='IVR') and (uniqueid='$uniqueid') ) ) order by call_time desc limit 1;"; $affected_rows = $dbhA->do($stmtA); - if ($AGILOG) {$agi_string = "-- VDAC record deleted: |$affected_rows| |$VD_lead_id|$uniqueid|$VD_uniqueid|$VD_callerid|$VARserver_ip"; &agi_output;} + if ($AGILOG) {$agi_string = "-- VDAC record deleted: |$affected_rows| |$VD_lead_id|$uniqueid|$VD_uniqueid|$VD_callerid|$VARserver_ip|$VD_status|"; &agi_output;} ############################################# ##### START QUEUEMETRICS LOGGING LOOKUP ##### diff --git a/docs/Inbound_VDAC_IVR.txt b/docs/Inbound_VDAC_IVR.txt new file mode 100644 index 00000000..a221670d --- /dev/null +++ b/docs/Inbound_VDAC_IVR.txt @@ -0,0 +1,59 @@ +Inbound VDAC IVR process 2008-05-25 + +This doc goes over the addition of the IVR status to the vicidial_auto_calls table and how calls that are not yet in an in-group(queue) can still be counted as active calls. This allows your system to show a tally of inbound calls that are still navigating menus before finding an in-group(queue) to be put into. + +The agi-VDAD_inbound_calltime_check.agi script does a check for the calltime scheme of the defined in-group(queue) as well as using the after-hours method for that in-group and the associated after-hours message if defined. Also, this script can place a record in the vicidial_auto_calls status in the IVR status. Calls in this status do not affect the dial ratios of blended campaigns, but they will display in the AST_timeonVDADall.php real-time status pages. + + + +The example below shows how to do a very simple IVR before sending to a queue asking if the caller wants English, Spanish, French or German language service. + +The "test_in_menu" audio file would have something like the following script: + +"Hello, thank you for calling ACME Service Inc. For English press one, para el +español, prensa dos, pour le Français, presse trois, für Deutschen Presse vier." + + + +extensions.conf additions: + + +; First, in the default context you will put a line sending the inbound calls +; for this number into a context named the same as the first in-group(queue), +; in this case "TEST_IN". There are also 3 other in-groups(queues) for the +; non-English in-groups(queues): +; TEST_IN - English - option 1 +; TEST_IN_ES - Spanish - option 2 +; TEST_IN_FR - French - option 3 +; TEST_IN_DE - German - option 4 + +[default] +exten => 7275551111,1,Goto(TEST_IN,1,1) + + +[TEST_IN] +exten => s,1,AGI(agi-VDAD_inbound_calltime_check.agi,TEST_IN-----YES) +exten => s,2,Background(test_in_menu) +exten => s.n.WaitExten(10) +exten => s,n,Background(test_in_menu) +exten => s.n.WaitExten(10) +exten => s,n,Playback(vm-goodbye) +exten => s,n,hangup + +exten => 1,1,AGI(agi-VDAD_ALL_inbound.agi,CIDLOOKUP-----LB-----TEST_IN-----7275551111-----Closer-----park----------999-----1-----OUTB) +exten => 1,n,Hangup + +exten => 2,1,AGI(agi-VDAD_ALL_inbound.agi,CIDLOOKUP-----LB-----TEST_IN_ES-----7275551111-----Closer-----park----------999-----1-----OUTB) +exten => 2,n,Hangup + +exten => 3,1,AGI(agi-VDAD_ALL_inbound.agi,CIDLOOKUP-----LB-----TEST_IN_FR-----7275551111-----Closer-----park----------999-----1-----OUTB) +exten => 3,n,Hangup + +exten => 4,1,AGI(agi-VDAD_ALL_inbound.agi,CIDLOOKUP-----LB-----TEST_IN_DE-----7275551111-----Closer-----park----------999-----1-----OUTB) +exten => 4,n,Hangup + +exten => #,1,Goto(s,2) +exten => i,1,Goto(s,2) +exten => t,1,Goto(s,2) +exten => h,1,DeadAGI(agi://127.0.0.1:4577/call_log--HVcauses--PRI-----NODEBUG-----${HANGUPCAUSE}-----${DIALSTATUS}-----${DIALEDTIME}-----${ANSWEREDTIME}) + diff --git a/extras/upgrade_2.0.5.sql b/extras/upgrade_2.0.5.sql index f7bca5ec..ee46ad6a 100644 --- a/extras/upgrade_2.0.5.sql +++ b/extras/upgrade_2.0.5.sql @@ -189,3 +189,16 @@ ALTER TABLE vicidial_timeclock_log ADD event_datestamp TIMESTAMP NOT NULL; ALTER TABLE vicidial_timeclock_log ADD tcid_link INT(9) UNSIGNED; UPDATE system_settings SET db_schema_version='1087'; + + + + + + + + + + +ALTER TABLE vicidial_auto_calls MODIFY status ENUM('SENT','RINGING','LIVE','XFER','PAUSED','CLOSER','BUSY','DISCONNECT','IVR') default 'PAUSED'; + +UPDATE system_settings SET db_schema_version='1088'; diff --git a/www/vicidial/AST_timeonVDADall.php b/www/vicidial/AST_timeonVDADall.php index 8dd3dc44..971436f0 100644 --- a/www/vicidial/AST_timeonVDADall.php +++ b/www/vicidial/AST_timeonVDADall.php @@ -33,6 +33,7 @@ # 80422-0033 - Added phonediaplay option, allow for toggle-sorting on sortable fields # 80422-1001 - Fixed sort by phone login # 80424-0515 - Added non_latin lookup from system_settings +# 80525-1040 - Added IVR status display and summary for inbound calls # header ("Content-type: text/html; charset=utf-8"); @@ -552,6 +553,7 @@ $parked_to_print = mysql_num_rows($rslt); $out_total=0; $out_ring=0; $out_live=0; + $in_ivr=0; while ($i < $parked_to_print) { $row=mysql_fetch_row($rslt); @@ -574,6 +576,22 @@ $parked_to_print = mysql_num_rows($rslt); } else { + if (eregi("IVR",$row[0])) + { + $in_ivr++; + + if ($CALLSdisplay > 0) + { + $CDstatus[$k] = $row[0]; + $CDcampaign_id[$k] = $row[1]; + $CDphone_number[$k] = $row[2]; + $CDserver_ip[$k] = $row[3]; + $CDcall_time[$k] = $row[4]; + $CDcall_type[$k] = $row[5]; + $CDqueue_priority[$k] = $row[6]; + $k++; + } + } if (eregi("CLOSER",$row[0])) {$nothing=1;} else @@ -596,6 +614,7 @@ $parked_to_print = mysql_num_rows($rslt); echo "$NFB$out_ring$NFE calls ringing         \n"; echo "$NFB$F  $out_live $FG$NFE calls waiting for agents       \n"; + echo "$NFB  $in_ivr$NFE calls in IVR       \n"; } else { diff --git a/www/vicidial/AST_timeonVDADallSUMMARY.php b/www/vicidial/AST_timeonVDADallSUMMARY.php index 0c9f0f94..11b1dec9 100644 --- a/www/vicidial/AST_timeonVDADallSUMMARY.php +++ b/www/vicidial/AST_timeonVDADallSUMMARY.php @@ -13,6 +13,7 @@ # 70111-1600 - added ability to use BLEND/INBND/*_C/*_B/*_I as closer campaigns # 70619-1339 - Added Status Category tally display # 71029-1900 - Changed CLOSER-type to not require campaign_id restriction +# 80525-1040 - Added IVR status summary display for inbound calls # header ("Content-type: text/html; charset=utf-8"); @@ -305,6 +306,7 @@ $parked_to_print = mysql_num_rows($rslt); $out_total=0; $out_ring=0; $out_live=0; + $in_ivr=0; while ($i < $parked_to_print) { $row=mysql_fetch_row($rslt); @@ -313,6 +315,8 @@ $parked_to_print = mysql_num_rows($rslt); {$out_live++;} else { + if (eregi("IVR",$row[0])) + {$in_ivr++;} if (eregi("CLOSER",$row[0])) {$nothing=1;} else @@ -334,6 +338,7 @@ $parked_to_print = mysql_num_rows($rslt); echo "$NFB$out_ring$NFE calls ringing         \n"; echo "$NFB$F  $out_live $FG$NFE calls waiting for agents       \n"; + echo "$NFB  $in_ivr$NFE calls in IVR       \n"; } else {