Add a new destination summary report

This commit is contained in:
FusionPBX 2024-01-02 18:54:22 -07:00 committed by GitHub
parent 0b968828fd
commit fff13633be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 381 additions and 0 deletions

View File

@ -0,0 +1,234 @@
<?php
/*
FusionPBX
Version: MPL 1.1
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.
The Original Code is FusionPBX
The Initial Developer of the Original Code is
Mark J Crane <markjcrane@fusionpbx.com>
Portions created by the Initial Developer are Copyright (C) 2023
the Initial Developer. All Rights Reserved.
Contributor(s):
Mark J Crane <markjcrane@fusionpbx.com>
*/
//includes files
require_once dirname(__DIR__, 2) . "/resources/require.php";
require_once "resources/check_auth.php";
//require_once "resources/paging.php";
//check permissions
if (permission_exists('destination_view')) {
//access granted
}
else {
echo "access denied";
exit;
}
//add multi-lingual support
$language = new text;
$text = $language->get();
//retrieve submitted data
if (!empty($_REQUEST)) {
$quick_select = $_REQUEST['quick_select'];
$start_stamp_begin = $_REQUEST['start_stamp_begin'];
$start_stamp_end = $_REQUEST['start_stamp_end'];
$include_internal = $_REQUEST['include_internal'];
}
else {
$quick_select = 3; //set default
}
//get the summary
$destination = new destinations;
$destination->domain_uuid = $_SESSION['domain_uuid'];
$destination->quick_select = $quick_select;
$destination->start_stamp_begin = $start_stamp_begin ?? null;
$destination->start_stamp_end = $start_stamp_end ?? null;
$destination->include_internal = $include_internal ?? null;
$summary = $destination->destination_summary();
//set the http header
if (!empty($_REQUEST['type']) && $_REQUEST['type'] == "csv") {
//set the headers
header('Content-type: application/octet-binary');
header('Content-Disposition: attachment; filename=user-summary.csv');
//show the column names on the first line
$z = 0;
foreach($summary[1] as $key => $val) {
if ($z == 0) {
echo '"'.$key.'"';
}
else {
echo ',"'.$key.'"';
}
$z++;
}
echo "\n";
//add the values to the csv
$x = 0;
foreach($summary as $users) {
$z = 0;
foreach($users as $key => $val) {
if ($z == 0) {
echo '"'.$summary[$x][$key].'"';
}
else {
echo ',"'.$summary[$x][$key].'"';
}
$z++;
}
echo "\n";
$x++;
}
exit;
}
//include the header
$document['title'] = $text['title-destination_summary'];
require_once "resources/header.php";
//css grid adjustment
echo "<style>\n";
echo " div.form_grid {\n";
echo " grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n";
echo " }\n";
echo "</style>\n";
//show the content
echo "<div class='action_bar' id='action_bar'>\n";
echo " <div class='heading'><b>".$text['title-destination_summary']."</b></div>\n";
echo " <div class='actions'>\n";
if (permission_exists('xml_cdr_extension_summary_all') && $_GET['show'] != 'all') {
echo button::create(['type'=>'button','label'=>$text['button-show_all'],'icon'=>$_SESSION['theme']['button_icon_all'],'collapse'=>'hide-sm-dn','link'=>'xml_cdr_extension_summary.php?show=all']);
}
echo button::create(['type'=>'button','label'=>$text['button-download_csv'],'icon'=>$_SESSION['theme']['button_icon_download'],'collapse'=>'hide-sm-dn','link'=>'xml_cdr_extension_summary.php?'.(!empty($_SERVER["QUERY_STRING"]) ? $_SERVER["QUERY_STRING"].'&' : null).'type=csv']);
echo button::create(['type'=>'button','label'=>$text['button-reset'],'icon'=>$_SESSION['theme']['button_icon_reset'],'collapse'=>'hide-xs','style'=>'margin-left: 15px;','link'=>'xml_cdr_extension_summary.php']);
echo button::create(['type'=>'button','label'=>$text['button-update'],'icon'=>$_SESSION['theme']['button_icon_save'],'id'=>'btn_save','collapse'=>'hide-xs','onclick'=>"document.getElementById('frm').submit();"]);
echo " </div>\n";
echo " <div style='clear: both;'></div>\n";
echo "</div>\n";
if (permission_exists('xml_cdr_search')) {
echo "<form name='frm' id='frm' method='get'>\n";
echo "<div class='form_grid' style='padding-bottom: 35px;'>\n";
echo " <div class='form_set'>\n";
echo " <div class='label'>\n";
echo " ".$text['label-preset']."\n";
echo " </div>\n";
echo " <div class='field'>\n";
echo " <select class='formfld' name='quick_select' id='quick_select' onchange=\"if (this.selectedIndex != 0) { document.getElementById('start_stamp_begin').value = ''; document.getElementById('start_stamp_end').value = ''; document.getElementById('frm').submit(); }\">\n";
echo " <option value=''></option>\n";
echo " <option value='1' ".(($quick_select == 1) ? "selected='selected'" : null).">".$text['option-last_seven_days']."</option>\n";
echo " <option value='2' ".(($quick_select == 2) ? "selected='selected'" : null).">".$text['option-last_hour']."</option>\n";
echo " <option value='3' ".(($quick_select == 3) ? "selected='selected'" : null).">".$text['option-today']."</option>\n";
echo " <option value='4' ".(($quick_select == 4) ? "selected='selected'" : null).">".$text['option-yesterday']."</option>\n";
echo " <option value='5' ".(($quick_select == 5) ? "selected='selected'" : null).">".$text['option-this_week']."</option>\n";
echo " <option value='6' ".(($quick_select == 6) ? "selected='selected'" : null).">".$text['option-this_month']."</option>\n";
echo " <option value='7' ".(($quick_select == 7) ? "selected='selected'" : null).">".$text['option-this_year']."</option>\n";
echo " </select>\n";
echo " </div>\n";
echo " </div>\n";
//echo " <div class='form_set'>\n";
//echo " <div class='label'>\n";
//echo " ".$text['label-include_internal']."\n";
//echo " </div>\n";
//echo " <div class='field'>\n";
//echo " <select class='formfld' name='include_internal' id='include_internal'>\n";
//echo " <option value='0'>".$text['option-false']."</option>\n";
//echo " <option value='1' ".((!empty($include_internal) && $include_internal == 1) ? "selected" : null).">".$text['option-true']."</option>\n";
//echo " </select>\n";
//echo " </div>\n";
//echo " </div>\n";
echo " <div class='form_set'>\n";
echo " <div class='label'>\n";
echo " ".$text['label-start_date_time']."\n";
echo " </div>\n";
echo " <div class='field'>\n";
echo " <input type='text' class='formfld datetimepicker' data-toggle='datetimepicker' data-target='#start_stamp_begin' onblur=\"$(this).datetimepicker('hide');\" style='min-width: 115px; width: 115px; max-width: 115px;' name='start_stamp_begin' id='start_stamp_begin' placeholder='".$text['label-from']."' value='".escape($start_stamp_begin ?? '')."'>\n";
echo " </div>\n";
echo " </div>\n";
echo " <div class='form_set'>\n";
echo " <div class='label'>\n";
echo " ".$text['label-end_date_time']."\n";
echo " </div>\n";
echo " <div class='field'>\n";
echo " <input type='text' class='formfld datetimepicker' data-toggle='datetimepicker' data-target='#start_stamp_end' onblur=\"$(this).datetimepicker('hide');\" style='min-width: 115px; width: 115px; max-width: 115px;' name='start_stamp_end' id='start_stamp_end' placeholder='".$text['label-to']."' value='".escape($start_stamp_end ?? '')."'>\n";
echo " </div>\n";
echo " </div>\n";
echo "</div>\n";
if (!empty($_GET['show']) && $_GET['show'] == 'all' && permission_exists('xml_cdr_extension_summary_all')) {
echo "<input type='hidden' name='show' value='all'>";
}
echo "</form>";
}
//show the results
echo "<table class='list'>\n";
echo " <tr class='list-header'>\n";
if (!empty($_GET['show']) && $_GET['show'] === "all" && permission_exists('xml_cdr_extension_summary_all')) {
echo " <th>".$text['label-domain']."</th>\n";
}
echo " <th>".$text['label-destination_number']."</th>\n";
if (permission_exists('number_alias')) {
echo " <th>".$text['label-number_alias']."</th>\n";
}
echo " <th class='center'>".$text['label-answered']."</th>\n";
echo " <th class='center'>".$text['label-unique_callers']."</th>\n";
echo " <th class='center'>".$text['label-total_calls']."</th>\n";
echo " <th class='center'>".$text['label-duration']."</th>\n";
echo " <th class='hide-sm-dn'>".$text['label-description']."</th>\n";
echo " </tr>\n";
if (is_array($summary)) {
foreach ($summary as $key => $row) {
echo "<tr class='list-row'>\n";
if (!empty($_GET['show']) && $_GET['show'] === "all" && permission_exists('xml_cdr_extension_summary_all')) {
echo " <td>".escape($row['domain_name'])."</td>\n";
}
echo " <td>".escape($row['destination_number'])."</td>\n";
if (permission_exists('number_alias')) {
echo " <td>".escape($row['number_alias'])."&nbsp;</td>\n";
}
echo " <td class='center'>".escape($row['answered_calls'])."&nbsp;</td>\n";
echo " <td class='center'>".escape($row['unique_callers'])."&nbsp;</td>\n";
echo " <td class='center'>".escape($row['total_calls'])."&nbsp;</td>\n";
//echo " <td class='center'>".(($row['outbound_calls'] != '') ? escape($row['outbound_calls']) : "0")."&nbsp;</td>\n";
echo " <td class='center'>".(($row['total_seconds'] != '') ? format_hours($row['total_seconds']) : '0:00:00')."</td>\n";
echo " <td class='description overflow hide-sm-dn'>".escape($row['destination_description'])."&nbsp;</td>\n";
echo "</tr>\n";
}
}
echo "</table>\n";
echo "<br />\n";
//show the footer
require_once "resources/footer.php";
?>

View File

@ -59,6 +59,9 @@ if (!class_exists('destinations')) {
$this->domain_uuid = $_SESSION['domain_uuid'];
}
//get the email queue settings
$this->setting = new settings();
//assign private variables
$this->app_name = 'destinations';
$this->app_uuid = '5ec89622-b19c-3559-64f0-afde802ab139';
@ -1105,6 +1108,150 @@ if (!class_exists('destinations')) {
}
} //method
/**
* destination summary returns an array
*/
public function destination_summary() {
//set the time zone
if (!empty($this->setting->get('domain', 'time_zone'))) {
$time_zone = $this->setting->get('domain', 'time_zone');
}
else {
$time_zone = date_default_timezone_get();
}
//build the date range
if ((!empty($this->start_stamp_begin) && strlen($this->start_stamp_begin) > 0) || !empty($this->start_stamp_end)) {
unset($this->quick_select);
if (strlen($this->start_stamp_begin) > 0 && !empty($this->start_stamp_end)) {
$sql_date_range = " and start_stamp between :start_stamp_begin::timestamptz and :start_stamp_end::timestamptz \n";
$parameters['start_stamp_begin'] = $this->start_stamp_begin.':00.000 '.$time_zone;
$parameters['start_stamp_end'] = $this->start_stamp_end.':59.999 '.$time_zone;
}
else {
if (!empty($this->start_stamp_begin)) {
$sql_date_range = "and start_stamp >= :start_stamp_begin::timestamptz \n";
$parameters['start_stamp_begin'] = $this->start_stamp_begin.':00.000 '.$time_zone;
}
if (!empty($this->start_stamp_end)) {
$sql_date_range .= "and start_stamp <= :start_stamp_end::timestamptz \n";
$parameters['start_stamp_end'] = $this->start_stamp_end.':59.999 '.$time_zone;
}
}
}
else {
switch ($this->quick_select) {
case 1: $sql_date_range = "and start_stamp >= '".date('Y-m-d H:i:s.000', strtotime("-1 week"))." ".$time_zone."'::timestamptz \n"; break; //last 7 days
case 2: $sql_date_range = "and start_stamp >= '".date('Y-m-d H:i:s.000', strtotime("-1 hour"))." ".$time_zone."'::timestamptz \n"; break; //last hour
case 3: $sql_date_range = "and start_stamp >= '".date('Y-m-d')." "."00:00:00.000 ".$time_zone."'::timestamptz \n"; break; //today
case 4: $sql_date_range = "and start_stamp between '".date('Y-m-d',strtotime("-1 day"))." "."00:00:00.000 ".$time_zone."'::timestamptz and '".date('Y-m-d',strtotime("-1 day"))." "."23:59:59.999 ".$time_zone."'::timestamptz \n"; break; //yesterday
case 5: $sql_date_range = "and start_stamp >= '".date('Y-m-d',strtotime("this week"))." "."00:00:00.000 ".$time_zone."' \n"; break; //this week
case 6: $sql_date_range = "and start_stamp >= '".date('Y-m-')."01 "."00:00:00.000 ".$time_zone."'::timestamptz \n"; break; //this month
case 7: $sql_date_range = "and start_stamp >= '".date('Y-')."01-01 "."00:00:00.000 ".$time_zone."'::timestamptz \n"; break; //this year
}
}
//calculate the summary data
$sql = "select \n";
$sql .= "d.domain_uuid, \n";
$sql .= "n.domain_name, \n";
$sql .= "d.destination_uuid, \n";
$sql .= "d.dialplan_uuid, \n";
$sql .= "d.destination_type, \n";
$sql .= "d.destination_prefix, \n";
$sql .= "d.destination_number, \n";
//total_calls
$sql .= "count(*) \n";
$sql .= "filter ( \n";
$sql .= " where caller_destination in (d.destination_number, concat(d.destination_prefix, d.destination_number), concat('+', d.destination_prefix, d.destination_number)) \n";
$sql .= ") \n";
$sql .= "as total_calls, \n";
//answered_calls
$sql .= "count(*) \n";
$sql .= "filter ( \n";
$sql .= " where caller_destination in (d.destination_number, concat(d.destination_prefix, d.destination_number), concat('+', d.destination_prefix, d.destination_number)) \n";
$sql .= " and billsec > 0 \n";
$sql .= ") \n";
$sql .= "as answered_calls, \n";
//unique_callers
$sql .= "count(distinct(c.caller_id_name)) \n";
$sql .= "filter ( \n";
$sql .= " where caller_destination in (d.destination_number, concat(d.destination_prefix, d.destination_number), concat('+', d.destination_prefix, d.destination_number)) \n";
$sql .= " and billsec > 0 \n";
$sql .= ") \n";
$sql .= "as unique_callers, \n";
//total_seconds
$sql .= "sum(billsec) \n";
$sql .= "filter ( \n";
$sql .= " where caller_destination in (d.destination_number, concat(d.destination_prefix, d.destination_number), concat('+', d.destination_prefix, d.destination_number)) \n";
$sql .= " and billsec > 0 \n";
$sql .= ") \n";
$sql .= "as total_seconds, \n";
$sql .= "d.destination_description \n";
$sql .= "from v_destinations as d, v_domains as n, \n";
$sql .= "( select \n";
$sql .= " domain_uuid, \n";
$sql .= " extension_uuid, \n";
$sql .= " caller_id_name, \n";
$sql .= " caller_id_number, \n";
$sql .= " caller_destination, \n";
$sql .= " destination_number, \n";
$sql .= " missed_call, \n";
$sql .= " answer_stamp, \n";
$sql .= " bridge_uuid, \n";
$sql .= " direction, \n";
$sql .= " start_stamp, \n";
$sql .= " hangup_cause, \n";
$sql .= " originating_leg_uuid, \n";
$sql .= " billsec, \n";
$sql .= " cc_side, \n";
$sql .= " sip_hangup_disposition \n";
$sql .= " from v_xml_cdr \n";
if (!(!empty($_GET['show']) && $_GET['show'] === 'all' && permission_exists('destination_summary_all'))) {
$sql .= " where domain_uuid = :domain_uuid \n";
}
else {
$sql .= " where true \n";
}
$sql .= " and direction = 'inbound' \n";
$sql .= " and caller_destination is not null \n";
$sql .= $sql_date_range;
$sql .= ") as c \n";
$sql .= "where \n";
$sql .= "d.domain_uuid = n.domain_uuid \n";
if (!(!empty($_GET['show']) && $_GET['show'] === 'all' && permission_exists('destination_summary_all'))) {
$sql .= "and d.domain_uuid = :domain_uuid \n";
}
$sql .= "and destination_type = 'inbound' \n";
$sql .= "and destination_enabled = 'true' \n";
$sql .= "group by d.domain_uuid, d.destination_uuid, d.dialplan_uuid, n.domain_name, d.destination_type, d.destination_prefix, d.destination_number \n";
$sql .= "order by destination_number asc \n";
if (!(!empty($_GET['show']) && $_GET['show'] === 'all' && permission_exists('destination_summary_all'))) {
$parameters['domain_uuid'] = $this->domain_uuid;
}
$database = new database;
$summary = $database->select($sql, $parameters, 'all');
unset($parameters);
//if (!empty($this->start_stamp_begin) && !empty($this->start_stamp_end)) {
// view_array($summary);
//}
//return the array
return $summary;
}
/**
* define singular function to convert a word in english to singular
*/