From 74454b738f956e611f62a5a2aa76b4c949c3a6cb Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 21 Jun 2017 17:20:29 +0300 Subject: [PATCH] Update CDR Stats application. (#2704) * Update CDR Stats application. Fix. Number of calls always calculate only for all domain. Fix. Number of missed calls ignores any search parameters and use only `inbound` filter. Fix. Calls duration for days use only domain filter and do not use any other filters. Add. Limit setting for number of hours to calculate statistic. Add. When timestamp set then calculate statistic only for this period. * Fix. Calculate `Calls per minute` Fix. Prevent divide `0/0` when calculate `ALOC` * Fix. `Hours` have to be integer type. --- app/xml_cdr/app_config.php | 8 + app/xml_cdr/xml_cdr_statistics.php | 11 +- app/xml_cdr/xml_cdr_statistics_inc.php | 244 +++++++++---------------- 3 files changed, 93 insertions(+), 170 deletions(-) diff --git a/app/xml_cdr/app_config.php b/app/xml_cdr/app_config.php index 658cbd0f10..f676e774ad 100644 --- a/app/xml_cdr/app_config.php +++ b/app/xml_cdr/app_config.php @@ -123,6 +123,14 @@ $apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true"; $apps[$x]['default_settings'][$y]['default_setting_description'] = ""; $y++; + $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "dd09aca6-5663-11e7-907b-a6006ad3dba0"; + $apps[$x]['default_settings'][$y]['default_setting_category'] = "cdr"; + $apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "stat_hours_limit"; + $apps[$x]['default_settings'][$y]['default_setting_name'] = "numeric"; + $apps[$x]['default_settings'][$y]['default_setting_value'] = "24"; + $apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false"; + $apps[$x]['default_settings'][$y]['default_setting_description'] = ""; + $y++; $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "cea53099-96c0-405f-ada6-219d0b398944"; $apps[$x]['default_settings'][$y]['default_setting_category'] = "cdr"; $apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "http_enabled"; diff --git a/app/xml_cdr/xml_cdr_statistics.php b/app/xml_cdr/xml_cdr_statistics.php index 860a8e52e1..5f2dfc1de2 100644 --- a/app/xml_cdr/xml_cdr_statistics.php +++ b/app/xml_cdr/xml_cdr_statistics.php @@ -215,14 +215,9 @@ else { echo " ALOC\n"; echo "\n"; echo "\n"; - echo " 1\n"; } - elseif ($i == $hours+2) { - echo "\n"; - echo " 7\n"; - } - elseif ($i == $hours+3) { - echo " 30\n"; + if ($i > $hours) { + echo " " . floor($row['hours']/24) . "\n"; } if ($i <= $hours) { echo " ".date('j M', $row['start_epoch'])."\n"; @@ -235,7 +230,7 @@ else { echo " ".$row['volume']." \n"; echo " ".(round($row['minutes'],2))." \n"; echo " ".(round($row['avg_min'],2))." \n"; - echo " ".$row['missed']." \n"; + echo " ".$row['missed']." \n"; echo " ".(round($row['asr'],2))." \n"; echo " ".(round($row['aloc'],2))." \n"; echo "\n"; diff --git a/app/xml_cdr/xml_cdr_statistics_inc.php b/app/xml_cdr/xml_cdr_statistics_inc.php index 1ada9e04cc..d8a36d5751 100644 --- a/app/xml_cdr/xml_cdr_statistics_inc.php +++ b/app/xml_cdr/xml_cdr_statistics_inc.php @@ -130,6 +130,11 @@ else { if(permission_exists('xml_cdr_b_leg')){ $leg = check_str($_REQUEST["leg"]); } + $show_all = permission_exists('xml_cdr_all') && ($_REQUEST['showall'] == 'true'); + } + else { + $show_all = permission_exists('xml_cdr_all') && ($_GET['showall'] == 'true'); + $direction = 'inbound'; } //if we do not see b-leg then use only a-leg to generate statistics @@ -138,6 +143,9 @@ else { } //build the sql where string + if (!$show_all) { + $sql_where_ands[] = "domain_uuid = '".$_SESSION['domain_uuid']."'"; + } if ($missed == true) { $sql_where_ands[] = "billsec = '0'"; } @@ -162,21 +170,15 @@ else { $sql_where_ands[] = "destination_number like '".$mod_destination_number."'"; } if (strlen($context) > 0) { $sql_where_ands[] = "context like '%".$context."%'"; } -/* if (strlen($start_stamp_begin) > 0 && strlen($start_stamp_end) > 0) { $sql_where_ands[] = "start_stamp BETWEEN '".$start_stamp_begin.":00.000' AND '".$start_stamp_end.":59.999'"; } - else { - if (strlen($start_stamp_begin) > 0) { $sql_where_ands[] = "start_stamp >= '".$start_stamp_begin.":00.000'"; } - if (strlen($start_stamp_end) > 0) { $sql_where_ands[] = "start_stamp <= '".$start_stamp_end.":59.999'"; } - } -*/ if (strlen($answer_stamp_begin) > 0 && strlen($answer_stamp_end) > 0) { $sql_where_ands[] = "answer_stamp BETWEEN '".$answer_stamp_begin.":00.000' AND '".$answer_stamp_end.":59.999'"; } - else { - if (strlen($answer_stamp_begin) > 0) { $sql_where_ands[] = "answer_stamp >= '".$answer_stamp_begin.":00.000'"; } - if (strlen($answer_stamp_end) > 0) { $sql_where_ands[] = "answer_stamp <= '".$answer_stamp_end.":59.999'"; } - } + // if (strlen($start_stamp_begin) > 0 && strlen($start_stamp_end) > 0) { $sql_where_ands[] = "start_stamp BETWEEN '".$start_stamp_begin.":00.000' AND '".$start_stamp_end.":59.999'"; } + // else if (strlen($start_stamp_begin) > 0) { $sql_where_ands[] = "start_stamp >= '".$start_stamp_begin.":00.000'"; } + // else if (strlen($start_stamp_end) > 0) { $sql_where_ands[] = "start_stamp <= '".$start_stamp_end.":59.999'"; } + if (strlen($answer_stamp_begin) > 0 && strlen($answer_stamp_end) > 0) { $sql_where_ands[] = "answer_stamp BETWEEN '".$answer_stamp_begin.":00.000' AND '".$answer_stamp_end.":59.999'"; } + else if (strlen($answer_stamp_begin) > 0) { $sql_where_ands[] = "answer_stamp >= '".$answer_stamp_begin.":00.000'"; } + else if (strlen($answer_stamp_end) > 0) { $sql_where_ands[] = "answer_stamp <= '".$answer_stamp_end.":59.999'"; } if (strlen($end_stamp_begin) > 0 && strlen($end_stamp_end) > 0) { $sql_where_ands[] = "end_stamp BETWEEN '".$end_stamp_begin.":00.000' AND '".$end_stamp_end.":59.999'"; } - else { - if (strlen($end_stamp_begin) > 0) { $sql_where_ands[] = "end_stamp >= '".$end_stamp_begin.":00.000'"; } - if (strlen($end_stamp_end) > 0) { $sql_where_ands[] = "end_stamp <= '".$end_stamp_end.":59.999'"; } - } + else if (strlen($end_stamp_begin) > 0) { $sql_where_ands[] = "end_stamp >= '".$end_stamp_begin.":00.000'"; } + else if (strlen($end_stamp_end) > 0) { $sql_where_ands[] = "end_stamp <= '".$end_stamp_end.":59.999'"; } if (strlen($duration) > 0) { $sql_where_ands[] = "duration like '%".$duration."%'"; } if (strlen($billsec) > 0) { $sql_where_ands[] = "billsec like '%".$billsec."%'"; } if (strlen($hangup_cause) > 0) { $sql_where_ands[] = "hangup_cause like '%".$hangup_cause."%'"; } @@ -233,7 +235,7 @@ else { // concatenate the 'ands's array, add to where clause if (sizeof($sql_where_ands) > 0) { - $sql_where = " where ".implode(" and ", $sql_where_ands)." and "; + $sql_where = " where ".implode(" and ", $sql_where_ands)." and "; } //calculate the seconds in different time frames @@ -245,15 +247,7 @@ else { //get the call volume between a start end end time in seconds function get_call_volume_between($start, $end, $where) { global $db; - if (strlen($where) == 0) { - if ($_GET['showall'] && permission_exists('xml_cdr_all')) { - $where = "where "; - } - else { - $where = "where domain_uuid = '".$_SESSION['domain_uuid']."' and "; - } - } - $sql = "select count(*) as count from v_xml_cdr "; + $sql = "select count(*) as count, sum(billsec) as seconds from v_xml_cdr "; $sql .= $where; $sql .= " start_epoch BETWEEN ".$start." AND ".$end." "; @@ -262,170 +256,96 @@ else { $result = $prep_statement->fetchAll(PDO::FETCH_ASSOC); unset ($prep_statement, $sql); if (count($result) > 0) { - foreach($result as $row) { - return $row['count']; + foreach ($result as $row) { + return array( + 'volume' => $row['count'], 'seconds' => $row['seconds'], + ); } } - else { - return false; - } - unset($prep_statement, $result, $sql); + return false; } -//get the call time in seconds between the start and end time in seconds - function get_call_seconds_between($start, $end, $where) { - global $db; - if (strlen($where) == 0) { - if ($_GET['showall'] && permission_exists('xml_cdr_all')) { - $where = "where "; - } - else { - $where = "where domain_uuid = '".$_SESSION['domain_uuid']."' and "; - } - } - $sql = "select sum(billsec) as seconds from v_xml_cdr "; - $sql .= $where; - $sql .= " start_epoch BETWEEN ".$start." AND ".$end." "; - $prep_statement = $db->prepare(check_sql($sql)); - $prep_statement->execute(); - $result = $prep_statement->fetchAll(PDO::FETCH_ASSOC); - unset ($prep_statement, $sql); - if (count($result) > 0) { - foreach($result as $row) { - $result = $row['seconds']; - if (strlen($result) == 0) { - return 0; - } - else { - return $row['seconds']; - } - } + function append_stats(&$stats, $hours, $start_epoch, $stop_epoch){ + global $db, $sql_where, $missed; + + $i = count($stats); + + $stats[$i]['hours'] = $hours; + $stats[$i]['start_stamp'] = date('Y-m-d h:n:s', $start_epoch); + $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); + $stats[$i]['start_epoch'] = $start_epoch; + $stats[$i]['stop_epoch'] = $stop_epoch; + $stat_range = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); + $stats[$i]['volume'] = $stat_range ? $stat_range['volume'] : 0; + $stats[$i]['seconds'] = $stat_range ? $stat_range['seconds'] : 0; + $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; + $stats[$i]['avg_sec'] = ($stats[$i]['volume']==0) ? 0 : $stats[$i]['seconds'] / $stats[$i]['volume']; + + if($missed) { + // we select only missed calls at first plase. so there no reasons to select it again. + $stats[$i]['missed'] = $stats[$i]['volume']; } else { - return false; + $where = $sql_where . "billsec = '0' and "; + $stat_range = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $where); + $stats[$i]['missed'] = $stat_range ? $stat_range['volume'] : 0; } - unset($prep_statement, $result, $sql); + + $delta_min = ($stop_epoch - $start_epoch) / 60; + $success_volume = ($stats[$i]['volume']==0) ? 0 : ($stats[$i]['volume'] - $stats[$i]['missed']); + + // Calls per minute + $stats[$i]['avg_min'] = $success_volume / $delta_min; + + //answer / seizure ratio + $stats[$i]['asr'] = ($stats[$i]['volume']==0) ? 0 : ($success_volume / $stats[$i]['volume'] * 100); + + //average length of call + $stats[$i]['aloc'] = ($success_volume==0) ? 0 : $stats[$i]['minutes'] / $success_volume; } - //$call_seconds_1st_hour = get_call_seconds_between(3600, 0); - //if (strlen($call_seconds_1st_hour) == 0) { $call_seconds_1st_hour = 0; } if (strlen(check_str($_GET['start_stamp_begin'])) > 0 && strlen(check_str($_GET['start_stamp_end'])) > 0 ) { $start_date = new DateTime(check_str($_GET['start_stamp_begin'])); $end_date = new DateTime(check_str($_GET['start_stamp_end'])); $time = $end_date->getTimestamp(); $time = $time - $time % 3600; - $hours = ($end_date->getTimestamp() - $start_date->getTimestamp()) / 3600; + $hours = floor(($end_date->getTimestamp() - $start_date->getTimestamp()) / 3600); } else { //round down to the nearest hour $time = time() - time() % 3600; $hours = 23; } -//call info hour by hour - for ($i = 0; $i <= $hours; $i++) { - $start_epoch = $time - 3600*$i; - $stop_epoch = $start_epoch + 3600; - $stats[$i]['hours'] = $i + 1; - $stats[$i]['start_stamp'] = date('Y-m-d h:n:s', $start_epoch); - $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); - $stats[$i]['start_epoch'] = $start_epoch; - $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); - $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); - $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; - $stats[$i]['avg_sec'] = ($stats[$i]['volume']==0) ? 0 : $stats[$i]['seconds'] / $stats[$i]['volume']; - $stats[$i]['avg_min'] = (($stats[$i]['volume']==0) ? 0 : $stats[$i]['volume'] - $stats[$i]['missed']) / 60; - - //answer / seizure ratio - if ($_GET['showall'] && permission_exists('xml_cdr_all')) { - $where = "where "; - } else { - $where = "where domain_uuid = '".$_SESSION['domain_uuid']."' and "; + if (isset($_SESSION['cdr']['stat_hours_limit']['numeric'])) { + $limit = $_SESSION['cdr']['stat_hours_limit']['numeric'] - 1; + if ($hours > $limit) { + $hours = $limit; } - $where .= " billsec = '0' and "; - $where .= " direction = 'inbound' and "; - $stats[$i]['missed'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $where); - $stats[$i]['asr'] = ($stats[$i]['volume']==0) ? 0 : (($stats[$i]['volume'] - $stats[$i]['missed']) / ($stats[$i]['volume']) * 100); - - //average length of call - $stats[$i]['aloc'] = ($stats[$i]['volume']==0) ? 0 : $stats[$i]['minutes'] / ($stats[$i]['volume'] - $stats[$i]['missed']); + unset($limit); } -//call info for a day - $i = $hours+1; - $start_epoch = time() - $seconds_day; - $stop_epoch = time(); - $stats[$i]['hours'] = 24; - $stats[$i]['start_stamp'] = date('Y-m-d h:n:s', $start_epoch); - $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); - $stats[$i]['start_epoch'] = $start_epoch; - $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); - $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); - $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; - $stats[$i]['avg_sec'] = ($stats[$i]['volume']==0) ? 0 : $stats[$i]['seconds'] / $stats[$i]['volume']; - $stats[$i]['avg_min'] = ($stats[$i]['volume'] - $stats[$i]['missed']) / (60*24); - if ($_GET['showall'] && permission_exists('xml_cdr_all')) { - $where = "where "; - } else { - $where = "where domain_uuid = '".$_SESSION['domain_uuid']."' and "; - } - $where .= " billsec = '0' and "; - $where .= " direction = 'inbound' and "; - $stats[$i]['missed'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $where); - $stats[$i]['asr'] = ($stats[$i]['volume']==0) ? 0 :(($stats[$i]['volume'] - $stats[$i]['missed']) / ($stats[$i]['volume']) * 100); - $stats[$i]['aloc'] = ($stats[$i]['volume']==0) ? 0 :$stats[$i]['minutes'] / ($stats[$i]['volume'] - $stats[$i]['missed']); - $i++; + $stats = array(); -//call info for a week - $start_epoch = time() - $seconds_week; - $stop_epoch = time(); - $stats[$i]['hours'] = 24 * 7; - $stats[$i]['start_stamp'] = date('Y-m-d h:n:s', $start_epoch); - $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); - $stats[$i]['start_epoch'] = $start_epoch; - $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); - $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); - $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; - $stats[$i]['avg_sec'] = ($stats[$i]['volume']==0) ? 0 :$stats[$i]['seconds'] / $stats[$i]['volume']; - $stats[$i]['avg_min'] = ($stats[$i]['volume']==0) ? 0 :($stats[$i]['volume'] - $stats[$i]['missed']) / (60*24*7); - if ($_GET['showall'] && permission_exists('xml_cdr_all')) { - $where = "where "; - } else { - $where = "where domain_uuid = '".$_SESSION['domain_uuid']."' and "; +//call info hour by hour for last n hours + for ($i = $hours; $i >= 0 ; $i--) { + $start_epoch = $time - 3600 * $i; + $stop_epoch = $start_epoch + 3600; + append_stats($stats, 1, $start_epoch, $stop_epoch); } - $where .= " billsec = '0' and "; - $where .= " direction = 'inbound' and "; - $stats[$i]['missed'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $where); - $stats[$i]['asr'] = ($stats[$i]['volume']==0) ? 0 :(($stats[$i]['volume'] - $stats[$i]['missed']) / ($stats[$i]['volume']) * 100); - $stats[$i]['aloc'] = ($stats[$i]['volume']==0) ? 0 :$stats[$i]['minutes'] / ($stats[$i]['volume'] - $stats[$i]['missed']); - $i++; -//call info for a month - $start_epoch = time() - $seconds_month; - $stop_epoch = time(); - $stats[$i]['hours'] = 24 * 30; - $stats[$i]['start_stamp'] = date('Y-m-d h:n:s', $start_epoch); - $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); - $stats[$i]['start_epoch'] = $start_epoch; - $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); - $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); - $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; - $stats[$i]['avg_sec'] = ($stats[$i]['volume']==0) ? 0 :$stats[$i]['seconds'] / $stats[$i]['volume']; - $stats[$i]['avg_min'] = ($stats[$i]['volume'] - $stats[$i]['missed']) / (60*24*30); - if ($_GET['showall'] && permission_exists('xml_cdr_all')) { - $where = "where "; - } else { - $where = "where domain_uuid = '".$_SESSION['domain_uuid']."' and "; +//call info for entire period + if (strlen(check_str($_GET['start_stamp_begin'])) > 0 && strlen(check_str($_GET['start_stamp_end'])) > 0 ) { + $start_epoch = new DateTime(check_str($_GET['start_stamp_begin'])); + $stop_epoch = new DateTime(check_str($_GET['start_stamp_end'])); + $days = $start_epoch->diff($stop_epoch)->d; + append_stats($stats, 24 * $days, $start_epoch->getTimestamp(), $stop_epoch->getTimestamp() ); + } + else { + $stop_epoch = time(); + append_stats($stats, 24, $stop_epoch - $seconds_day, $stop_epoch ); + append_stats($stats, 24 * 7, $stop_epoch - $seconds_week, $stop_epoch ); + append_stats($stats, 24 * 30, $stop_epoch - $seconds_month, $stop_epoch ); } - $where .= " billsec = '0' and "; - $where .= " direction = 'inbound' and "; - $stats[$i]['missed'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $where); - $stats[$i]['asr'] = ($stats[$i]['volume']==0) ? 0 :(($stats[$i]['volume'] - $stats[$i]['missed']) / ($stats[$i]['volume']) * 100); - $stats[$i]['aloc'] =($stats[$i]['volume']==0) ? 0 : $stats[$i]['minutes'] / ($stats[$i]['volume'] - $stats[$i]['missed']); - $i++; //show the graph @@ -471,4 +391,4 @@ else { if ($x == $hours) { break; } $x++; } -?> +?> \ No newline at end of file