From 17768f69691a02ff534f90f642634a50a9ed64a1 Mon Sep 17 00:00:00 2001 From: mattf Date: Sat, 29 Apr 2017 01:14:30 +0000 Subject: [PATCH] Added Inbound and Advanced Forecasting Reports git-svn-id: svn://192.168.202.10@2743 3d104415-ff17-0410-8863-d5cf3c621b8a --- agc_2-X/trunk/UPGRADE | 3 + .../www/vicidial/AST_inbound_forecasting.php | 1316 ++++++++++++++++ agc_2-X/trunk/www/vicidial/Erlang_report.php | 1357 +++++++++++++++++ agc_2-X/trunk/www/vicidial/admin.php | 18 +- agc_2-X/trunk/www/vicidial/graphcanvas.inc | 5 +- agc_2-X/trunk/www/vicidial/help.php | 66 +- 6 files changed, 2758 insertions(+), 7 deletions(-) create mode 100644 agc_2-X/trunk/www/vicidial/AST_inbound_forecasting.php create mode 100644 agc_2-X/trunk/www/vicidial/Erlang_report.php diff --git a/agc_2-X/trunk/UPGRADE b/agc_2-X/trunk/UPGRADE index 2063bd82..7b03f9dd 100644 --- a/agc_2-X/trunk/UPGRADE +++ b/agc_2-X/trunk/UPGRADE @@ -147,6 +147,9 @@ OTHER CHANGES: 29. Added cm_fpg.agi script to allow callers to place their phone numbers into a Filter Phone Group. Works from a Call Menu. +30. Added Inbound and Advanced Forecasting Reports. Both use the Erlang formulas + and past data to forecast agent and call metrics. + diff --git a/agc_2-X/trunk/www/vicidial/AST_inbound_forecasting.php b/agc_2-X/trunk/www/vicidial/AST_inbound_forecasting.php new file mode 100644 index 00000000..8e47ae77 --- /dev/null +++ b/agc_2-X/trunk/www/vicidial/AST_inbound_forecasting.php @@ -0,0 +1,1316 @@ +, Joe Johnson LICENSE: AGPLv2 +# +# CHANGES +# +# 170428-1205 - First build +# + +$startMS = microtime(); + +require("dbconnect_mysqli.php"); +require("functions.php"); + + function factorial($num) { + $num=floor($num); + if ($num>0) { + $result=1; + for ($x=1; $x<=$num; $x++) { + $result*=$x; + } + return $result; + } else { + return 1; + } + } + function erlsum($low, $limit, $erlangs) { + $result=0; + for ($n=$low; $n<=$limit; $n++) { + $result+=pow($erlangs, $n)/(factorial($n)); + } + return $result; + } + function adjustedGoS($erlangs, $GoS, $retry_rate, $lines) { + $E[0]=$erlangs; + $P[0]=$GoS; + + for ($q=0; $q<100; $q++) { + $E[($q+1)]=$erlangs+($retry_rate/100)*$E[$q]*$P[$q]; + $P[($q+1)]=(pow($E[($q+1)], $lines)/(factorial($lines)))/(erlsum(0, $lines, $E[($q+1)])); + + } + return $P[100]; + } + +if (file_exists('options.php')) + { + require('options.php'); + } + +$PHP_AUTH_USER=$_SERVER['PHP_AUTH_USER']; +$PHP_AUTH_PW=$_SERVER['PHP_AUTH_PW']; +$PHP_SELF=$_SERVER['PHP_SELF']; +if (isset($_GET["group"])) {$group=$_GET["group"];} + elseif (isset($_POST["group"])) {$group=$_POST["group"];} +if (isset($_GET["campaign"])) {$campaign=$_GET["campaign"];} + elseif (isset($_POST["campaign"])) {$campaign=$_POST["campaign"];} +if (isset($_GET["query_date"])) {$query_date=$_GET["query_date"];} + elseif (isset($_POST["query_date"])) {$query_date=$_POST["query_date"];} +if (isset($_GET["end_date"])) {$end_date=$_GET["end_date"];} + elseif (isset($_POST["end_date"])) {$end_date=$_POST["end_date"];} +if (isset($_GET["drop_percent"])) {$drop_percent=$_GET["drop_percent"];} + elseif (isset($_POST["drop_percent"])) {$drop_percent=$_POST["drop_percent"];} +if (isset($_GET["shift"])) {$shift=$_GET["shift"];} + elseif (isset($_POST["shift"])) {$shift=$_POST["shift"];} +if (isset($_GET["erlang_type"])) {$erlang_type=$_GET["erlang_type"];} + elseif (isset($_POST["erlang_type"])) {$erlang_type=$_POST["erlang_type"];} +if (isset($_GET["actual_agents"])) {$actual_agents=$_GET["actual_agents"];} + elseif (isset($_POST["actual_agents"])) {$actual_agents=$_POST["actual_agents"];} +if (isset($_GET["hourly_pay"])) {$hourly_pay=$_GET["hourly_pay"];} + elseif (isset($_POST["hourly_pay"])) {$hourly_pay=$_POST["hourly_pay"];} +if (isset($_GET["revenue_per_sale"])) {$revenue_per_sale=$_GET["revenue_per_sale"];} + elseif (isset($_POST["revenue_per_sale"])) {$revenue_per_sale=$_POST["revenue_per_sale"];} +if (isset($_GET["sale_chance"])) {$sale_chance=$_GET["sale_chance"];} + elseif (isset($_POST["sale_chance"])) {$sale_chance=$_POST["sale_chance"];} +if (isset($_GET["retry_rate"])) {$retry_rate=$_GET["retry_rate"];} + elseif (isset($_POST["retry_rate"])) {$retry_rate=$_POST["retry_rate"];} +if (isset($_GET["target_pqueue"])) {$target_pqueue=$_GET["target_pqueue"];} + elseif (isset($_POST["target_pqueue"])) {$target_pqueue=$_POST["target_pqueue"];} +if (isset($_GET["file_download"])) {$file_download=$_GET["file_download"];} + elseif (isset($_POST["file_download"])) {$file_download=$_POST["file_download"];} +if (isset($_GET["submit"])) {$submit=$_GET["submit"];} + elseif (isset($_POST["submit"])) {$submit=$_POST["submit"];} +if (isset($_GET["SUBMIT"])) {$SUBMIT=$_GET["SUBMIT"];} + elseif (isset($_POST["SUBMIT"])) {$SUBMIT=$_POST["SUBMIT"];} +if (isset($_GET["DB"])) {$DB=$_GET["DB"];} + elseif (isset($_POST["DB"])) {$DB=$_POST["DB"];} +if (isset($_GET["report_display_type"])) {$report_display_type=$_GET["report_display_type"];} + elseif (isset($_POST["report_display_type"])) {$report_display_type=$_POST["report_display_type"];} + +if (strlen($shift)<2) {$shift='ALL';} + +$report_name = 'Inbound Forecasting Report'; +$db_source = 'M'; + +if ($ignore_afterhours=="checked") {$status_clause=" and status!='AFTHRS'";} + +$HTML_text=""; +$report_display_type="HTML"; + +# $actual_agents=preg_replace("/[^0-9.]/", "", $actual_agents); +# $actual_agents+=0; +# $hourly_pay=preg_replace("/[^0-9.]/", "", $hourly_pay); +# $hourly_pay+=0; +# $revenue_per_sale=preg_replace("/[^0-9.]/", "", $revenue_per_sale); +# $revenue_per_sale+=0; +# $sale_chance=preg_replace("/[^0-9.]/", "", $sale_chance); +# $sale_chance+=0; +# $retry_rate=preg_replace("/[^0-9.]/", "", $retry_rate); +# $retry_rate+=0; + +switch ($erlang_type) { + default: + case "B": + $erlB="checked"; + $erlC=""; + break; + case "C": + $erlB=""; + $erlC="checked"; + break; +} + +$JS_text="\n"; +$HEADER.="\n"; +$HEADER.="\n"; +# $HEADER.="\n"; +$HEADER.="\n"; +$HEADER.="\n"; +$HEADER.="\n"; +$HEADER.=""._QXZ("$report_name")."\n"; + +$short_header=1; + +$MAIN.="
\n"; +$MAIN.=""._QXZ("$report_name")." $NWB#inbound_forecasting$NWE\n"; + +#$MAIN.="\n"; +$MAIN.="\n"; + +$MAIN.="\n"; + +$MAIN.="\n"; +# $MAIN.="\n"; +$MAIN.="
"._QXZ("Dates").":
"; +$MAIN.="\n"; + + +$MAIN.=""; + +$MAIN.="\n"; + +$MAIN.="
"._QXZ("to")."
"; + +$MAIN.="

"; +$MAIN.=""._QXZ("Target drop rate").":
% (optional)"; +# $MAIN.=""._QXZ("Target queue prob.").":% (C report)"; +$MAIN.="
"._QXZ("Campaigns").":
"; +$MAIN.="\n"; +$MAIN.="
"._QXZ("In-groups").":
\n"; +$MAIN.="
"._QXZ("Cost analysis stats (optional)").":
"; +# $MAIN.=_QXZ("Actual agents").":

"; +# $MAIN.=_QXZ("Hourly pay per agent").":
\$
"; +# $MAIN.=_QXZ("Revenue per sale").":
\$
"; +# $MAIN.=_QXZ("Chance of sale").":
%
"; +# $MAIN.=_QXZ("Retry rate").":
% (B "._QXZ("reports only").")"; +# $MAIN.="
"; +$MAIN.=""; +$MAIN.=""; + +# $MAIN.=""._QXZ("Erlang type").":
"; +# $MAIN.="B - "._QXZ("inbound/call loss stats")."
"; +# $MAIN.="C - "._QXZ("outbound/waiting time stats")."

"; + +# $MAIN.="  "; + + +if ($IDR_calltime_available==1) + { + $MAIN.="\n"; + } + +$MAIN.="


"._QXZ("Advanced Forecasting Report")."

"._QXZ("DOWNLOAD")." | "._QXZ("REPORTS")."
\n"; +# $MAIN.=""; +$MAIN.="
";
+
+if ($groups_selected==0 && $campaigns_selected==0)
+	{
+	$MAIN.="\n\n";
+	$MAIN.=_QXZ("PLEASE SELECT AN IN-GROUP AND DATE RANGE ABOVE AND CLICK SUBMIT")."\n";
+	echo "$HEADER";
+	require("admin_header.php");
+	echo "$MAIN";
+	}
+else
+	{
+	$campaign_group_stmt="select closer_campaigns from vicidial_campaigns where campaign_id in ($campaign_SQL)";
+	if ($DB) {echo "|$campaign_group_stmt|\n";}
+	$campaign_group_rslt=mysql_to_mysqli($campaign_group_stmt, $link);
+	$campaign_group_SQL="";
+	while ($cg_row=mysqli_fetch_row($campaign_group_rslt)) {
+		if (strlen(trim($cg_row[0]))>0) {
+			$cg_row[0]=preg_replace("/^\s+|\s\-/", "", $cg_row[0]);
+			$campaign_group_SQL.="'".preg_replace("/\s/", "','", $cg_row[0])."',";
+		}		
+	}
+	$campaign_group_SQL=$group_SQL.",".$campaign_group_SQL;
+	$campaign_group_SQL=preg_replace("/^,|,$/", "", $campaign_group_SQL);
+
+	$campaign_string=preg_replace("/^\||\|$/", "", $campaign_string);
+	$group_string=preg_replace("/^\||\|$/", "", $group_string);
+	$ASCII_text =" Date range :  $query_date to $end_date\n";
+	$ASCII_text.=" Campaigns  :  ".preg_replace("/\|/", ", ", $campaign_string)."\n";
+	$ASCII_text.=" In-groups  :  ".preg_replace("/\|/", ", ", $group_string)."\n\n";
+# 	$ASCII_text.=" Report type:  $erlang_type\n\n";
+
+	$HTML_text.=" Date range :  $query_date to $end_date\n";
+	$HTML_text.=" Campaigns  :  ".preg_replace("/\|/", ", ", $campaign_string)."\n";
+	$HTML_text.=" In-groups  :  ".preg_replace("/\|/", ", ", $group_string)."";
+# 	$HTML_text.=" Report type:  $erlang_type\n\n";
+	
+	$sale_stmt="select distinct status from vicidial_campaign_statuses where campaign_id in ($campaign_SQL) and sale='Y' UNION select status from vicidial_statuses where sale='Y'";
+	if ($DB) {echo "|$sale_stmt|\n";}
+	$sale_rslt=mysql_to_mysqli($sale_stmt, $link);
+	$sales_array=array();
+	while ($sale_row=mysqli_fetch_row($sale_rslt)) {
+		array_push($sales_array, "$sale_row[0]");
+	}
+
+	if ($erlang_type=="B") {
+		$hour_stmt="select closecallid, substr(call_date, 1, 13) as start_hour, length_in_sec, substr(call_date+INTERVAL length_in_sec second, 1, 13) as end_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'))-UNIX_TIMESTAMP(call_date), length_in_sec) as length_up_to_next_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(call_date+INTERVAL length_in_sec second)-UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00')), 0) as length_running_into_next_hour, status, uniqueid from vicidial_closer_log where length_in_sec is not null and campaign_id in ($campaign_group_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59' and status!='AFTHRS'"; # *
+
+		$avg_stmt="select avg(length_in_sec) as avg_length from vicidial_closer_log where length_in_sec is not null and campaign_id in ($campaign_group_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # **
+
+		$wrapup_stmt="select uniqueid from vicidial_closer_log where length_in_sec is not null and user!='VDCL' and campaign_id in ($campaign_group_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # ***
+	} else {
+		$hour_stmt="select uniqueid, substr(call_date, 1, 13) as start_hour, length_in_sec, substr(call_date+INTERVAL length_in_sec second, 1, 13) as end_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'))-UNIX_TIMESTAMP(call_date), length_in_sec) as length_up_to_next_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(call_date+INTERVAL length_in_sec second)-UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00')), 0) as length_running_into_next_hour, status, uniqueid from vicidial_log where length_in_sec is not null and campaign_id in ($campaign_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59' and status!='AFTHRS'"; # *
+
+		$avg_stmt="select avg(length_in_sec) as avg_length from vicidial_log where length_in_sec is not null and campaign_id in ($campaign_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # **
+
+		$wrapup_stmt="select uniqueid from vicidial_log where length_in_sec is not null and user!='VDCL' and campaign_id in ($campaign_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # ***
+	}
+	if ($DB) {echo "|$hour_stmt|\n";}
+	if ($DB) {echo "|$avg_stmt|\n";}
+	if ($DB) {echo "|$wrapup_stmt|\n";}
+
+	# $ASCII_text.=$hour_stmt."
\n"; + $hour_rslt=mysql_to_mysqli($hour_stmt, $link); # * + $erlang_calls=mysqli_num_rows($hour_rslt); + + # PROVIDE ACTUAL STATS + $avg_rslt=mysql_to_mysqli($avg_stmt, $link); # ** + $avg_row=mysqli_fetch_array($avg_rslt); + $average_call_length=$avg_row["avg_length"]; + + $wrapup_rslt=mysql_to_mysqli($wrapup_stmt, $link); # *** + $wrapup_calls=mysqli_num_rows($wrapup_rslt); + $uid_ct=0; + $uid_clause=""; + $dispo_secs=0; + $talk_secs=0; + while ($wrapup_row=mysqli_fetch_row($wrapup_rslt)) { + $uid_ct++; + $uid_clause.="'$wrapup_row[0]',"; + if ($uid_ct%100==0) { + $uid_clause=preg_replace('/,$/', '', $uid_clause); + $uid_stmt="select dispo_sec, talk_sec from vicidial_agent_log where uniqueid in ($uid_clause)"; + $uid_rslt=mysql_to_mysqli($uid_stmt, $link); + while ($uid_row=mysqli_fetch_row($uid_rslt)) { + $dispo_secs+=$uid_row[0]; + $talk_secs+=$uid_row[1]; + } + $uid_clause=""; + } + } + if (strlen($uid_clause)>0) { + $uid_clause=preg_replace('/,$/', '', $uid_clause); + $uid_stmt="select dispo_sec, talk_sec from vicidial_agent_log where uniqueid in ($uid_clause)"; + $uid_rslt=mysql_to_mysqli($uid_stmt, $link); + while ($uid_row=mysqli_fetch_row($uid_rslt)) { + $dispo_secs+=$uid_row[0]; + $talk_secs+=$uid_row[1]; + } + $uid_clause=""; + } + $avg_dispo_sec=$dispo_secs/$wrapup_calls; + $avg_talk_sec=$talk_secs/$wrapup_calls; + ##### + + + $wrapup_stmt="select average(dispo_sec) from vicidial_agent_log"; + + $erlang_array=array(); + $drops_blocks=0; + $sales=0; + while ($hour_row=mysqli_fetch_array($hour_rslt)) { + $erlang_array["$hour_row[start_hour]"][0]+=$hour_row["length_up_to_next_hour"]; + $erlang_array["$hour_row[start_hour]"][2]++; + + if ($hour_row["length_running_into_next_hour"]>0) { + $erlang_array["$hour_row[end_hour]"][0]+=$hour_row["length_running_into_next_hour"]; + $erlang_array["$hour_row[end_hour]"][2]++; + if ($hour_row["status"]=="DROP") { + $erlang_array["$hour_row[end_hour]"][3]++; + } + } + + if ($hour_row["status"]=="DROP") { + $erlang_array["$hour_row[start_hour]"][1]+=$hour_row["length_up_to_next_hour"]; + $erlang_array["$hour_row[end_hour]"][1]+=$hour_row["length_running_into_next_hour"]; + $erlang_array["$hour_row[start_hour]"][3]++; + $drops_blocks++; + } + + if (in_array("$hour_row[status]", $sales_array)) { + $erlang_array["$hour_row[start_hour]"][4]++; + $sales++; + } + } + $hours_active=count($erlang_array); # Used for giving total erlangs for day, need to divide by number of hours reported, not one hour + $total_erlangs=($erlang_calls*$average_call_length/(3600*$hours_active)); + $total_blocking=($drops_blocks/$erlang_calls); + $sale_percent=($sales/$erlang_calls); + + $rpt_header ="+-----------------+-------+-------+------------+----------+-------------+----------+---------+"; + if ($erlang_type=="B") {$rpt_header.="---------+";} + if ($erlang_type=="C") {$rpt_header.="------------+------------+";} + $rpt_header.="------------+------------+------------+----------+-----------+------------+------------+------------+\n"; + + $ASCII_text.=$rpt_header; + # $ASCII_text.=$hour_stmt."
\n"; + + # Damn fixed-space formatting, hate ASCII. HATE. + if ($erlang_type=="B") { + if ($actual_agents>0) { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Actual agents: ")).sprintf("%-131s", "$actual_agents")." |\n"; + } + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total calls: ")).sprintf("%-131s", "$erlang_calls")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total drops: ")).sprintf("%-131s", "$drops_blocks")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired drop rate: ")).sprintf("%-5.2f", "$drop_percent").sprintf("%-126s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total blocking/drop rate: ")).sprintf("%-5.2f", (100*$total_blocking)).sprintf("%-126s", " %")." |\n"; # sprintf("%-131.4f", "$total_blocking") + # $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired sale rate: ")).sprintf("%-5.2f", "$sale_chance").sprintf("%-126s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Sale rate: ")).sprintf("%-5.2f", (100*$sale_percent)).sprintf("%-126s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Average call duration: ")).sprintf("%-131.2f", "$average_call_length")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Erlangs: ")).sprintf("%-131.4f", $total_erlangs)." |\n"; + } + if ($erlang_type=="C") { + if ($actual_agents>0) { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Actual agents: ")).sprintf("%-147s", "$actual_agents")." |\n"; + } + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total calls: ")).sprintf("%-147s", "$erlang_calls")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total drops: ")).sprintf("%-147s", "$drops_blocks")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired drop rate: ")).sprintf("%-5.2f", "$drop_percent").sprintf("%-142s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total blocking/drop rate: ")).sprintf("%-5.2f", (100*$total_blocking)).sprintf("%-142s", " %")." |\n"; # sprintf("%-147.4f", "$total_blocking") + # $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired sale rate: ")).sprintf("%-5.2f", "$sale_chance").sprintf("%-142s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Sale rate: ")).sprintf("%-5.2f", (100*$sale_percent)).sprintf("%-142s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Average call duration: ")).sprintf("%-147.2f", "$average_call_length")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Erlangs: ")).sprintf("%-147.4f", $total_erlangs)." |\n"; + } + + $HTML_text.=""; + $HTML_text.=""; # B +# $HTML_text.=""; # B + } + if ($erlang_type=="C") { + $HTML_text.=""; # C + $HTML_text.=""; # C + } +# $HTML_text.=""; + ############# + + ##### RECOMMENDED AGENTS + $lines=1; + if ($erlang_type=="B") { + $GoS=(pow($total_erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $total_erlangs)); + if ($GoS>$drop_rate) { + $ASCII_text.=""; + } + } + if ($erlang_type=="C") { + $Pqueue=(pow($total_erlangs, $lines)/(factorial($lines)))/((pow($total_erlangs, $lines)/(factorial($lines)))+((1-($total_erlangs/$lines))*erlsum(0, ($lines-1), $total_erlangs))); + if ($Pqueue>$pqueue_target) { + $ASCII_text.=""; + } + } + + if ($erlang_type=="B") { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Recommended agent count: ")).sprintf("%-131s", $lines)." |\n"; + } else { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Recommended agent count: ")).sprintf("%-147s", $lines)." |\n"; + } + $CSV_text.="\"Recommended agent count:\",\"$lines\"\n"; + $CSV_text.="\n"; + ############# + + $ASCII_text.=$rpt_header; + $ASCII_text.= "| "._QXZ("CALLING HOUR", 15)." | "._QXZ("CALLS", 5)." | "._QXZ("SALES", 5)." | "._QXZ("TOTAL TIME", 10)." | "._QXZ("AVG TIME", 8)." | "._QXZ("DROPPED HRS", 11)." | "._QXZ("BLOCKING", 8)." | "._QXZ("ERLANGS", 7); + if ($erlang_type=="B") {$ASCII_text.=" | "._QXZ("GOS", 7);} # B + if ($erlang_type=="C") {$ASCII_text.=" | "._QXZ("QUEUE PROB", 10)." | "._QXZ("AVG ANSWER", 10);} # C + $ASCII_text.=" | "._QXZ("REC AGENTS", 10)." | "._QXZ("EST AGENTS", 10)." | "._QXZ("CALLS/AGNT", 10)." |\n"; # ." | "._QXZ("REV/CALL", 8)." | "._QXZ("REV/AGENT", 9)." | "._QXZ("TOTAL REV", 10)." | "._QXZ("TOTAL COST", 10)." | "._QXZ("MARGIN", 10) + $ASCII_text.=$rpt_header; + $CSV_text.="\""._QXZ("CALLING HOUR")."\",\""._QXZ("CALLS")."\",\""._QXZ("SALES")."\",\""._QXZ("TOTAL TIME")."\",\""._QXZ("AVG TIME")."\",\""._QXZ("DROPPED HRS")."\",\""._QXZ("BLOCKING")."\",\""._QXZ("ERLANGS")."\","; + if ($erlang_type=="B") {$CSV_text.="\""._QXZ("GRADE OF SERVICE")."\",";} # B + if ($erlang_type=="C") {$CSV_text.="\""._QXZ("QUEUE PROBABILITY")."\",\""._QXZ("AVERAGE ANSWER SPEED")."\",";} # C + $CSV_text.="\""._QXZ("REC AGENTS")."\",\""._QXZ("EST AGENTS")."\",\""._QXZ("CALLS/AGNT")."\"\n"; # ,\""._QXZ("REV/CALL")."\",\""._QXZ("REV/AGENT")."\",\""._QXZ("TOTAL REV")."\",\""._QXZ("TOTAL COST")."\",\""._QXZ("MARGIN")."\" + ksort($erlang_array); + + $HTML_text2=""; + $HTML_text2.="
"; + + $CSV_text=""; + if ($actual_agents>0) { + $CSV_text.="\"Actual agents:\",\"$actual_agents\"\n"; + } + $CSV_text.="\"Total calls:\",\"$erlang_calls\"\n"; + $CSV_text.="\"Total drops:\",\"$drops_blocks\"\n"; + $CSV_text.="\"Desired drop rate:\",\"".sprintf("%5.2f", "$drop_percent")." %\"\n"; + $CSV_text.="\"Total blocking/drop rate:\",\"".sprintf("%-5.2f", (100*$total_blocking))."\"\n"; + # $CSV_text.="\"Desired sale rate:\",\"".sprintf("%5.2f", "$sale_chance")." %\"\n"; + $CSV_text.="\"Sale rate:\",\"".sprintf("%-5.2f", (100*$sale_percent))."\"\n"; + $CSV_text.="\"Average call duration:\",\"".sprintf("%.2f", "$average_call_length")." seconds\"\n"; + $CSV_text.="\"Erlangs:\",\"".sprintf("%.4f", "$total_erlangs")."\"\n"; + + + # ESTIMATED AGENTS + $lines=1; + if ($total_blocking>0) { + $GoS=(pow($total_erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $total_erlangs)); + if ($GoS>$total_blocking) { + $ASCII_text.=""; + } + $Pqueue=(pow($total_erlangs, $lines)/(factorial($lines)))/((pow($total_erlangs, $lines)/(factorial($lines)))+((1-($total_erlangs/$lines))*erlsum(0, ($lines-1), $total_erlangs))); + $ASA=($Pqueue*$average_call_length)/($lines-$total_erlangs); + } else { + $lines="N/A"; + $Pqueue=0; + $ASA=0; + } + if ($Pqueue>1) {$Pqueue=1;} + $est_GoS=$GoS; # Need this here since we moved the output line further down & need to save it. + $est_lines=$lines; # Need this here since we moved the output line further down & need to save it. + + if ($erlang_type=="B") { +# $ASCII_text.="| ".sprintf("%70s", _QXZ("Retry rate: ")).sprintf("%-131s", "$retry_rate %")." |\n"; # B + $ASCII_text.="| ".sprintf("%70s", _QXZ("Grade of service: ")).sprintf("%-131s", sprintf("%0.2f", (100*$GoS)." %"))." |\n"; # B + $ASCII_text.="| ".sprintf("%70s", _QXZ("Estimated agents fielding calls: ")).sprintf("%-131s", $lines)." |\n"; + } + if ($erlang_type=="C") { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Estimated queue probability: ")).sprintf("%-5.2f", (100*$Pqueue)).sprintf("%-142s", " %")." |\n"; # C + $ASCII_text.="| ".sprintf("%70s", _QXZ("Average speed of answering: ")).sprintf("%-147s", sec_convert($ASA,'H'))." |\n"; # C + $ASCII_text.="| ".sprintf("%70s", _QXZ("Estimated agents fielding calls: ")).sprintf("%-147s", $lines)." |\n"; + } + + if ($erlang_type=="B") { +# $CSV_text.="\""._QXZ("Retry rate: ")."\",\"$retry_rate %\"\n"; # B + $CSV_text.="\""._QXZ("Grade of service: ")."\",\"".sprintf("%0.2f", (100*$GoS))." %\"\n"; # B + } + if ($erlang_type=="C") { + $CSV_text.="\""._QXZ("Estimated queue probability: ")."\",\"".sprintf("%.2f", (100*$Pqueue))."%\"\n"; # C + $CSV_text.="\""._QXZ("Average speed of answering: ")."\",\"".sec_convert($ASA,'H')."\"\n"; # C + } + $CSV_text.="\""._QXZ("Estimated agents fielding calls: ")."\",\"$lines\"\n"; + + if ($erlang_type=="B") { +## $HTML_text.="
"._QXZ("Retry rate: ")."$retry_rate %
"._QXZ("Grade of service: ")."".sprintf("%0.2f", (100*$GoS))."%
"._QXZ("Estimated queue probability: ")."".sprintf("%.2f", (100*$Pqueue))."%
"._QXZ("Average speed of answering: ")."".sec_convert($ASA,'H')."
"._QXZ("Estimated agents fielding calls: ")."".$lines."
"; + $HTML_text2.="
"; + $HTML_text2.=""; + if ($actual_agents>0) { + $HTML_text2.=""; + } + $HTML_text2.=""; + $HTML_text2.=""; + $HTML_text2.=""; + $HTML_text2.=""; + # $HTML_text2.=""; + $HTML_text2.=""; + $HTML_text2.=""; + $HTML_text2.=""; + $HTML_text2.=""; # B + $HTML_text2.=""; + $HTML_text2.=""; + $HTML_text2.="
"._QXZ("INBOUND SUMMARY")."
"._QXZ("Actual agents: ")."".$actual_agents."
"._QXZ("Total calls: ")."".$erlang_calls."
"._QXZ("Total drops: ")."".$drops_blocks."
"._QXZ("Desired drop rate: ")."".sprintf("%5.2f", "$drop_percent")." %
"._QXZ("Total blocking/drop rate: ")."".sprintf("%-5.2f", (100*$total_blocking))." %
"._QXZ("Desired sale rate: ")."".sprintf("%5.2f", "$sale_chance")." %
"._QXZ("Sale rate: ")."".sprintf("%-5.2f", (100*$sale_percent))." %
"._QXZ("Average call duration: ")."".sprintf("%18.2f", "$average_call_length")."
"._QXZ("Erlangs: ")."".sprintf("%18.4f", $total_erlangs)."
"._QXZ("Grade of service: ")."".sprintf("%0.2f", (100*$est_GoS))."%
"._QXZ("Estimated agents fielding calls: ")."".$est_lines."
"._QXZ("Recommended agent count: ")."".$lines."
"; + $HTML_text2.="
"; # For closing the table above that encompasses first report table and chart + + $HTML_text2.=""; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + + if ($erlang_type=="B") { + $HTML_text2.="\n"; # B + } + if ($erlang_type=="C") { + $HTML_text2.="\n"; # C + $HTML_text2.="\n"; # C + } + + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + # $HTML_text2.="\n"; + # $HTML_text2.="\n"; + # $HTML_text2.="\n"; + # $HTML_text2.="\n"; + # $HTML_text2.="\n"; + $HTML_text2.="\n"; + + + $bht=0; + $graph_stats=array(); + $q=0; + while(list($key, $val)=each($erlang_array)) { + if ($val[0]>$bht) {$bht=$val[0];} + if ($q%2==0) {$tdclass="records_list_x";} else {$tdclass="records_list_y";} + $average_time=round($val[0]/$val[2]); + $blocking=($val[3]/$val[2]); + $erlangs=($val[2]*$average_time/3600); # Row is call per hour, therefore call length average must be in hours. + $sales=$val[4]+0; + + $ASCII_text.="| "; #.substr($key, 0, -2)." - ".substr($key, 5, 2)." ".substr($key, 8, 2)." ".substr($key, 0, 4); + $ASCII_text.=date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4))); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%5s", $val[2]); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%5s", $sales); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%10s", sec_convert($val[0],'H')); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%8s", sec_convert($average_time,'H')); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%11s", sec_convert($val[1],'H')); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%8s", sprintf("%01.4f", $blocking)); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%7s", sprintf("%01.4f", $erlangs)); + $ASCII_text.=" | "; + + $CSV_text.="\"".date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4)))."\",\"".$val[2]."\",\"".$sales."\",\"".sec_convert($val[0],'H')."\",\"".sec_convert($average_time,'H')."\",\"".sec_convert($val[1],'H')."\",\"".sprintf("%01.4f", $blocking)."\",\"".sprintf("%01.4f", $erlangs)."\","; + + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + + $graph_key=date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4))); + $graph_stats["$graph_key"][0]=$val[2]; + $graph_stats["$graph_key"][1]=$val[0]; + $graph_stats["$graph_key"][2]=$average_time; + $graph_stats["$graph_key"][3]=$val[1]; + $graph_stats["$graph_key"][4]=sprintf("%01.4f", $blocking); + $graph_stats["$graph_key"][5]=sprintf("%01.4f", $erlangs); + + ##### RECOMMENDED AGENTS + $lines=1; + if ($erlang_type=="B") { + $GoS=(pow($erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $erlangs)); + if ($GoS>$drop_rate) { + $ASCII_text.=""; + } + } + if ($erlang_type=="C") { + $Pqueue=(pow($erlangs, $lines)/(factorial($lines)))/((pow($erlangs, $lines)/(factorial($lines)))+((1-($erlangs/$lines))*erlsum(0, ($lines-1), $erlangs))); + if ($Pqueue>$pqueue_target) { + $ASCII_text.=""; + } + } + $recommended_agents=$lines; + + ##### ESTIMATED AGENTS + $lines=1; + if ($blocking>0) { + $GoS=(pow($erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $erlangs)); + if ($GoS>$blocking) { + $ASCII_text.=""; + } + + $Pqueue=(pow($erlangs, $lines)/(factorial($lines)))/((pow($erlangs, $lines)/(factorial($lines)))+((1-($erlangs/$lines))*erlsum(0, ($lines-1), $erlangs))); + $ASA=($Pqueue*$average_time)/($lines-$erlangs); + } else { + $lines="$recommended_agents"; + $Pqueue=0; + $ASA=0; + } + if ($actual_agents>0) { + $lines=$actual_agents; + $Pqueue=0; + $ASA=0; + } + if ($Pqueue>1) {$Pqueue=1;} + + if ($erlang_type=="B") { + $ASCII_text.=sprintf("%7s", sprintf("%0.2f", (100*$GoS))."%"); + $ASCII_text.=" | "; + } + if ($erlang_type=="C") { + $ASCII_text.=sprintf("%10s", sprintf("%.4f", (100*$Pqueue))."%"); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%10s", sec_convert($ASA,'H')); + $ASCII_text.=" | "; + } + $ASCII_text.=sprintf("%10s", $recommended_agents); + $ASCII_text.=" | "; + if ($erlang_type=="B") { + $CSV_text.="\"".sprintf("%0.2f", (100*$GoS))."%\","; # B + } + if ($erlang_type=="C") { + $CSV_text.="\"".sprintf("%.6f", (100*$Pqueue))."%\","; # C + $CSV_text.="\"".sec_convert($ASA,'H')."\","; # C + } + $CSV_text.="\"$recommended_agents\","; + $graph_stats["$graph_key"][7]=$recommended_agents; + if ($erlang_type=="B") { + $HTML_text2.="\n"; # B + } + if ($erlang_type=="C") { + $HTML_text2.="\n"; # C + $HTML_text2.="\n"; # C + } + $HTML_text2.="\n"; + + $ASCII_text.=sprintf("%10s", $lines); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%-10.2f", ($val[2]/$lines)); +# $ASCII_text.=" | "; +# $ASCII_text.=sprintf("%-8s", "\$".number_format(($revenue_per_sale*$sales/$val[2]),2,".",",")); +# $ASCII_text.=" | "; +# $ASCII_text.=sprintf("%-9s", "\$".number_format(($revenue_per_sale*$sales/$lines),2,".",",")); +# $ASCII_text.=" | "; +# $ASCII_text.=sprintf("%-10s", "\$".number_format(($revenue_per_sale*$sales),2,".",",")); +# $ASCII_text.=" | "; +# $ASCII_text.=sprintf("%-10s", "\$".number_format(($lines*$hourly_pay),2,".",",")); +# $ASCII_text.=" | "; +# $ASCII_text.=sprintf("%-10s", "\$".number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",",")); + $ASCII_text.=" |\n"; + + $graph_stats["$graph_key"][8]=$drop_rate; + + + $CSV_text.="\"$lines\","; + $CSV_text.="\"".sprintf("%.2f", ($val[2]/$lines))."\","; +# $CSV_text.="\"$".number_format(($revenue_per_sale*$sales/$val[2]),2,".",",")."\","; +# $CSV_text.="\"$".number_format(($revenue_per_sale*$sales/$lines),2,".",",")."\","; +# $CSV_text.="\"$".number_format(($revenue_per_sale*$sales),2,".",",")."\","; +# $CSV_text.="\"$".number_format(($lines*$hourly_pay),2,".",",")."\","; +# $CSV_text.="\"$".number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",",")."\"\n"; + + $graph_stats["$graph_key"][6]=$lines; + $graph_stats["$graph_key"][8]=$drop_rate; + $graph_stats["$graph_key"][9]=$sales; + $graph_stats["$graph_key"][10]=number_format(($revenue_per_sale*$sales/$val[2]),2,".",""); # Revenue per call + $graph_stats["$graph_key"][11]=number_format(($revenue_per_sale*$sales/$lines),2,".",""); # Revenue per agent + $graph_stats["$graph_key"][12]=number_format(($revenue_per_sale*$sales),2,".",""); # Total revenue + $graph_stats["$graph_key"][13]=number_format(($lines*$hourly_pay),2,".",""); # Cost + $graph_stats["$graph_key"][14]=number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",","); + $graph_stats["$graph_key"][15]=$GoS; + $graph_stats["$graph_key"][16]=$Pqueue; # Cost + $graph_stats["$graph_key"][17]=$ASA; # Cost + + $HTML_text2.="\n"; + $HTML_text2.="\n"; +# $HTML_text2.="\n"; +# $HTML_text2.="\n"; +# $HTML_text2.="\n"; +# $HTML_text2.="\n"; +# $HTML_text2.="\n"; + $HTML_text2.="\n"; + $q++; + } + $ASCII_text.=$rpt_header; + $ASCII_text.=" BHT: ".sec_convert($bht,'H')." ($bht seconds)\n"; + + $HTML_text2.="
"._QXZ("CALLING HOUR").""._QXZ("CALLS").""._QXZ("SALES").""._QXZ("TOTAL TIME").""._QXZ("AVG TIME").""._QXZ("DROPPED HRS").""._QXZ("BLOCKING").""._QXZ("ERLANGS").""._QXZ("GRADE OF SERVICE").""._QXZ("QUEUE PROB").""._QXZ("AVG ANSWER").""._QXZ("REC AGENTS").""._QXZ("EST AGENTS").""._QXZ("CALLS PER AGENT").""._QXZ("REVENUE PER CALL").""._QXZ("REVENUE PER AGENT").""._QXZ("TOTAL REVENUE").""._QXZ("TOTAL COST").""._QXZ("MARGIN")."
".date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4)))."".$val[2]."".$sales."".sec_convert($val[0],'H')."".sec_convert($average_time,'H')."".sec_convert($val[1],'H')."".sprintf("%01.4f", $blocking)."".sprintf("%01.4f", $erlangs)."".sprintf("%0.2f", (100*$GoS))."%".sprintf("%.4f", (100*$Pqueue))."%".sec_convert($ASA,'H')." $recommended_agents$lines".sprintf("%.2f", ($val[2]/$lines))."\$".number_format(($revenue_per_sale*$sales/$val[2]),2,".",",")."\$".number_format(($revenue_per_sale*$sales/$lines),2,".",",")."\$".number_format(($revenue_per_sale*$sales),2,".",",")."\$".number_format(($lines*$hourly_pay),2,".",",")."\$".number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",",")."
"; + + # USE THIS FOR COMBINED graphs, use pipe-delimited array elements, dataset_name|index|link_name|graph_override + # You have to hard code the graph name in where it is overridden and mind the data indices. No other way to do it. + $multigraph_text=""; + $graph_id++; + $graph_array=array("ERL_AGENTSdata|7,6|AGENTS|integer|Rec. Agents,Est. Agents", "ERL_BLOCKdata|4,8|BLOCKING/DROPS|percent|Blocking,Desired drop rate", "ERL_CALLSdata|0,9|CALLS|integer|Calls,Sales", "ERL_TIMEdata|2,3,1|TIMES|time|Average time,Dropped time,Total time", "ERL_ERLANGSdata|5|ERLANGS|integer|Erlangs"); # , "ERL_REVENUEdata|10,11|REVENUE|dollar|Revenue per call,Revenue per agent", "ERL_REVENUEdata|12,13|MARGINS|dollar|Total revenue,Total cost" + if ($erlang_type=="B") { + array_push($graph_array, "ERL_GOSdata|15|GoS|integer|Grade of Service"); + } + if ($erlang_type=="C") { + array_push($graph_array, "ERL_PQUEUEdata|16|QUEUE|percent|Call queue probability"); + } + + + $default_graph="line"; # Graph that is initally displayed when page loads + include("graph_color_schemas.inc"); + + + # CUSTOMIZING COLORS FOR LINE GRAPHS + $graph_colors=array("216,0,0", "0,0,216", "0,216,0", "216,216,0", "216,0,216", "0,216,216"); + + + $graph_totals_array=array(); + $graph_totals_rawdata=array(); + for ($q=0; $q0) + { + $FILE_TIME = date("Ymd-His"); + $CSVfilename = "AST_Erlang_report_$US$FILE_TIME.csv"; + $CSV_text=preg_replace('/\n +,/', ',', $CSV_text); + $CSV_text=preg_replace('/ +\"/', '"', $CSV_text); + $CSV_text=preg_replace('/\" +/', '"', $CSV_text); + + // We'll be outputting a TXT file + header('Content-type: application/octet-stream'); + // It will be called LIST_101_20090209-121212.txt + header("Content-Disposition: attachment; filename=\"$CSVfilename\""); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Pragma: public'); + ob_clean(); + flush(); + + echo "$CSV_text"; + } +else + { + header("Content-type: text/html; charset=utf-8"); + + echo "$HEADER"; + require("admin_header.php"); + echo "$MAIN"; + flush(); + } +# echo $ASCII_text; + } +?> \ No newline at end of file diff --git a/agc_2-X/trunk/www/vicidial/Erlang_report.php b/agc_2-X/trunk/www/vicidial/Erlang_report.php new file mode 100644 index 00000000..4dd4f623 --- /dev/null +++ b/agc_2-X/trunk/www/vicidial/Erlang_report.php @@ -0,0 +1,1357 @@ +, Joe Johnson LICENSE: AGPLv2 +# +# CHANGES +# +# 170428-1205 - First build +# + +$startMS = microtime(); + +require("dbconnect_mysqli.php"); +require("functions.php"); + + function factorial($num) { + $num=floor($num); + if ($num>0) { + $result=1; + for ($x=1; $x<=$num; $x++) { + $result*=$x; + } + return $result; + } else { + return 1; + } + } + function erlsum($low, $limit, $erlangs) { + $result=0; + for ($n=$low; $n<=$limit; $n++) { + $result+=pow($erlangs, $n)/(factorial($n)); + } + return $result; + } + function adjustedGoS($erlangs, $GoS, $retry_rate, $lines) { + $E[0]=$erlangs; + $P[0]=$GoS; + + for ($q=0; $q<100; $q++) { + $E[($q+1)]=$erlangs+($retry_rate/100)*$E[$q]*$P[$q]; + $P[($q+1)]=(pow($E[($q+1)], $lines)/(factorial($lines)))/(erlsum(0, $lines, $E[($q+1)])); + + } + return $P[100]; + } + +if (file_exists('options.php')) + { + require('options.php'); + } + +$PHP_AUTH_USER=$_SERVER['PHP_AUTH_USER']; +$PHP_AUTH_PW=$_SERVER['PHP_AUTH_PW']; +$PHP_SELF=$_SERVER['PHP_SELF']; +if (isset($_GET["group"])) {$group=$_GET["group"];} + elseif (isset($_POST["group"])) {$group=$_POST["group"];} +if (isset($_GET["campaign"])) {$campaign=$_GET["campaign"];} + elseif (isset($_POST["campaign"])) {$campaign=$_POST["campaign"];} +if (isset($_GET["query_date"])) {$query_date=$_GET["query_date"];} + elseif (isset($_POST["query_date"])) {$query_date=$_POST["query_date"];} +if (isset($_GET["end_date"])) {$end_date=$_GET["end_date"];} + elseif (isset($_POST["end_date"])) {$end_date=$_POST["end_date"];} +if (isset($_GET["drop_percent"])) {$drop_percent=$_GET["drop_percent"];} + elseif (isset($_POST["drop_percent"])) {$drop_percent=$_POST["drop_percent"];} +if (isset($_GET["shift"])) {$shift=$_GET["shift"];} + elseif (isset($_POST["shift"])) {$shift=$_POST["shift"];} +if (isset($_GET["erlang_type"])) {$erlang_type=$_GET["erlang_type"];} + elseif (isset($_POST["erlang_type"])) {$erlang_type=$_POST["erlang_type"];} +if (isset($_GET["actual_agents"])) {$actual_agents=$_GET["actual_agents"];} + elseif (isset($_POST["actual_agents"])) {$actual_agents=$_POST["actual_agents"];} +if (isset($_GET["hourly_pay"])) {$hourly_pay=$_GET["hourly_pay"];} + elseif (isset($_POST["hourly_pay"])) {$hourly_pay=$_POST["hourly_pay"];} +if (isset($_GET["revenue_per_sale"])) {$revenue_per_sale=$_GET["revenue_per_sale"];} + elseif (isset($_POST["revenue_per_sale"])) {$revenue_per_sale=$_POST["revenue_per_sale"];} +if (isset($_GET["sale_chance"])) {$sale_chance=$_GET["sale_chance"];} + elseif (isset($_POST["sale_chance"])) {$sale_chance=$_POST["sale_chance"];} +if (isset($_GET["retry_rate"])) {$retry_rate=$_GET["retry_rate"];} + elseif (isset($_POST["retry_rate"])) {$retry_rate=$_POST["retry_rate"];} +if (isset($_GET["target_pqueue"])) {$target_pqueue=$_GET["target_pqueue"];} + elseif (isset($_POST["target_pqueue"])) {$target_pqueue=$_POST["target_pqueue"];} +if (isset($_GET["file_download"])) {$file_download=$_GET["file_download"];} + elseif (isset($_POST["file_download"])) {$file_download=$_POST["file_download"];} +if (isset($_GET["submit"])) {$submit=$_GET["submit"];} + elseif (isset($_POST["submit"])) {$submit=$_POST["submit"];} +if (isset($_GET["SUBMIT"])) {$SUBMIT=$_GET["SUBMIT"];} + elseif (isset($_POST["SUBMIT"])) {$SUBMIT=$_POST["SUBMIT"];} +if (isset($_GET["DB"])) {$DB=$_GET["DB"];} + elseif (isset($_POST["DB"])) {$DB=$_POST["DB"];} +if (isset($_GET["report_display_type"])) {$report_display_type=$_GET["report_display_type"];} + elseif (isset($_POST["report_display_type"])) {$report_display_type=$_POST["report_display_type"];} + +if (strlen($shift)<2) {$shift='ALL';} + +$report_name = 'Advanced Forecasting Report'; +$db_source = 'M'; + +if ($ignore_afterhours=="checked") {$status_clause=" and status!='AFTHRS'";} + +$HTML_text=""; +$actual_agents=preg_replace("/[^0-9.]/", "", $actual_agents); +$actual_agents+=0; +$hourly_pay=preg_replace("/[^0-9.]/", "", $hourly_pay); +$hourly_pay+=0; +$revenue_per_sale=preg_replace("/[^0-9.]/", "", $revenue_per_sale); +$revenue_per_sale+=0; +$sale_chance=preg_replace("/[^0-9.]/", "", $sale_chance); +$sale_chance+=0; +$retry_rate=preg_replace("/[^0-9.]/", "", $retry_rate); +$retry_rate+=0; + +switch ($erlang_type) { + default: + case "B": + $erlB="checked"; + $erlC=""; + break; + case "C": + $erlB=""; + $erlC="checked"; + break; +} + +$JS_text="\n"; +$HEADER.="\n"; +$HEADER.="\n"; +# $HEADER.="\n"; +$HEADER.="\n"; +$HEADER.="\n"; +$HEADER.="\n"; +$HEADER.=""._QXZ("$report_name")."\n"; + +$short_header=1; + +$MAIN.="\n"; +$MAIN.=""._QXZ("$report_name")." $NWB#erlang_report$NWE\n"; + +#$MAIN.="\n"; +$MAIN.="\n"; + +$MAIN.="\n"; + +$MAIN.="\n"; +$MAIN.="\n"; +$MAIN.="
"._QXZ("Dates").":
"; +$MAIN.="\n"; + + +$MAIN.=""; + +$MAIN.="\n"; + +$MAIN.="
"._QXZ("to")."
"; + +$MAIN.="

"; +$MAIN.=""._QXZ("Target drop rate").":% (B report)
"; +$MAIN.=""._QXZ("Target queue prob.").":% (C report)"; +$MAIN.="
"._QXZ("Campaigns").":
"; +$MAIN.="\n"; +$MAIN.="
"._QXZ("In-groups").":
\n"; +$MAIN.="
"._QXZ("Cost analysis stats (optional)").":
"; +$MAIN.=_QXZ("Actual agents").":

"; +$MAIN.=_QXZ("Hourly pay per agent").":
\$
"; +$MAIN.=_QXZ("Revenue per sale").":
\$
"; +$MAIN.=_QXZ("Chance of sale").":
%
"; +$MAIN.=_QXZ("Retry rate").":
% (B "._QXZ("reports only").")"; +$MAIN.="
"._QXZ("Erlang type").":
"; +$MAIN.="B - "._QXZ("inbound/call loss stats")."
"; +$MAIN.="C - "._QXZ("outbound/waiting time stats")."

"; +$MAIN.="  "; + + +if ($IDR_calltime_available==1) + { + $MAIN.="\n"; + } + +$MAIN.="

"._QXZ("Basic Forecasting Report")."

"._QXZ("DOWNLOAD")." | "._QXZ("MODIFY")." | "._QXZ("REPORTS")."
\n"; +# $MAIN.=""; +$MAIN.="
\n\n";
+
+if ($groups_selected==0 && $campaigns_selected==0)
+	{
+	$MAIN.="\n\n";
+	$MAIN.=_QXZ("PLEASE SELECT AN IN-GROUP AND DATE RANGE ABOVE AND CLICK SUBMIT")."\n";
+	echo "$HEADER";
+	require("admin_header.php");
+	echo "$MAIN";
+	}
+else
+	{
+	$campaign_group_stmt="select closer_campaigns from vicidial_campaigns where campaign_id in ($campaign_SQL)";
+	if ($DB) {echo "|$campaign_group_stmt|\n";}
+	$campaign_group_rslt=mysql_to_mysqli($campaign_group_stmt, $link);
+	$campaign_group_SQL="";
+	while ($cg_row=mysqli_fetch_row($campaign_group_rslt)) {
+		if (strlen(trim($cg_row[0]))>0) {
+			$cg_row[0]=preg_replace("/^\s+|\s\-/", "", $cg_row[0]);
+			$campaign_group_SQL.="'".preg_replace("/\s/", "','", $cg_row[0])."',";
+		}		
+	}
+	$campaign_group_SQL=$group_SQL.",".$campaign_group_SQL;
+	$campaign_group_SQL=preg_replace("/^,|,$/", "", $campaign_group_SQL);
+
+	$campaign_string=preg_replace("/^\||\|$/", "", $campaign_string);
+	$group_string=preg_replace("/^\||\|$/", "", $group_string);
+	$ASCII_text =" Date range :  $query_date to $end_date\n";
+	$ASCII_text.=" Campaigns  :  ".preg_replace("/\|/", ", ", $campaign_string)."\n";
+	$ASCII_text.=" In-groups  :  ".preg_replace("/\|/", ", ", $group_string)."\n";
+	$ASCII_text.=" Report type:  $erlang_type\n\n";
+
+	$HTML_text.=" Date range :  $query_date to $end_date\n";
+	$HTML_text.=" Campaigns  :  ".preg_replace("/\|/", ", ", $campaign_string)."\n";
+	$HTML_text.=" In-groups  :  ".preg_replace("/\|/", ", ", $group_string)."\n";
+	$HTML_text.=" Report type:  $erlang_type\n\n";
+	
+	$sale_stmt="select distinct status from vicidial_campaign_statuses where campaign_id in ($campaign_SQL) and sale='Y' UNION select status from vicidial_statuses where sale='Y'";
+	if ($DB) {echo "|$sale_stmt|\n";}
+	$sale_rslt=mysql_to_mysqli($sale_stmt, $link);
+	$sales_array=array();
+	while ($sale_row=mysqli_fetch_row($sale_rslt)) {
+		array_push($sales_array, "$sale_row[0]");
+	}
+
+	if ($erlang_type=="B") {
+		$hour_stmt="select closecallid, substr(call_date, 1, 13) as start_hour, length_in_sec, substr(call_date+INTERVAL length_in_sec second, 1, 13) as end_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'))-UNIX_TIMESTAMP(call_date), length_in_sec) as length_up_to_next_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(call_date+INTERVAL length_in_sec second)-UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00')), 0) as length_running_into_next_hour, status, uniqueid from vicidial_closer_log where length_in_sec is not null and campaign_id in ($campaign_group_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59' and status!='AFTHRS'"; # *
+
+		$avg_stmt="select avg(length_in_sec) as avg_length from vicidial_closer_log where length_in_sec is not null and campaign_id in ($campaign_group_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # **
+
+		$wrapup_stmt="select uniqueid from vicidial_closer_log where length_in_sec is not null and user!='VDCL' and campaign_id in ($campaign_group_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # ***
+	} else {
+		$hour_stmt="select uniqueid, substr(call_date, 1, 13) as start_hour, length_in_sec, substr(call_date+INTERVAL length_in_sec second, 1, 13) as end_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'))-UNIX_TIMESTAMP(call_date), length_in_sec) as length_up_to_next_hour, if(DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00')!=DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00'), UNIX_TIMESTAMP(call_date+INTERVAL length_in_sec second)-UNIX_TIMESTAMP(DATE_FORMAT(call_date+INTERVAL length_in_sec second, '%Y-%m-%d %H:00:00')), 0) as length_running_into_next_hour, status, uniqueid from vicidial_log where length_in_sec is not null and campaign_id in ($campaign_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59' and status!='AFTHRS'"; # *
+
+		$avg_stmt="select avg(length_in_sec) as avg_length from vicidial_log where length_in_sec is not null and campaign_id in ($campaign_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # **
+
+		$wrapup_stmt="select uniqueid from vicidial_log where length_in_sec is not null and user!='VDCL' and campaign_id in ($campaign_SQL) and call_date>='$query_date 00:00:00' and call_date<='$end_date 23:59:59'"; # ***
+	}
+	if ($DB) {echo "|$hour_stmt|\n";}
+	if ($DB) {echo "|$avg_stmt|\n";}
+	if ($DB) {echo "|$wrapup_stmt|\n";}
+
+	# $ASCII_text.=$hour_stmt."
\n"; + $hour_rslt=mysql_to_mysqli($hour_stmt, $link); # * + $erlang_calls=mysqli_num_rows($hour_rslt); + + # PROVIDE ACTUAL STATS + $avg_rslt=mysql_to_mysqli($avg_stmt, $link); # ** + $avg_row=mysqli_fetch_array($avg_rslt); + $average_call_length=$avg_row["avg_length"]; + + $wrapup_rslt=mysql_to_mysqli($wrapup_stmt, $link); # *** + $wrapup_calls=mysqli_num_rows($wrapup_rslt); + $uid_ct=0; + $uid_clause=""; + $dispo_secs=0; + $talk_secs=0; + while ($wrapup_row=mysqli_fetch_row($wrapup_rslt)) { + $uid_ct++; + $uid_clause.="'$wrapup_row[0]',"; + if ($uid_ct%100==0) { + $uid_clause=preg_replace('/,$/', '', $uid_clause); + $uid_stmt="select dispo_sec, talk_sec from vicidial_agent_log where uniqueid in ($uid_clause)"; + $uid_rslt=mysql_to_mysqli($uid_stmt, $link); + while ($uid_row=mysqli_fetch_row($uid_rslt)) { + $dispo_secs+=$uid_row[0]; + $talk_secs+=$uid_row[1]; + } + $uid_clause=""; + } + } + if (strlen($uid_clause)>0) { + $uid_clause=preg_replace('/,$/', '', $uid_clause); + $uid_stmt="select dispo_sec, talk_sec from vicidial_agent_log where uniqueid in ($uid_clause)"; + $uid_rslt=mysql_to_mysqli($uid_stmt, $link); + while ($uid_row=mysqli_fetch_row($uid_rslt)) { + $dispo_secs+=$uid_row[0]; + $talk_secs+=$uid_row[1]; + } + $uid_clause=""; + } + $avg_dispo_sec=$dispo_secs/$wrapup_calls; + $avg_talk_sec=$talk_secs/$wrapup_calls; + ##### + + + $wrapup_stmt="select average(dispo_sec) from vicidial_agent_log"; + + $erlang_array=array(); + $drops_blocks=0; + $sales=0; + while ($hour_row=mysqli_fetch_array($hour_rslt)) { + $erlang_array["$hour_row[start_hour]"][0]+=$hour_row["length_up_to_next_hour"]; + $erlang_array["$hour_row[start_hour]"][2]++; + + if ($hour_row["length_running_into_next_hour"]>0) { + $erlang_array["$hour_row[end_hour]"][0]+=$hour_row["length_running_into_next_hour"]; + $erlang_array["$hour_row[end_hour]"][2]++; + if ($hour_row["status"]=="DROP") { + $erlang_array["$hour_row[end_hour]"][3]++; + } + } + + if ($hour_row["status"]=="DROP") { + $erlang_array["$hour_row[start_hour]"][1]+=$hour_row["length_up_to_next_hour"]; + $erlang_array["$hour_row[end_hour]"][1]+=$hour_row["length_running_into_next_hour"]; + $erlang_array["$hour_row[start_hour]"][3]++; + $drops_blocks++; + } + + if (in_array("$hour_row[status]", $sales_array)) { + $erlang_array["$hour_row[start_hour]"][4]++; + $sales++; + } + } + $hours_active=count($erlang_array); # Used for giving total erlangs for day, need to divide by number of hours reported, not one hour + $total_erlangs=($erlang_calls*$average_call_length/(3600*$hours_active)); + $total_blocking=($drops_blocks/$erlang_calls); + $sale_percent=($sales/$erlang_calls); + + $rpt_header ="+-----------------+-------+-------+------------+----------+-------------+----------+---------+"; + if ($erlang_type=="B") {$rpt_header.="---------+";} + if ($erlang_type=="C") {$rpt_header.="------------+------------+";} + $rpt_header.="------------+------------+------------+----------+-----------+------------+------------+------------+\n"; + + $ASCII_text.=$rpt_header; + # $ASCII_text.=$hour_stmt."
\n"; + + # Damn fixed-space formatting, hate ASCII. HATE. + if ($erlang_type=="B") { + if ($actual_agents>0) { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Actual agents: ")).sprintf("%-131s", "$actual_agents")." |\n"; + } + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total calls: ")).sprintf("%-131s", "$erlang_calls")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total drops: ")).sprintf("%-131s", "$drops_blocks")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired drop rate: ")).sprintf("%-5.2f", "$drop_percent").sprintf("%-126s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total blocking/drop rate: ")).sprintf("%-5.2f", (100*$total_blocking)).sprintf("%-126s", " %")." |\n"; # sprintf("%-131.4f", "$total_blocking") + $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired sale rate: ")).sprintf("%-5.2f", "$sale_chance").sprintf("%-126s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Actual sale rate: ")).sprintf("%-5.2f", (100*$sale_percent)).sprintf("%-126s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Average call duration: ")).sprintf("%-131.2f", "$average_call_length")." |\n"; + # $ASCII_text.="| ".sprintf("%70s", _QXZ("Average talk length: ")).sprintf("%-131.4f", "$avg_talk_sec")." |\n"; + # $ASCII_text.="| ".sprintf("%70s", _QXZ("Average wrapup time: ")).sprintf("%-131.4f", "$avg_dispo_sec")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Erlangs: ")).sprintf("%-131.4f", $total_erlangs)." |\n"; + } + if ($erlang_type=="C") { + if ($actual_agents>0) { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Actual agents: ")).sprintf("%-147s", "$actual_agents")." |\n"; + } + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total calls: ")).sprintf("%-147s", "$erlang_calls")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total drops: ")).sprintf("%-147s", "$drops_blocks")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired drop rate: ")).sprintf("%-5.2f", "$drop_percent").sprintf("%-142s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Total blocking/drop rate: ")).sprintf("%-5.2f", (100*$total_blocking)).sprintf("%-142s", " %")." |\n"; # sprintf("%-147.4f", "$total_blocking") + $ASCII_text.="| ".sprintf("%70s", _QXZ("Desired sale rate: ")).sprintf("%-5.2f", "$sale_chance").sprintf("%-142s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Actual sale rate: ")).sprintf("%-5.2f", (100*$sale_percent)).sprintf("%-142s", " %")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Average call duration: ")).sprintf("%-147.2f", "$average_call_length")." |\n"; + # $ASCII_text.="| ".sprintf("%70s", _QXZ("Average talk length: ")).sprintf("%-147.4f", "$avg_talk_sec")." |\n"; + # $ASCII_text.="| ".sprintf("%70s", _QXZ("Average wrapup time: ")).sprintf("%-147.4f", "$avg_dispo_sec")." |\n"; + $ASCII_text.="| ".sprintf("%70s", _QXZ("Erlangs: ")).sprintf("%-147.4f", $total_erlangs)." |\n"; + } + $HTML_text.=""; + if ($actual_agents>0) { + $HTML_text.=""; + } + $HTML_text.=""; + $HTML_text.=""; + $HTML_text.=""; + $HTML_text.=""; + $HTML_text.=""; + $HTML_text.=""; + $HTML_text.=""; + $HTML_text.=""; + + $CSV_text=""; + if ($actual_agents>0) { + $CSV_text.="\"Actual agents:\",\"$actual_agents\"\n"; + } + $CSV_text.="\"Total calls:\",\"$erlang_calls\"\n"; + $CSV_text.="\"Total drops:\",\"$drops_blocks\"\n"; + $CSV_text.="\"Desired drop rate:\",\"".sprintf("%5.2f", "$drop_percent")." %\"\n"; + $CSV_text.="\"Total blocking/drop rate:\",\"".sprintf("%-5.2f", (100*$total_blocking))."\"\n"; + $CSV_text.="\"Desired sale rate:\",\"".sprintf("%5.2f", "$sale_chance")." %\"\n"; + $CSV_text.="\"Actual sale rate:\",\"".sprintf("%-5.2f", (100*$sale_percent))."\"\n"; + $CSV_text.="\"Average call duration:\",\"".sprintf("%.2f", "$average_call_length")." seconds\"\n"; + $CSV_text.="\"Erlangs:\",\"".sprintf("%.4f", "$total_erlangs")."\"\n"; + + + # ESTIMATED AGENTS + $lines=1; + if ($total_blocking>0) { + $GoS=(pow($total_erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $total_erlangs)); + if ($GoS>$total_blocking) { + $ASCII_text.=""; + # if ($retry_rate>0) {$GoS=adjustedGoS($total_erlangs, $GoS, $retry_rate, $lines);} + } + $Pqueue=(pow($total_erlangs, $lines)/(factorial($lines)))/((pow($total_erlangs, $lines)/(factorial($lines)))+((1-($total_erlangs/$lines))*erlsum(0, ($lines-1), $total_erlangs))); + $ASA=($Pqueue*$average_call_length)/($lines-$total_erlangs); + } else { + $lines="N/A"; + $Pqueue=0; + $ASA=0; + } + if ($Pqueue>1) {$Pqueue=1;} + + if ($erlang_type=="B") { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Retry rate: ")).sprintf("%-131s", "$retry_rate %")." |\n"; # B + $ASCII_text.="| ".sprintf("%70s", _QXZ("Grade of service: ")).sprintf("%-131s", sprintf("%0.2f", (100*$GoS)." %"))." |\n"; # B + $ASCII_text.="| ".sprintf("%70s", _QXZ("Estimated agents fielding calls: ")).sprintf("%-131s", $lines)." |\n"; + } + if ($erlang_type=="C") { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Estimated queue probability: ")).sprintf("%-5.2f", (100*$Pqueue)).sprintf("%-142s", " %")." |\n"; # C + $ASCII_text.="| ".sprintf("%70s", _QXZ("Average speed of answering: ")).sprintf("%-147s", sec_convert($ASA,'H'))." |\n"; # C + $ASCII_text.="| ".sprintf("%70s", _QXZ("Estimated agents fielding calls: ")).sprintf("%-147s", $lines)." |\n"; + } + + if ($erlang_type=="B") { + $CSV_text.="\""._QXZ("Retry rate: ")."\",\"$retry_rate %\"\n"; # B + $CSV_text.="\""._QXZ("Grade of service: ")."\",\"".sprintf("%0.2f", (100*$GoS))." %\"\n"; # B + } + if ($erlang_type=="C") { + $CSV_text.="\""._QXZ("Estimated queue probability: ")."\",\"".sprintf("%.2f", (100*$Pqueue))."%\"\n"; # C + $CSV_text.="\""._QXZ("Average speed of answering: ")."\",\"".sec_convert($ASA,'H')."\"\n"; # C + } + $CSV_text.="\""._QXZ("Estimated agents fielding calls: ")."\",\"$lines\"\n"; + + if ($erlang_type=="B") { + $HTML_text.=""; # B + $HTML_text.=""; # B + } + if ($erlang_type=="C") { + $HTML_text.=""; # C + $HTML_text.=""; # C + } + $HTML_text.=""; + ############# + + ##### RECOMMENDED AGENTS + $lines=1; + if ($erlang_type=="B") { + $GoS=(pow($total_erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $total_erlangs)); + if ($GoS>$drop_rate) { + $ASCII_text.=""; + } + } + if ($erlang_type=="C") { + $Pqueue=(pow($total_erlangs, $lines)/(factorial($lines)))/((pow($total_erlangs, $lines)/(factorial($lines)))+((1-($total_erlangs/$lines))*erlsum(0, ($lines-1), $total_erlangs))); + if ($Pqueue>$pqueue_target) { + $ASCII_text.=""; + } + } + + if ($erlang_type=="B") { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Recommended agent count: ")).sprintf("%-131s", $lines)." |\n"; + } else { + $ASCII_text.="| ".sprintf("%70s", _QXZ("Recommended agent count: ")).sprintf("%-147s", $lines)." |\n"; + } + $CSV_text.="\"Recommended agent count:\",\"$lines\"\n"; + $CSV_text.="\n"; + + $HTML_text.=""; + $HTML_text.="
"._QXZ("Actual agents: ")."".$actual_agents."
"._QXZ("Total calls: ")."".$erlang_calls."
"._QXZ("Total drops: ")."".$drops_blocks."
"._QXZ("Desired drop rate: ")."".sprintf("%5.2f", "$drop_percent")." %
"._QXZ("Total blocking/drop rate: ")."".sprintf("%-5.2f", (100*$total_blocking))." %
"._QXZ("Desired sale rate: ")."".sprintf("%5.2f", "$sale_chance")." %
"._QXZ("Actual sale rate: ")."".sprintf("%-5.2f", (100*$sale_percent))." %
"._QXZ("Average call duration: ")."".sprintf("%18.2f", "$average_call_length")."
"._QXZ("Erlangs: ")."".sprintf("%18.4f", $total_erlangs)."
"._QXZ("Retry rate: ")."$retry_rate %
"._QXZ("Grade of service: ")."".sprintf("%0.2f", (100*$GoS))."%
"._QXZ("Estimated queue probability: ")."".sprintf("%.2f", (100*$Pqueue))."%
"._QXZ("Average speed of answering: ")."".sec_convert($ASA,'H')."
"._QXZ("Estimated agents fielding calls: ")."".$lines."
"._QXZ("Recommended agent count: ")."".$lines."
"; + + ############# + + $ASCII_text.=$rpt_header; + $ASCII_text.= "| "._QXZ("CALLING HOUR", 15)." | "._QXZ("CALLS", 5)." | "._QXZ("SALES", 5)." | "._QXZ("TOTAL TIME", 10)." | "._QXZ("AVG TIME", 8)." | "._QXZ("DROPPED HRS", 11)." | "._QXZ("BLOCKING", 8)." | "._QXZ("ERLANGS", 7); + if ($erlang_type=="B") {$ASCII_text.=" | "._QXZ("GOS", 7);} # B + if ($erlang_type=="C") {$ASCII_text.=" | "._QXZ("QUEUE PROB", 10)." | "._QXZ("AVG ANSWER", 10);} # C + $ASCII_text.=" | "._QXZ("REC AGENTS", 10)." | "._QXZ("EST AGENTS", 10)." | "._QXZ("CALLS/AGNT", 10)." | "._QXZ("REV/CALL", 8)." | "._QXZ("REV/AGENT", 9)." | "._QXZ("TOTAL REV", 10)." | "._QXZ("TOTAL COST", 10)." | "._QXZ("MARGIN", 10)." |\n"; # EST QUEUE | + $ASCII_text.=$rpt_header; + $CSV_text.="\""._QXZ("CALLING HOUR")."\",\""._QXZ("CALLS")."\",\""._QXZ("SALES")."\",\""._QXZ("TOTAL TIME")."\",\""._QXZ("AVG TIME")."\",\""._QXZ("DROPPED HRS")."\",\""._QXZ("BLOCKING")."\",\""._QXZ("ERLANGS")."\","; + if ($erlang_type=="B") {$CSV_text.="\""._QXZ("GRADE OF SERVICE")."\",";} # B + if ($erlang_type=="C") {$CSV_text.="\""._QXZ("QUEUE PROBABILITY")."\",\""._QXZ("AVERAGE ANSWER SPEED")."\",";} # C + $CSV_text.="\""._QXZ("REC AGENTS")."\",\""._QXZ("EST AGENTS")."\",\""._QXZ("CALLS/AGNT")."\",\""._QXZ("REV/CALL")."\",\""._QXZ("REV/AGENT")."\",\""._QXZ("TOTAL REV")."\",\""._QXZ("TOTAL COST")."\",\""._QXZ("MARGIN")."\"\n"; + ksort($erlang_array); + + $HTML_text2=""; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + + if ($erlang_type=="B") { + $HTML_text2.="\n"; # B + } + if ($erlang_type=="C") { + $HTML_text2.="\n"; # C + $HTML_text2.="\n"; # C + } + + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + + + $bht=0; + $graph_stats=array(); + $q=0; + while(list($key, $val)=each($erlang_array)) { + if ($val[0]>$bht) {$bht=$val[0];} + if ($q%2==0) {$tdclass="records_list_x";} else {$tdclass="records_list_y";} + $average_time=round($val[0]/$val[2]); + $blocking=($val[3]/$val[2]); + $erlangs=($val[2]*$average_time/3600); # Row is call per hour, therefore call length average must be in hours. + $sales=$val[4]+0; + + $ASCII_text.="| "; #.substr($key, 0, -2)." - ".substr($key, 5, 2)." ".substr($key, 8, 2)." ".substr($key, 0, 4); + $ASCII_text.=date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4))); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%5s", $val[2]); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%5s", $sales); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%10s", sec_convert($val[0],'H')); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%8s", sec_convert($average_time,'H')); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%11s", sec_convert($val[1],'H')); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%8s", sprintf("%01.4f", $blocking)); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%7s", sprintf("%01.4f", $erlangs)); + $ASCII_text.=" | "; + + $CSV_text.="\"".date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4)))."\",\"".$val[2]."\",\"".$sales."\",\"".sec_convert($val[0],'H')."\",\"".sec_convert($average_time,'H')."\",\"".sec_convert($val[1],'H')."\",\"".sprintf("%01.4f", $blocking)."\",\"".sprintf("%01.4f", $erlangs)."\","; + + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + + $graph_key=date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4))); + $graph_stats["$graph_key"][0]=$val[2]; + $graph_stats["$graph_key"][1]=$val[0]; + $graph_stats["$graph_key"][2]=$average_time; + $graph_stats["$graph_key"][3]=$val[1]; + $graph_stats["$graph_key"][4]=sprintf("%01.4f", $blocking); + $graph_stats["$graph_key"][5]=sprintf("%01.4f", $erlangs); + + ##### RECOMMENDED AGENTS + $lines=1; + if ($erlang_type=="B") { + $GoS=(pow($erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $erlangs)); + if ($GoS>$drop_rate) { + $ASCII_text.=""; + # if ($retry_rate>0) {$GoS=adjustedGoS($erlangs, $GoS, $retry_rate, $lines);} + } + } + if ($erlang_type=="C") { + $Pqueue=(pow($erlangs, $lines)/(factorial($lines)))/((pow($erlangs, $lines)/(factorial($lines)))+((1-($erlangs/$lines))*erlsum(0, ($lines-1), $erlangs))); + if ($Pqueue>$pqueue_target) { + $ASCII_text.=""; + } + } + $recommended_agents=$lines; + + ##### ESTIMATED AGENTS + $lines=1; + if ($blocking>0) { + $GoS=(pow($erlangs, $lines)/(factorial($lines)))/(erlsum(0, $lines, $erlangs)); + if ($GoS>$blocking) { + $ASCII_text.=""; + # if ($retry_rate>0) {$GoS=adjustedGoS($erlangs, $GoS, $retry_rate, $lines);} + } + + $Pqueue=(pow($erlangs, $lines)/(factorial($lines)))/((pow($erlangs, $lines)/(factorial($lines)))+((1-($erlangs/$lines))*erlsum(0, ($lines-1), $erlangs))); + $ASA=($Pqueue*$average_time)/($lines-$erlangs); + } else { + $lines="$recommended_agents"; + $Pqueue=0; + $ASA=0; + } + if ($actual_agents>0) { + $lines=$actual_agents; + $Pqueue=0; + $ASA=0; + } + if ($Pqueue>1) {$Pqueue=1;} + + if ($erlang_type=="B") { + $ASCII_text.=sprintf("%7s", sprintf("%0.2f", (100*$GoS))."%"); + $ASCII_text.=" | "; + } + if ($erlang_type=="C") { + $ASCII_text.=sprintf("%10s", sprintf("%.4f", (100*$Pqueue))."%"); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%10s", sec_convert($ASA,'H')); + $ASCII_text.=" | "; + } + $ASCII_text.=sprintf("%10s", $recommended_agents); + $ASCII_text.=" | "; + if ($erlang_type=="B") { + $CSV_text.="\"".sprintf("%0.2f", (100*$GoS))."%\","; # B + } + if ($erlang_type=="C") { + $CSV_text.="\"".sprintf("%.6f", (100*$Pqueue))."%\","; # C + $CSV_text.="\"".sec_convert($ASA,'H')."\","; # C + } + $CSV_text.="\"$recommended_agents\","; + $graph_stats["$graph_key"][7]=$recommended_agents; + if ($erlang_type=="B") { + $HTML_text2.="\n"; # B + } + if ($erlang_type=="C") { + $HTML_text2.="\n"; # C + $HTML_text2.="\n"; # C + } + $HTML_text2.="\n"; + + $ASCII_text.=sprintf("%10s", $lines); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%-10.2f", ($val[2]/$lines)); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%-8s", "\$".number_format(($revenue_per_sale*$sales/$val[2]),2,".",",")); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%-9s", "\$".number_format(($revenue_per_sale*$sales/$lines),2,".",",")); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%-10s", "\$".number_format(($revenue_per_sale*$sales),2,".",",")); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%-10s", "\$".number_format(($lines*$hourly_pay),2,".",",")); + $ASCII_text.=" | "; + $ASCII_text.=sprintf("%-10s", "\$".number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",",")); + $ASCII_text.=" |\n"; + # $ASCII_text.=sprintf("%-7.2f", (100*$Pqueue))." % |"; # $val[3] drops ERLANG C + # $ASCII_text.=" (".pow($erlangs, $lines)."/".(factorial($lines)).")/((".pow($erlangs, $lines)."/".(factorial($lines)).")+((1-($erlangs/$lines))*erlsum(0, ($lines-1), $erlangs)))"; ERLANG C + + $graph_stats["$graph_key"][8]=$drop_rate; + + + $CSV_text.="\"$lines\","; + $CSV_text.="\"".sprintf("%.2f", ($val[2]/$lines))."\","; + $CSV_text.="\"$".number_format(($revenue_per_sale*$sales/$val[2]),2,".",",")."\","; + $CSV_text.="\"$".number_format(($revenue_per_sale*$sales/$lines),2,".",",")."\","; + $CSV_text.="\"$".number_format(($revenue_per_sale*$sales),2,".",",")."\","; + $CSV_text.="\"$".number_format(($lines*$hourly_pay),2,".",",")."\","; + $CSV_text.="\"$".number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",",")."\"\n"; + # $CSV_text.="\"".sprintf("%.2f", (100*$Pqueue))." %\","; ERLANG C + + $graph_stats["$graph_key"][6]=$lines; + $graph_stats["$graph_key"][8]=$drop_rate; + $graph_stats["$graph_key"][9]=$sales; + $graph_stats["$graph_key"][10]=number_format(($revenue_per_sale*$sales/$val[2]),2,".",""); # Revenue per call + $graph_stats["$graph_key"][11]=number_format(($revenue_per_sale*$sales/$lines),2,".",""); # Revenue per agent + $graph_stats["$graph_key"][12]=number_format(($revenue_per_sale*$sales),2,".",""); # Total revenue + $graph_stats["$graph_key"][13]=number_format(($lines*$hourly_pay),2,".",""); # Cost + $graph_stats["$graph_key"][14]=number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",","); + $graph_stats["$graph_key"][15]=$GoS; + $graph_stats["$graph_key"][16]=$Pqueue; # Cost + $graph_stats["$graph_key"][17]=$ASA; # Cost + # $graph_stats["$graph_key"][9]=$Pqueue; ERLANG C + + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $HTML_text2.="\n"; + $q++; + } + $ASCII_text.=$rpt_header; + $ASCII_text.=" BHT: ".sec_convert($bht,'H')." ($bht seconds)\n"; + + $HTML_text2.="
"._QXZ("CALLING HOUR").""._QXZ("CALLS").""._QXZ("SALES").""._QXZ("TOTAL TIME").""._QXZ("AVG TIME").""._QXZ("DROPPED HRS").""._QXZ("BLOCKING").""._QXZ("ERLANGS").""._QXZ("GRADE OF SERVICE").""._QXZ("QUEUE PROB").""._QXZ("AVG ANSWER").""._QXZ("REC AGENTS").""._QXZ("EST AGENTS").""._QXZ("CALLS PER AGENT").""._QXZ("REVENUE PER CALL").""._QXZ("REVENUE PER AGENT").""._QXZ("TOTAL REVENUE").""._QXZ("TOTAL COST").""._QXZ("MARGIN")."
".date("Y-m-d ha", mktime(substr($key, -2), 0, 0, substr($key, 5, 2), substr($key, 8, 2), substr($key, 0, 4)))."".$val[2]."".$sales."".sec_convert($val[0],'H')."".sec_convert($average_time,'H')."".sec_convert($val[1],'H')."".sprintf("%01.4f", $blocking)."".sprintf("%01.4f", $erlangs)."".sprintf("%0.2f", (100*$GoS))."%".sprintf("%.4f", (100*$Pqueue))."%".sec_convert($ASA,'H')." $recommended_agents$lines".sprintf("%.2f", ($val[2]/$lines))."\$".number_format(($revenue_per_sale*$sales/$val[2]),2,".",",")."\$".number_format(($revenue_per_sale*$sales/$lines),2,".",",")."\$".number_format(($revenue_per_sale*$sales),2,".",",")."\$".number_format(($lines*$hourly_pay),2,".",",")."\$".number_format((($revenue_per_sale*$sales)-($lines*$hourly_pay)),2,".",",")."
"; + + # USE THIS FOR COMBINED graphs, use pipe-delimited array elements, dataset_name|index|link_name|graph_override + # You have to hard code the graph name in where it is overridden and mind the data indices. No other way to do it. + $multigraph_text=""; + $graph_id++; + $graph_array=array("ERL_BLOCKdata|4,8|BLOCKING/DROPS|percent|Blocking,Desired drop rate", "ERL_AGENTSdata|7,6|AGENTS|integer|Rec. Agents,Est. Agents", "ERL_CALLSdata|0,9|CALLS|integer|Calls,Sales", "ERL_TIMEdata|2,3,1|TIMES|time|Average time,Dropped time,Total time", "ERL_ERLANGSdata|5|ERLANGS|integer|Erlangs", "ERL_REVENUEdata|10,11|REVENUE|dollar|Revenue per call,Revenue per agent", "ERL_REVENUEdata|12,13|MARGINS|dollar|Total revenue,Total cost"); + if ($erlang_type=="B") { + array_push($graph_array, "ERL_GOSdata|15|GoS|integer|Grade of Service"); + } + if ($erlang_type=="C") { + array_push($graph_array, "ERL_PQUEUEdata|16|QUEUE|percent|Call queue probability"); +# $graph_stats["$graph_key"][16]=$ASA; # Cost + } + + + $default_graph="line"; # Graph that is initally displayed when page loads + include("graph_color_schemas.inc"); +# $backgroundColor=array("#9999FF", "#99FF99", "#FF9999"); +# $hoverBackgroundColor=array("#9999FF", "#99FF99", "#FF9999"); +# $hoverBorderColor=array("#9999FF", "#99FF99", "#FF9999"); +# $graphConstants ="\t\t\t\thoverBorderWidth: 2,\n"; +# $graphConstants.="\t\t\t\ttension: 0,\n"; +# $graphConstants.="\t\t\t\tfillColor: \"rgba(255,255,255,0.5)\",\n"; +# # $graphConstants.="\t\t\t\tbackgroundColor: \"#99f\",\n"; +# $graphConstants.="\t\t\t\tborderColor: \"rgba(0,0,0,0.8)\",\n"; +# $graphConstants.="\t\t\t\tpointBorderColor: \"rgba(0,0,0,1)\",\n"; +# $graphConstants.="\t\t\t\tpointBackgroundColor: \"#99f\",\n"; +# $graphConstants.="\t\t\t\tpointHoverBackgroundColor: \"rgba(255,255,204,0.75)\",\n"; +# $graphConstants.="\t\t\t\tpointHoverBorderColor: \"rgba(255,255,102,1)\"\n"; + + + # CUSTOMIZING COLORS FOR LINE GRAPHS + $graph_colors=array("216,0,0", "0,0,216", "0,216,0", "216,216,0", "216,0,216", "0,216,216"); + + + $graph_totals_array=array(); + $graph_totals_rawdata=array(); + for ($q=0; $q"._QXZ("TOTAL")." - ".sec_convert($current_graph_total, 'H')." \n"; + $chart_options="options: {tooltips: {callbacks: {label: function(tooltipItem, data) {var value = Math.round(data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]); return data.datasets[tooltipItem.datasetIndex].label+\": \"+value.toHHMMSS();}}}, legend: { display: true }},"; + break; + case "percent": + # $graph_totals_array[$q]=""; + $chart_options="options: {tooltips: {callbacks: {label: function(tooltipItem, data) {var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; return data.datasets[tooltipItem.datasetIndex].label+\": \"+ (value*100) + '%';}}}, legend: { display: true }},"; + break; + case "dollar": + # $graph_totals_array[$q]=""; + $chart_options="options: {tooltips: {callbacks: {label: function(tooltipItem, data) {var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; return data.datasets[tooltipItem.datasetIndex].label+\": \$\"+ value;}}}, legend: { display: true }},"; + break; + default: + # $graph_totals_array[$q]=" "._QXZ("TOTAL").": $current_graph_total\n"; + $chart_options="options: { legend: { display: true}},"; + break; + } + + $datasets.="\t\t]\n"; + $datasets.="\t}\n"; + + $JS_text.=$labels.$datasets; + # $JS_text.="}\n"; + # $JS_text.="prepChart('$default_graph', $graph_id, $q, $dataset_name);\n"; + $JS_text.="var main_ctx = document.getElementById(\"CanvasID".$graph_id."_".$q."\");\n"; + $JS_text.="var GraphID".$graph_id."_".$q." = new Chart(main_ctx, {type: '$default_graph', $chart_options data: $dataset_name});\n"; + } + + + $graph_count=count($graph_array); + $graph_title=_QXZ("ERLANGS REPORT"); + $hide_graph_choice="yes"; + include("graphcanvas.inc"); + $GRAPH.=$graphCanvas; + + + if ($report_display_type=="HTML") + { + $JS_onload.="}\n"; + $JS_text.=$JS_onload; + $JS_text.="\n"; + require("chart_button.php"); + + $MAIN.=$HTML_text.$GRAPH.$HTML_text2.$JS_text; + } + else + { + $MAIN.=$ASCII_text; + } + + + #$MAIN.="
"; + #$MAIN.=""; + $MAIN.=""; + +if ($file_download>0) + { + $FILE_TIME = date("Ymd-His"); + $CSVfilename = "AST_Erlang_report_$US$FILE_TIME.csv"; + $CSV_text=preg_replace('/\n +,/', ',', $CSV_text); + $CSV_text=preg_replace('/ +\"/', '"', $CSV_text); + $CSV_text=preg_replace('/\" +/', '"', $CSV_text); + + // We'll be outputting a TXT file + header('Content-type: application/octet-stream'); + // It will be called LIST_101_20090209-121212.txt + header("Content-Disposition: attachment; filename=\"$CSVfilename\""); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Pragma: public'); + ob_clean(); + flush(); + + echo "$CSV_text"; + } +else + { + header("Content-type: text/html; charset=utf-8"); + + echo "$HEADER"; + require("admin_header.php"); + echo "$MAIN"; + flush(); + } +# echo $ASCII_text; + } +?> \ No newline at end of file diff --git a/agc_2-X/trunk/www/vicidial/admin.php b/agc_2-X/trunk/www/vicidial/admin.php index f4245243..c453d0c1 100644 --- a/agc_2-X/trunk/www/vicidial/admin.php +++ b/agc_2-X/trunk/www/vicidial/admin.php @@ -120,9 +120,9 @@ $PHP_AUTH_PW=$_SERVER['PHP_AUTH_PW']; $PHP_SELF=$_SERVER['PHP_SELF']; $QUERY_STRING = getenv("QUERY_STRING"); -$Vreports = 'NONE, Real-Time Main Report, Real-Time Campaign Summary, Inbound Report, Inbound Report by DID, Inbound Service Level Report, Inbound Summary Hourly Report, Inbound Daily Report, Inbound DID Report, Agent DID Report, Inbound IVR Report, Outbound Calling Report, Outbound Summary Interval Report, Outbound IVR Report, Fronter - Closer Report, Fronter - Closer Detail Report, Lists Campaign Statuses Report, Lists Statuses Report, Campaign Status List Report, Export Calls Report, Export Leads Report, Agent Time Detail, Agent Status Detail, Agent Performance Detail, Team Performance Detail, Performance Comparison Report, Single Agent Daily, Single Agent Daily Time, User Group Login Report, User Group Hourly Report, User Timeclock Report, User Group Timeclock Status Report, User Timeclock Detail Report, Server Performance Report, Administration Change Log, List Update Stats, User Stats, User Time Sheet, Download List, Dialer Inventory Report, Maximum System Stats, Maximum Stats Detail, Search Leads Logs, Email Log Report, Carrier Log Report, Campaign Debug, Asterisk Debug, Hangup Cause Report, Lists Pass Report, Called Counts List IDs Report, Agent Debug Log Report, Agent Parked Call Report, Agent-Manager Chat Log, Recording Access Log Report, API Log Report'; +$Vreports = 'NONE, Real-Time Main Report, Real-Time Campaign Summary, Inbound Report, Inbound Report by DID, Inbound Service Level Report, Inbound Summary Hourly Report, Inbound Daily Report, Inbound DID Report, Agent DID Report, Inbound IVR Report, Inbound Forecasting Report, Advanced Forecasting Report, Outbound Calling Report, Outbound Summary Interval Report, Outbound IVR Report, Fronter - Closer Report, Fronter - Closer Detail Report, Lists Campaign Statuses Report, Lists Statuses Report, Campaign Status List Report, Export Calls Report, Export Leads Report, Agent Time Detail, Agent Status Detail, Agent Performance Detail, Team Performance Detail, Performance Comparison Report, Single Agent Daily, Single Agent Daily Time, User Group Login Report, User Group Hourly Report, User Timeclock Report, User Group Timeclock Status Report, User Timeclock Detail Report, Server Performance Report, Administration Change Log, List Update Stats, User Stats, User Time Sheet, Download List, Dialer Inventory Report, Maximum System Stats, Maximum Stats Detail, Search Leads Logs, Email Log Report, Carrier Log Report, Campaign Debug, Asterisk Debug, Hangup Cause Report, Lists Pass Report, Called Counts List IDs Report, Agent Debug Log Report, Agent Parked Call Report, Agent-Manager Chat Log, Recording Access Log Report, API Log Report'; -$UGreports = 'ALL REPORTS, NONE, Real-Time Main Report, Real-Time Campaign Summary, Inbound Report, Inbound Report by DID, Inbound Service Level Report, Inbound Summary Hourly Report, Inbound Daily Report, Inbound DID Report, Agent DID Report, Inbound Email Report, Inbound Chat Report, Inbound IVR Report, Outbound Calling Report, Outbound Summary Interval Report, Outbound IVR Report, Fronter - Closer Report, Fronter - Closer Detail Report, Lists Campaign Statuses Report, Lists Statuses Report, Campaign Status List Report, Export Calls Report, Export Leads Report, Agent Time Detail, Agent Status Detail, Agent Performance Detail, Team Performance Detail, Performance Comparison Report, Single Agent Daily, Single Agent Daily Time, User Group Login Report, User Group Hourly Report, User Timeclock Report, User Group Timeclock Status Report, User Timeclock Detail Report, Server Performance Report, Administration Change Log, List Update Stats, User Stats, User Time Sheet, Download List, Dialer Inventory Report, Custom Reports Links, CallCard Search, Maximum System Stats, Maximum Stats Detail, Search Leads Logs, Email Log Report, Lists Pass Report, Called Counts List IDs Report, Front Page System Summary, Report Page Servers Summary, Admin Utilities Page, Agent Debug Log Report, Agent Parked Call Report, Agent-Manager Chat Log, Recording Access Log Report, API Log Report'; +$UGreports = 'ALL REPORTS, NONE, Real-Time Main Report, Real-Time Campaign Summary, Inbound Report, Inbound Report by DID, Inbound Service Level Report, Inbound Summary Hourly Report, Inbound Daily Report, Inbound DID Report, Agent DID Report, Inbound Email Report, Inbound Chat Report, Inbound IVR Report, Inbound Forecasting Report, Advanced Forecasting Report, Outbound Calling Report, Outbound Summary Interval Report, Outbound IVR Report, Fronter - Closer Report, Fronter - Closer Detail Report, Lists Campaign Statuses Report, Lists Statuses Report, Campaign Status List Report, Export Calls Report, Export Leads Report, Agent Time Detail, Agent Status Detail, Agent Performance Detail, Team Performance Detail, Performance Comparison Report, Single Agent Daily, Single Agent Daily Time, User Group Login Report, User Group Hourly Report, User Timeclock Report, User Group Timeclock Status Report, User Timeclock Detail Report, Server Performance Report, Administration Change Log, List Update Stats, User Stats, User Time Sheet, Download List, Dialer Inventory Report, Custom Reports Links, CallCard Search, Maximum System Stats, Maximum Stats Detail, Search Leads Logs, Email Log Report, Lists Pass Report, Called Counts List IDs Report, Front Page System Summary, Report Page Servers Summary, Admin Utilities Page, Agent Debug Log Report, Agent Parked Call Report, Agent-Manager Chat Log, Recording Access Log Report, API Log Report'; $Vtables = 'NONE,log_noanswer,did_agent_log,contact_information'; @@ -4110,12 +4110,13 @@ else # 170412-2222 - Added Agent Parked Call Report link in Admin Utilities # 170416-1548 - Added ready_max_logout campaign/user setting and routing_prefix server setting # 170425-1353 - Fixed issue with entries in this server lists +# 170428-1958 - Added Inbound and Advanced Forecasting Reports # # make sure you have added a user to the vicidial_users MySQL table with at least user_level 9 to access this page the first time -$admin_version = '2.14-611a'; -$build = '170425-1353'; +$admin_version = '2.14-612a'; +$build = '170428-1958'; $STARTtime = date("U"); $SQLdate = date("Y-m-d H:i:s"); @@ -38913,7 +38914,7 @@ if ($ADD==999999) echo "
\n"; echo ""._QXZ("Inbound and Outbound Calling Reports")."
\n"; echo "