Asternic CDR Reports

 asternic cdr stats

Приложение устанавливается в три клика, как локальный модуль FreePBX.
В отличии от стандартного CDR группирует вызовы по внутренним абонентам,
а также по входящим и исходящим вызовам.
Скачать Asternic CDR Reports

Как установить

После загрузки модуля необходимо войти в FreePBX, выберите Admin - Module Admin, а затем выберите опцию «Upload module». Вы должны выбрать файл, который вы только что скачали с вашего жесткого диска и нажмите кнопку «Upload».

После загрузки, нажмите на ссылку Manage Local Modules, прокрутите страницу вниз до раздела Отчеты, а затем нажмите на кнопку Asternic CDR Reports. После этого установите переключатель Install и, наконец, нажмите кнопку Proceed в самом низу страницы.

FreePBX Call Recordings + Asternic CDR Reports 1.5.1

Данная модификация включает отображение записей разговоров FreePBX
в модуле Asterisk CDR Reports Скачать asternic_cdr-1.5.1.tgz исправленный asternic_cdr

код модификации

Замените файл:

/var/www/html/admin/modules/asternic_cdr/functions.inc.php модуля Asternic.

на файл именем с модифицированным кодом:

[root@localhost asternic_cdr]# ls -la | grep fu
-rw-r--r--  1 asterisk asterisk 16431 Feb 13 16:17 functions.inc.php
-rw-r--r--  1 asterisk asterisk 16163 Feb 13 16:16 functions.inc.php.bk
<?php

if(isset($_SERVER['PATH_INFO'])) {
    define("SELF",  substr($_SERVER['PHP_SELF'], 0, (strlen($_SERVER['PHP_SELF']) - @strlen($_SERVER['PATH_INFO']))));
} else {
    define("SELF",  $_SERVER['PHP_SELF']);
}

function asternic_cdr_get_config($engine) {
    // Executed on APPLY in FreePBX, we regenerate the fop2buttons if needed
    global $amp_conf, $db, $active_modules;


}

function asternic_cdr_query() {

    global $active_modules, $amp_conf, $db;

    $sql = "SELECT exten,privacy,label,`group`,email,channel,queuechannel,originatechannel,customastdb,spyoptions,external FROM fop2buttons";
    $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
    if(DB::IsError($results)) {
        die($results->getMessage());
    }
    foreach ($results as $result) {
        $fopprivacy[$result['exten']]   = $result['privacy'];
        $foplabel[$result['exten']]     = $result['label'];
        $fopgroup[$result['exten']]     = $result['group'];
        $fopemail[$result['exten']]     = $result['email'];
        $fopchannel[$result['exten']]   = $result['channel'];
        $fopqchannel[$result['exten']]  = $result['queuechannel'];
        $fopochannel[$result['exten']]  = $result['originatechannel'];
        $fopcustastdb[$result['exten']] = $result['customastdb'];
        $fopspyoption[$result['exten']] = $result['spyoptions'];
        $fopexternal[$result['exten']]  = $result['external'];
    }

}

function return_timestamp($date_string)
{
  list ($year,$month,$day,$hour,$min,$sec) = preg_split("/-|:| /",$date_string,6);
  $u_timestamp = mktime($hour,$min,$sec,$month,$day,$year);
  return $u_timestamp;
}

function swf_bar($values,$width,$height,$divid,$stack)
{
    global $config;

    if ($stack==1) {
        $chart = "images/barstack.swf";
    } else {
        $chart = "images/bar.swf";
    }
    $return = "<div id='$divid'>\n";
    $return.= "</div>\n";
    $values = html_entity_decode($values);
    $return.= "<script type='text/javascript'>\n";
    $return.='$(document).ready(function() {'."\n";

    $variables = split("&",$values);
    if(isset($config['no_animation'][''])) {
        $variables[] = "noanimate=1";
    }

    $return .= "var flashvars = {\n";
    $param = Array();
    foreach($variables as $deauna) {
        $pedazos = split("=",$deauna);
        $param[]="'$pedazos[0]': '$pedazos[1]'";
    }
    $texti = implode(",\n",$param);
    $return.=$texti;
    $return.=" };\n";

    $return.= "swfobject.embedSWF('$chart', '$divid', '$width', '$height', '9.0.0', '#336699', flashvars, {wmode:'transparent'});\n";
    $return.= "});</script>\n";
    echo $return;
}

function print_exports($header_pdf,$data_pdf,$width_pdf,$title_pdf,$cover_pdf) {
        global $lang;
        global $language;
        $head_serial = serialize($header_pdf);
        $data_serial = serialize($data_pdf);
        $width_serial = serialize($width_pdf);
        $title_serial = serialize($title_pdf);
        $cover_serial = serialize($cover_pdf);
        $head_serial = rawurlencode($head_serial);
        $data_serial = rawurlencode($data_serial);
        $width_serial = rawurlencode($width_serial);
        $title_serial = rawurlencode($title_serial);
        $cover_serial = rawurlencode($cover_serial);

        $complete_self = $_SERVER['REQUEST_URI'];
                //echo "<br/><form method=post action='modules/asternic_cdr/export.php'>\n";
        echo "<br/><form method='post' action='$complete_self'>\n";
        foreach($_REQUEST as $kkey=>$vval) {
                echo "<input type='hidden' name='$kkey' value='".$vval."' />\n";
        }
                echo "<input type='hidden' name='action' value='export' />\n";
                echo "<input type='hidden' name='head' value='".$head_serial."' />\n";
                echo "<input type='hidden' name='rawdata' value='".$data_serial."' />\n";
                echo "<input type='hidden' name='width' value='".$width_serial."' />\n";
                echo "<input type='hidden' name='title' value='".$title_serial."' />\n";
                echo "<input type='hidden' name='cover' value='".$cover_serial."' />\n";
                echo "<a href='javascript:void()' class='info'><input type=image name='pdf' src='images/asternic_pdf.gif' style='border:0;'><span>";
                echo _('Export to PDF');
                echo "</span></a>\n";
                echo "<a href='javascript:void()' class='info'><input type=image name='csv' src='images/asternic_excel.gif' style='border:0;'><span>";
                echo _('Export to CSV/Excel');
                echo "</span></a>\n";
                echo "</form>";
}

function seconds2minutes($segundos) {
    $horas    = intval($segundos / 3600);
    $minutos  = intval($segundos % 3600 ) / 60;
    $segundos = $segundos % 60;
    $ret = sprintf("%02d:%02d:%02d",$horas,$minutos,$segundos);

//    return "$minutos:$segundos";
    return $ret;
}

function remove_quotes($argument) {
    return substr($argument,1,-1);
}

function asternic_download($file) {
    include("download.php");
}

function asternic_getrecords( $MYVARS ) {
    global $active_modules, $amp_conf, $db;

    $channel = $MYVARS['channel'];
    $start   = $MYVARS['start'];
    $end     = $MYVARS['end'];
    $gtype    = $MYVARS['direction'];
    $condicionextra="";

    if($gtype=='outgoing') {
        $chanfield = "channel";
        $otherchanfield = "dstchannel";
    } else {
        $chanfield = "dstchannel";
        $otherchanfield = "channel";
    }

$query = "SELECT substring($chanfield,1,locate(\"-\",$chanfield,length($chanfield)-8)-1) AS chan1,";
//$query = "SELECT IF($chanfield like 'Local/%',CONCAT('SIP',RIGHT(substring(replace($chanfield,'-','/'),1,instr($chanfield,'@')-1),instr(reverse(substring(replace($chanfield,'-','/'),1,instr($chanfield,'@')-1)),'/'))),substring($chanfield,1,locate(\"-\",$chanfield,length($chanfield)-8)-1)) as chan1, ";
//$query.= "billsec,duration,duration-billsec as ringtime,src,";
//изменение
$query.= "billsec,duration,duration-billsec as ringtime,src,recordingfile,";
$query.="IF(dst='s',dcontext,dst) as dst,calldate,disposition,accountcode,userfield,uniqueid FROM asteriskcdrdb.cdr ";
$query.= "WHERE calldate >= '$start' AND calldate <= '$end' AND (duration-billsec) >=0 $condicionextra ";
$query.= "HAVING chan1 IN ('$channel') ORDER BY calldate";


$me=true;

$res = $db->query($query);

if(DB::IsError($res)) {
    die($res->getMessage());
}

$ftype = $_REQUEST['type'];
$fdisplay = $_REQUEST['display'];
$ftab = $gtype;

$cont=0;
while ($res->fetchInto($row, DB_FETCHMODE_ASSOC)) {

      if (!(substr($row['accountcode'],0,5)=='Local' && $dispo[$row['disposition']]=='BUSY' && $row[9]=='ResetCDR')) {
         $cont++;
         $disposition = $row['disposition'];

         if(!isset($detail[$row['chan1']])) {
             $detail[$row['chan1']]="";
         }

         $me = ! $me;
         if($me==true) {
             $odclass="class='odd'";
         } else {
             $odclass="";
         }
         $bill_print = seconds2minutes($row['billsec']);

         $detail[$row['chan1']].= "<tr $odclass>\n<td>$cont</td>\n";
         $detail[$row['chan1']].= "<td style='text-align: center;' >".$row['calldate']."</td>\n";
         $detail[$row['chan1']].= "<td>".$row['src']."</td><td>".$row['dst']."</td>\n";
         $detail[$row['chan1']].= "<td align=right>".$bill_print."</td>\n";
         $detail[$row['chan1']].="<td align=right>".$row['ringtime']." "._('secs')."</td>\n";
         $detail[$row['chan1']].= "<td style='text-align: center;'>";

         if($row['disposition']=="NO ANSWER" || $row['disposition']=="FAILED") {
            $detail[$row['chan1']].="<span style='color: red;'>";
         } elseif($row['disposition']=="BUSY") {
            $detail[$row['chan1']].="<span style='color: orange;'>";
         } else {
            $detail[$row['chan1']].="<span style='color: green;'>";
         }

          $detail[$row['chan1']].= $row['disposition'];
          $detail[$row['chan1']].= "</span></td>";
//изменение
if ($row['recordingfile']) {
            $rec_parts = explode('-',$row['recordingfile']);
            $fyear = substr($rec_parts[3],0,4);
            $fmonth = substr($rec_parts[3],4,2);
            $fday = substr($rec_parts[3],6,2);
            $monitor_base = $amp_conf['MIXMON_DIR'] ? $amp_conf['MIXMON_DIR'] : $amp_conf['ASTSPOOLDIR'] . '/monitor';
            $recordingfile = "$monitor_base/$fyear/$fmonth/$fday/" . $row['recordingfile'];
            if (!file_exists($recordingfile)) {
                $recordingfile = '';
                $detail[$row['chan1']].= "\n<td>";
            }
            else {
            $detail[$row['chan1']].= "\n<td style='text-align: center;' title=\"$row[recordingfile]\"><a href=\"".$PHP_SELF."?getRec=".base64_encode($recordingfile)."\" target=\"_blank\"><img src=\"images/asternic_playicon.png\" alt=\"Call recording\" /></a>";
            }
        } else {
            $recordingfile = '';
            $detail[$row['chan1']].= "\n<td>";
        }
          $detail[$row['chan1']].= "</td>\n";


//изменение
//          $detail[$row['chan1']].= "\n<td>";
//
//          $uni = $row['uniqueid'];
//          $uni = str_replace(".","",$uni);
//
//             if($row['userfield']<>"") {
//              $detail[$row['chan1']].="<a href=\"javascript:void(0);\" onclick='javascript:playVmail(\"".$row['userfield']."\",\"play".$uni."\");'>";
//              $detail[$row['chan1']].="<div class='playicon' title='Play' id='play".$uni."'  style='float:left;'>";
//              $detail[$row['chan1']].="<img src='images/blank.gif' alt='pixel' height='16' width='16' border='0'>";
//              $detail[$row['chan1']].="</div></a>";
//              $detail[$row['chan1']].="<a href=\"javascript:void(0); return false;\" onclick='javascript:downloadVmail(\"".$row['userfield']."\",\"play".$uni."\",\"$ftype\",\"$fdisplay\",\"$ftab\"); return false;'>";
//              $detail[$row['chan1']].="<div class='downicon' title='Download' id='dload".$uni."'  style='float:left;'>";
//              $detail[$row['chan1']].="<img src='images/blank.gif' alt='pixel' height='16' width='16' border='0'>";
//              $detail[$row['chan1']].="</div></a>";
//          } else {
//              $detail[$row['chan1']].= "&nbsp;";
//          }
//          $detail[$row['chan1']].= "</td>\n";
          $detail[$row['chan1']].= "\n</tr>\n";
      }

}

echo "<table width='99%' cellpadding=3 cellspacing=3 border=0 id='table${channel}' class='sortable'>\n";
echo "<thead><tr><td bgcolor='#ddcc00'>#</td>";
echo "<td bgcolor='#ddcc00' align='center'>"._('Date')."</td>\n";
echo "<td bgcolor='#ddcc00'>"._('From')."</td>\n";
echo "<td bgcolor='#ddcc00'>"._('To')."</td>\n";
echo "<td bgcolor='#ddcc00' align='right'>"._('Billable Time')."</td>\n";
echo "<td bgcolor='#ddcc00' align='right'>"._('Ring Time')."</td>\n";
echo "<td bgcolor='#ddcc00' align='center'>"._('Disposition')."</td>\n";
echo "<td bgcolor='#ddcc00' align='center'>"._('Listen')."</td></tr></thead>\n";
echo "<tbody>".$detail[$channel]."</tbody>\n";
echo "</table>\n";


$complete_self = $_SERVER['REQUEST_URI'];
echo "<form id='downloadform' method='get' action='$complete_self'><input type=hidden name='file' id='downloadfile' value=''><input type=hidden name='action' value='download'><input type='hidden' name='type' id='dtype' value=''><input type='hidden' id='idisplay' name='display' value=''> <input type='hidden' id='itab' name='tab' value=''></form>";

}


define('FPDF_FONTPATH',dirname(__FILE__).'/lib/font/');
include_once(dirname(__FILE__) . "/lib/fpdf.php");

class PDF extends FPDF
{

function Footer()
{
    global $lang;
    global $language;
    //Go to 1.5 cm from bottom
    $this->SetY(-15);
    //Select Arial italic 8
    $this->SetFont('Arial','I',8);
    //Print centered page number
    $this->Cell(0,10,$lang["$language"]['page'].' '.$this->PageNo(),0,0,'C');
}

function Cover($cover)
{
    $this->SetFont('Arial','',15);
    $this->MultiCell(150,9,$cover);
    $this->Ln();
}

function Header()
{
    global $title;
    //Select Arial bold 15
    $this->SetFont('Arial','B',15);
    //Move to the right
    $this->Cell(85);
    //Framed title
    $this->Cell(30,10,$title,0,0,'C');
    //Line break
    $this->Ln(10);
}

function TableHeader($header,$w)
{
    $this->SetFillColor(255,0,0);
    $this->SetTextColor(255);
    $this->SetDrawColor(128,0,0);
    $this->SetLineWidth(.3);
    $this->SetFont('','B',11);

    for($i=0;$i<count($header);$i++)
        $this->Cell($w[$i],10,$header[$i],1,0,'C',1);
    $this->Ln();
}

//Colored table
function FancyTable($header,$data,$w)
{

    $this->TableHeader($header,$w);

    //Color and font restoration
    $this->SetFillColor(224,235,255);
    $this->SetTextColor(0);
    $this->SetFont('');
    //Data
    $fill=0;
    $supercont=1;
    foreach($data as $row)
    {
        $contador=0;
        foreach($row as $valor) {
            $this->Cell($w[$contador],6,$valor,'LR',0,'C',$fill);
            $contador++;
        }
        $this->Ln();
        $fill=!$fill;
        if($supercont%40 == 0) {
            $this->Cell(array_sum($w),0,'','T');
            $this->AddPage();
            $this->TableHeader($header,$w);
            $this->SetFillColor(224,235,255);
            $this->SetTextColor(0);
            $this->SetFont('');
        }
        $supercont++;
    }
    $this->Cell(array_sum($w),0,'','T');
}
}

function asternic_export_csv($header,$data) {
    header("Content-Type: application/csv-tab-delimited-table");
    header("Content-disposition: filename=table.csv");

    $linea="";
    foreach($header as $valor) {
        $linea.="\"$valor\",";
    }
    $linea=substr($linea,0,-1);

    print $linea."\r\n";

    foreach($data as $valor) {
        $linea="";
        foreach($valor as $subvalor) {
            $linea.="\"$subvalor\",";
        }
        $linea=substr($linea,0,-1);
        print $linea."\r\n";
    }
}

function asternic_export($REQ) {

    $header = unserialize(rawurldecode($REQ['head']));
    $data   = unserialize(rawurldecode($REQ['rawdata']));
    $width  = unserialize(rawurldecode($REQ['width']));
    $title  = unserialize(rawurldecode($REQ['title']));
    $cover  = unserialize(rawurldecode($REQ['cover']));

    if(isset($_REQUEST['pdf']) || isset($REQ['pdf_x'])) {
        $pdf=new PDF();
        $pdf->SetFont('Arial','',12);
        $pdf->SetAutoPageBreak(true);
        $pdf->SetLeftMargin(1);
        $pdf->SetRightMargin(1);
        $pdf->AddPage();
        if($cover<>"") {
            $pdf->Cover($cover);
        }
        $pdf->AddPage();
        $pdf->FancyTable($header,$data,$width);
        $pdf->Output("export.pdf","D");
    } else {
        asternic_export_csv($header,$data);
    }
}

//изменение
function recordfile_uri($path) {
    $size = filesize($path);
    $name = basename($path);
    $extension = strtolower(substr(strrchr($name,"."),1));
    // This will set the Content-Type to the appropriate setting for the file
    $ctype ='';
    switch( $extension ) {
        case "WAV":
            $ctype="audio/x-wav";
            break;
        case "wav":
            $ctype="audio/x-wav";
            break;
        case "ulaw":
            $ctype="audio/basic";
            break;
        case "alaw":
            $ctype="audio/x-alaw-basic";
            break;
        case "sln":
            $ctype="audio/x-wav";
            break;
        case "gsm":
            $ctype="audio/x-gsm";
            break;
        case "g729":
            $ctype="audio/x-g729";
            break;
        default: //not downloadable
            // echo ("<b>404 File not found! foo</b>");
            // TODO: what to do if none of the above work?
        break ;
    }

  $fp=fopen($path, "rb");
  if ($size && $ctype && $fp) {
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: audio file");
    header("Content-Type: " . $ctype);
    header("Content-Disposition: attachment; filename=" . $name);
    header("Content-Transfer-Encoding: binary");
    header("Content-length: " . $size);
    $chunksize = 1*(1024*1024);
    while (!feof($fp)) {
        $buffer = fread($fp, $chunksize);
        echo $buffer;
        ob_flush();
        flush();
    }
    fclose($fp);
  }
}
if(isset($_GET['getRec'])){
    recordfile_uri(base64_decode($_GET['getRec']));
    die();
}

?>

Источник, с подробными разъяснениями

FreePBX

Приложения

  • soft/cdr/asternic-cdr-stats.txt
  • Последние изменения: 2016/12/25