base
This commit is contained in:
@@ -0,0 +1,840 @@
|
||||
package TTXReports;
|
||||
#
|
||||
# This module is a part of Trouble Ticket Express package
|
||||
# http://www.troubleticketexpress.com
|
||||
#
|
||||
# COPYRIGHT: 2002-2005, United Web Coders
|
||||
# http://www.unitedwebcoders.com
|
||||
#
|
||||
# $Revision: 224 $
|
||||
# $Date: 2006-07-24 11:32:24 -0400 (Mon, 24 Jul 2006) $
|
||||
#
|
||||
|
||||
$TTXReports::VERSION='2.22';
|
||||
BEGIN {
|
||||
$TTXReports::REVISION = '$Revision: 224 $';
|
||||
if ($TTXReports::REVISION =~ /(\d+)/) {
|
||||
$TTXReports::REVISION = $1;
|
||||
}
|
||||
};
|
||||
|
||||
use strict;
|
||||
use TTXCommon;
|
||||
use TTXConfig;
|
||||
require TTXUser;
|
||||
require TTXBarChart;
|
||||
require TTXDictionary;
|
||||
my @months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
|
||||
|
||||
# =================================================================== checkpoint
|
||||
|
||||
sub checkpoint {
|
||||
my $cfg = $_[0];
|
||||
my $grantlist = $cfg->get('grant.reports');
|
||||
if ($grantlist ne undef) {
|
||||
my $uid = $cfg->get('_USER')->get('login');
|
||||
if (!grep(/^$uid$/, split(/,/,$grantlist))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
# ========================================================================= main
|
||||
|
||||
sub main {
|
||||
my ($cfg, $query, $data) = @_;
|
||||
return 'helpdesk' if !checkpoint($cfg);
|
||||
for (my $i = 0; $i < 12; ++$i) {
|
||||
$months[$i] = TTXDictionary::translate($months[$i]);
|
||||
}
|
||||
my $basewidth = $cfg->get('HTMLBASEWIDTH') || 700;
|
||||
my %rtitle = (
|
||||
overview => 'Overview',
|
||||
operperf => 'Operator Performance',
|
||||
aging360 => 'Ticket Aging',
|
||||
aging => 'Hot Tickets',
|
||||
slevel => 'Service Level'
|
||||
);
|
||||
$data->{PAGEHEADING} = '[%Reports%]';
|
||||
$data->{REPORTQUERY} =<<EOT;
|
||||
<table cellpadding=5>
|
||||
<tr>
|
||||
<td align=left>
|
||||
<select name=rtype size=1>
|
||||
EOT
|
||||
if ($query->param('rtype') eq undef) {
|
||||
$data->{REPORTQUERY} .= '<option value="">-- [%Select Report%] --</option>';
|
||||
}
|
||||
foreach my $rtype ('overview', 'operperf', 'aging360', 'aging', 'slevel') {
|
||||
next if $rtype eq 'slevel' && !$cfg->get('opersla');
|
||||
$data->{REPORTQUERY} .= "<option value=$rtype";
|
||||
$data->{REPORTQUERY} .= ' selected' if $query->param('rtype') eq $rtype;
|
||||
$data->{REPORTQUERY} .= '>[%'.$rtitle{$rtype}.'%]</option>'."\n";
|
||||
}
|
||||
$data->{REPORTQUERY} .=<<EOT;
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
EOT
|
||||
return undef if !$query->param('do');
|
||||
$query->param(-name => 'do', -value => '');
|
||||
my $rtype = TTXCommon::cleanit($query, 'rtype');
|
||||
if ($rtype eq undef) {
|
||||
$data->{REPORT} = "<center><b>[%No report selected%]</b><br><br></center>\n";
|
||||
} elsif ($rtype eq 'overview') {
|
||||
$cfg->set('_NOCOOKIE',1);
|
||||
overview($cfg, $query, $data);
|
||||
} elsif ($rtype eq 'operperf') {
|
||||
$cfg->set('_NOCOOKIE',1);
|
||||
operperf($cfg, $query, $data);
|
||||
} elsif ($rtype eq 'aging360') {
|
||||
$cfg->set('_NOCOOKIE',1);
|
||||
aging360($cfg, $query, $data);
|
||||
} elsif ($rtype eq 'aging') {
|
||||
$cfg->set('_NOCOOKIE',1);
|
||||
aging($cfg, $query, $data);
|
||||
} elsif ($rtype eq 'slevel') {
|
||||
$cfg->set('_NOCOOKIE',1);
|
||||
slevel($cfg, $query, $data);
|
||||
} else {
|
||||
$data->{REPORT} = '<center><b>[%Unknown report requested%]</b><br><br></center>'."\n";
|
||||
}
|
||||
$data->{REPORT} = "<tr><td align=left>\n".$data->{REPORT}."</td></tr>\n";
|
||||
return undef;
|
||||
}
|
||||
# ===================================================================== overview
|
||||
|
||||
sub overview {
|
||||
my ($cfg, $query, $data) = @_;
|
||||
my $tmcuts = cuttimes($cfg);
|
||||
my $img = $cfg->get('imgurl')."/dot.gif";
|
||||
my @fltr;
|
||||
my %drange = (
|
||||
fld => 'created',
|
||||
stm => $tmcuts->{trail}->{months12}->{start},
|
||||
etm => $tmcuts->{today}->{stop}
|
||||
);
|
||||
$| = 1;
|
||||
my $tickets = TTXCommon::dbtik();
|
||||
my $tmp = $cfg->set('hideoldsolved', '');
|
||||
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
|
||||
$cfg->set('hideoldsolved', $tmp);
|
||||
$tmcuts->{total}->{cnt} = $browser->{total};
|
||||
my $m12stop = $tmcuts->{trail}->{months12}->{stop};
|
||||
my $m12idx = 0;
|
||||
my $m12idxstop = $tmcuts->{trail}->{months12}->{0}->{stop};
|
||||
my $m12m = $tmcuts->{trail}->{months12}->{0};
|
||||
my $w12stop = $tmcuts->{trail}->{weeks12}->{stop};
|
||||
my $w12start = $tmcuts->{trail}->{weeks12}->{start};
|
||||
my $w12idx = 0;
|
||||
my $w12idxstop = $tmcuts->{trail}->{weeks12}->{start} + 7*24*3600;
|
||||
my $w12bars = [];
|
||||
$w12bars->[0]->{stop} = $w12idxstop;
|
||||
my $d30stop = $tmcuts->{trail}->{days30}->{stop};
|
||||
my $d30start = $tmcuts->{trail}->{days30}->{start};
|
||||
my $d30idx = 0;
|
||||
my $d30idxstop = $tmcuts->{trail}->{days30}->{start} + 24*3600;
|
||||
my $d30bars = [];
|
||||
$d30bars->[0]->{stop} = $d30idxstop;
|
||||
foreach my $tid (@{$browser->{list}}) {
|
||||
my $t = $tickets->ticket($tid, 1);
|
||||
next if $t eq undef;
|
||||
my $tm = $t->{open};
|
||||
if ($tm < $m12stop) {
|
||||
while ($tm >= $m12idxstop) {
|
||||
++$m12idx;
|
||||
$m12idxstop = $tmcuts->{trail}->{months12}->{$m12idx}->{stop};
|
||||
$m12m = $tmcuts->{trail}->{months12}->{$m12idx};
|
||||
print "\n"; #keep browser alive
|
||||
}
|
||||
++$m12m->{cnt};
|
||||
} else {
|
||||
++$tmcuts->{thismonth}->{cnt};
|
||||
}
|
||||
if ($tm >= $w12start) {
|
||||
while ($tm >= $w12idxstop && $w12idx < 12) {
|
||||
++$w12idx;
|
||||
last if $w12idx > 11;
|
||||
$w12idxstop += 7*24*3600;
|
||||
$w12bars->[$w12idx]->{stop} = $w12idxstop;
|
||||
}
|
||||
if ($w12idx < 12) {
|
||||
++$w12bars->[$w12idx]->{val};
|
||||
} else {
|
||||
++$tmcuts->{thisweek}->{cnt};
|
||||
}
|
||||
}
|
||||
if ($tm >= $d30start) {
|
||||
while ($tm >= $d30idxstop && $d30idx < 30) {
|
||||
++$d30idx;
|
||||
last if $d30idx > 29;
|
||||
$d30idxstop += 24*3600;
|
||||
$d30bars->[$d30idx]->{stop} = $d30idxstop;
|
||||
}
|
||||
if ($d30idx < 30) {
|
||||
++$d30bars->[$d30idx]->{val};
|
||||
} else {
|
||||
++$tmcuts->{today}->{cnt};
|
||||
}
|
||||
}
|
||||
#
|
||||
# Purge ticket out of memory
|
||||
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
|
||||
# If using Standard (palin text database) Edition the consequent
|
||||
# $tickets->save would destroy the database.
|
||||
#
|
||||
delete $tickets->{TICKETS}->{$tid};
|
||||
}
|
||||
while ($w12idx < 12) {
|
||||
++$w12idx;
|
||||
last if $w12idx > 11;
|
||||
$w12idxstop += 7*24*3600;
|
||||
$w12bars->[$w12idx]->{stop} = $w12idxstop;
|
||||
}
|
||||
while ($d30idx < 30) {
|
||||
++$d30idx;
|
||||
last if $d30idx > 29;
|
||||
$d30idxstop += 24*3600;
|
||||
$d30bars->[$d30idx]->{stop} = $d30idxstop;
|
||||
}
|
||||
my $bars = [];
|
||||
for (my $i=0; $i < 12; ++$i) {
|
||||
$bars->[$i]->{lbl} = $months[$tmcuts->{trail}->{months12}->{$i}->{idx}];
|
||||
$bars->[$i]->{val} = $tmcuts->{trail}->{months12}->{$i}->{cnt};
|
||||
}
|
||||
my $chart = TTXBarChart::vbar($bars, 25, 125, 'red');
|
||||
for (my $i=0; $i < 12; ++$i) {
|
||||
$w12bars->[$i]->{lbl} = $months[(gmtime($w12bars->[$i]->{stop} - 6*3600 + 60 * int($cfg->get('timezone'))))[4]];
|
||||
}
|
||||
for (my $i=11; $i > 0; --$i) {
|
||||
if ($w12bars->[$i]->{lbl} eq $w12bars->[$i-1]->{lbl}) {
|
||||
$w12bars->[$i]->{lbl} = '';
|
||||
}
|
||||
}
|
||||
my $chart1 = TTXBarChart::vbar($w12bars, 25, 125, 'blue');
|
||||
for (my $i=0; $i < 30; ++$i) {
|
||||
$d30bars->[$i]->{lbl} = (gmtime($d30bars->[$i]->{stop} - 3600+ 60 * int($cfg->get('timezone'))))[3];
|
||||
}
|
||||
my $chartd30 = TTXBarChart::vbar($d30bars, 22, 125, 'green', 0.5);
|
||||
my $newtoday = int $tmcuts->{today}->{cnt};
|
||||
my $newthisweek = int $tmcuts->{thisweek}->{cnt};
|
||||
my $newthismonth = int $tmcuts->{thismonth}->{cnt};
|
||||
$data->{REPORT} .=<<EOT;
|
||||
<table cellpadding=0 cellspacing=0>
|
||||
<tr>
|
||||
<td align=left colspan=3>
|
||||
<b>[%New tickets%]</b>
|
||||
<table cellpadding=0 cellspacing=1>
|
||||
<tr>
|
||||
<td align=left><font color=gray><b>[%Today%]</b></font></td>
|
||||
<td align=right><font color=green><b>$newtoday</b></font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left><font color=gray><b>[%This Week%]</b></font></td>
|
||||
<td align=right><font color=blue><b>$newthisweek</b></font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=left><font color=gray><b>[%This Month%] </b></font></td>
|
||||
<td align=right><font color=red><b>$newthismonth</b></font></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center valign=top>
|
||||
<table cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=center>
|
||||
<b>[%New tickets, last 12 months%]</b>
|
||||
<br><br>
|
||||
$chart
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td><img src="$img" width=17 height=1 /></td>
|
||||
<td align=center valign=top>
|
||||
<table cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=center>
|
||||
<b>[%New tickets, last 12 weeks%]</b>
|
||||
<br><br>
|
||||
$chart1
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=3><img src="$img" width=1 height=10 /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center valign=top colspan=3>
|
||||
<table cellpadding=1 cellspacing=0 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=center>
|
||||
<br class=tiny>
|
||||
<b>[%New tickets, last 30 days%]</b>
|
||||
<br><br>
|
||||
$chartd30
|
||||
<br><br class=tiny>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
EOT
|
||||
}
|
||||
# ===================================================================== operperf
|
||||
|
||||
sub operperf {
|
||||
my ($cfg, $query, $data) = @_;
|
||||
my $tmcuts = cuttimes($cfg);
|
||||
my $img = $cfg->get('imgurl')."/dot.gif";
|
||||
my @fltr = ({col => 'status', expr => '^(CLS|WFR)$'});
|
||||
my %drange = (
|
||||
fld => 'updated',
|
||||
stm => $tmcuts->{trail}->{months12}->{start},
|
||||
etm => $tmcuts->{today}->{stop}
|
||||
);
|
||||
$| = 1;
|
||||
my $tickets = TTXCommon::dbtik();
|
||||
my $tmp = $cfg->set('hideoldsolved', '');
|
||||
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
|
||||
$cfg->set('hideoldsolved', $tmp);
|
||||
$tmcuts->{total}->{cnt} = $browser->{total};
|
||||
my $opercnts = {};
|
||||
|
||||
my $m12stop = $tmcuts->{trail}->{months12}->{stop};
|
||||
my $w12stop = $tmcuts->{trail}->{weeks12}->{stop};
|
||||
my $w12start = $tmcuts->{trail}->{weeks12}->{start};
|
||||
my $d30stop = $tmcuts->{trail}->{days30}->{stop};
|
||||
my $d30start = $tmcuts->{trail}->{days30}->{start};
|
||||
my $tcnt = 0;
|
||||
foreach my $tid (@{$browser->{list}}) {
|
||||
if (!$tcnt) {
|
||||
print "\n";
|
||||
$tcnt = 100;
|
||||
}
|
||||
--$tcnt;
|
||||
my $t = $tickets->ticket($tid, 1);
|
||||
next if $t eq undef;
|
||||
my $oper = $t->{oper};
|
||||
next if $oper eq undef;
|
||||
my $tm = $t->{updated};
|
||||
if ($tm < $m12stop) {
|
||||
++$opercnts->{$oper}->{m12};
|
||||
} else {
|
||||
++$opercnts->{$oper}->{thismonth};
|
||||
}
|
||||
if ($tm >= $w12start) {
|
||||
if ($tm < $w12stop) {
|
||||
++$opercnts->{$oper}->{w12};
|
||||
} else {
|
||||
++$opercnts->{$oper}->{thisweek};
|
||||
}
|
||||
}
|
||||
if ($tm >= $d30start) {
|
||||
if ($tm < $d30stop) {
|
||||
++$opercnts->{$oper}->{d30};
|
||||
} else {
|
||||
++$opercnts->{$oper}->{today};
|
||||
}
|
||||
}
|
||||
#
|
||||
# Purge ticket out of memory
|
||||
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
|
||||
# If using Standard (palin text database) Edition the consequent
|
||||
# $tickets->save would destroy the database.
|
||||
#
|
||||
delete $tickets->{TICKETS}->{$tid};
|
||||
}
|
||||
my $bars = [];
|
||||
my @operlist = TTXUser::list();
|
||||
@operlist = sort @operlist;
|
||||
my $i = 0;
|
||||
foreach my $oper (@operlist) {
|
||||
$bars->[$i]->{lbl} = $oper;
|
||||
$bars->[$i]->{val} = 0;
|
||||
if ($opercnts->{$oper} ne undef) {
|
||||
$bars->[$i]->{val} = $opercnts->{$oper}->{m12};
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
my $chart = TTXBarChart::hbar($bars, 18, 125, 'red', 0.8);
|
||||
$i = 0;
|
||||
foreach my $oper (@operlist) {
|
||||
$bars->[$i]->{lbl} = $oper;
|
||||
$bars->[$i]->{val} = 0;
|
||||
if ($opercnts->{$oper} ne undef) {
|
||||
$bars->[$i]->{val} = $opercnts->{$oper}->{w12};
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
my $chart1 = TTXBarChart::hbar($bars, 18, 125, 'blue', 0.8);
|
||||
$i = 0;
|
||||
foreach my $oper (@operlist) {
|
||||
$bars->[$i]->{lbl} = $oper;
|
||||
$bars->[$i]->{val} = 0;
|
||||
if ($opercnts->{$oper} ne undef) {
|
||||
$bars->[$i]->{val} = $opercnts->{$oper}->{d30};
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
my $chartd30 = TTXBarChart::hbar($bars, 18, 125, 'green', 0.8);
|
||||
$i = 0;
|
||||
foreach my $oper (@operlist) {
|
||||
$bars->[$i]->{lbl} = $oper;
|
||||
$bars->[$i]->{val} = 0;
|
||||
if ($opercnts->{$oper} ne undef) {
|
||||
$bars->[$i]->{val} = $opercnts->{$oper}->{today};
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
my $charttoday = TTXBarChart::hbar($bars, 18, 125, 'green', 0.8);
|
||||
$i = 0;
|
||||
foreach my $oper (@operlist) {
|
||||
$bars->[$i]->{lbl} = $oper;
|
||||
$bars->[$i]->{val} = 0;
|
||||
if ($opercnts->{$oper} ne undef) {
|
||||
$bars->[$i]->{val} = $opercnts->{$oper}->{thisweek};
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
my $chartthisweek = TTXBarChart::hbar($bars, 18, 125, 'blue', 0.8);
|
||||
$i = 0;
|
||||
foreach my $oper (@operlist) {
|
||||
$bars->[$i]->{lbl} = $oper;
|
||||
$bars->[$i]->{val} = 0;
|
||||
if ($opercnts->{$oper} ne undef) {
|
||||
$bars->[$i]->{val} = $opercnts->{$oper}->{thismonth};
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
my $chartthismonth = TTXBarChart::hbar($bars, 18, 125, 'red', 0.8);
|
||||
$data->{REPORT} .=<<EOT;
|
||||
<br>
|
||||
<table cellpadding=0 cellspacing=0>
|
||||
<tr>
|
||||
<td align=center valign=top>
|
||||
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=left>
|
||||
<center><b>[%Answers, this month%]</b></center>
|
||||
<br>
|
||||
$chartthismonth
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td><img src="$img" width=17 height=1 /></td>
|
||||
<td align=center valign=top>
|
||||
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=left>
|
||||
<center><b>[%Answers, this week%]</b></center>
|
||||
<br>
|
||||
$chartthisweek
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td><img src="$img" width=17 height=1 /></td>
|
||||
<td align=center valign=top>
|
||||
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=left>
|
||||
<center><b>[%Answers, today%]</b></center>
|
||||
<br>
|
||||
$charttoday
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=5><img src="$img" width=1 height=10 /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center valign=top>
|
||||
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=left>
|
||||
<center><b>[%Answers, last 12 months%]</b></center>
|
||||
<br>
|
||||
$chart
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td><img src="$img" width=17 height=1 /></td>
|
||||
<td align=center valign=top>
|
||||
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=left>
|
||||
<center><b>[%Answers, last 12 weeks%]</b></center>
|
||||
<br>
|
||||
$chart1
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td><img src="$img" width=17 height=1 /></td>
|
||||
<td align=center valign=top>
|
||||
<table width="100%" cellpadding=10 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=left>
|
||||
<center><b>[%Answers, last 30 days%]</b></center>
|
||||
<br>
|
||||
$chartd30
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br class=tiny />
|
||||
EOT
|
||||
}
|
||||
# ======================================================================= slevel
|
||||
|
||||
sub slevel {
|
||||
my ($cfg, $query, $data) = @_;
|
||||
my $tmcuts = cuttimes($cfg);
|
||||
my $img = $cfg->get('imgurl')."/dot.gif";
|
||||
my @fltr = ({col => 'status', expr => '^CLS$'});
|
||||
my %drange = (
|
||||
fld => 'solved',
|
||||
stm => $tmcuts->{trail}->{months12}->{11}->{start},
|
||||
etm => $tmcuts->{trail}->{months12}->{11}->{stop},
|
||||
# etm => $tmcuts->{lastweek}->{stop}
|
||||
);
|
||||
$| = 1;
|
||||
my $tickets = TTXCommon::dbtik();
|
||||
my $tmp = $cfg->set('hideoldsolved', '');
|
||||
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
|
||||
my $opercnts = {};
|
||||
my $tcnt = 0;
|
||||
foreach my $tid (@{$browser->{list}}) {
|
||||
if (!$tcnt) {
|
||||
print "\n";
|
||||
$tcnt = 100;
|
||||
}
|
||||
--$tcnt;
|
||||
my $t = $tickets->ticket($tid, 1);
|
||||
next if $t eq undef;
|
||||
my $oper = $t->{oper};
|
||||
next if $oper eq undef; # just to make sure
|
||||
if (!defined $opercnts->{$oper}) {
|
||||
my $u = TTXUser->new($oper);
|
||||
next if $u eq undef;
|
||||
$opercnts->{$oper}->{sla} = int($u->{sla}) * 3600;
|
||||
}
|
||||
++$opercnts->{$oper}->{lm}->{total};
|
||||
++$opercnts->{$oper}->{lm}->{jit} if $opercnts->{$oper}->{sla} > ($t->{closed} - $t->{open});
|
||||
#
|
||||
# Purge ticket out of memory
|
||||
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
|
||||
# If using Standard (palin text database) Edition the consequent
|
||||
# $tickets->save would destroy the database.
|
||||
#
|
||||
delete $tickets->{TICKETS}->{$tid};
|
||||
}
|
||||
%drange = (
|
||||
fld => 'solved',
|
||||
stm => $tmcuts->{lastweek}->{start},
|
||||
etm => $tmcuts->{lastweek}->{stop},
|
||||
);
|
||||
$browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
|
||||
$cfg->set('hideoldsolved', $tmp);
|
||||
foreach my $tid (@{$browser->{list}}) {
|
||||
if (!$tcnt) {
|
||||
print "\n";
|
||||
$tcnt = 100;
|
||||
}
|
||||
--$tcnt;
|
||||
my $t = $tickets->ticket($tid, 1);
|
||||
next if $t eq undef;
|
||||
my $oper = $t->{oper};
|
||||
next if $oper eq undef; # just to make sure
|
||||
if (!defined $opercnts->{$oper}) {
|
||||
my $u = TTXUser->new($oper);
|
||||
next if $u eq undef;
|
||||
$opercnts->{$oper}->{sla} = int($u->{sla}) * 3600;
|
||||
}
|
||||
++$opercnts->{$oper}->{lw}->{total};
|
||||
++$opercnts->{$oper}->{lw}->{jit} if $opercnts->{$oper}->{sla} > ($t->{closed} - $t->{open});
|
||||
#
|
||||
# Purge ticket out of memory
|
||||
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
|
||||
# If using Standard (palin text database) Edition the consequent
|
||||
# $tickets->save would destroy the database.
|
||||
#
|
||||
delete $tickets->{TICKETS}->{$tid};
|
||||
}
|
||||
|
||||
$data->{REPORT} .=<<EOT;
|
||||
<center>
|
||||
<b>[%Service Level Report%]</b><br>
|
||||
<span class=sm>([%percentage of tickets solved within SLA time%])</span>
|
||||
<br><br>
|
||||
<table cellpadding=3 style="border-style:solid;border-color:gray;border-width:1px;">
|
||||
<tr>
|
||||
<td align=center>
|
||||
<b>[%Operator%]</b>
|
||||
</td>
|
||||
<td align=center>
|
||||
<b>[%Last Week%]</b>
|
||||
</td>
|
||||
<td align=center>
|
||||
<b>[%Last Month%]</b>
|
||||
</td>
|
||||
</tr>
|
||||
EOT
|
||||
foreach my $oper (sort keys %{$opercnts}) {
|
||||
$data->{REPORT} .= "<tr>\n<td align=left>$oper</td><td align=right>".
|
||||
($opercnts->{$oper}->{lw}->{total} ?
|
||||
int(100*$opercnts->{$oper}->{lw}->{jit}/$opercnts->{$oper}->{lw}->{total}).'%':'-' ).
|
||||
"</td>\n<td align=right>".
|
||||
($opercnts->{$oper}->{lm}->{total} ?
|
||||
int(100*$opercnts->{$oper}->{lm}->{jit}/$opercnts->{$oper}->{lm}->{total}).'%':'-' ).
|
||||
"</td>\n</tr>\n";
|
||||
}
|
||||
$data->{REPORT} .=<<EOT;
|
||||
|
||||
</table>
|
||||
</center>
|
||||
<br class=tiny />
|
||||
EOT
|
||||
}
|
||||
# ===================================================================== aging360
|
||||
|
||||
sub aging360 {
|
||||
my ($cfg, $query, $data) = @_;
|
||||
my @tmlst = (
|
||||
'0-24 [%hrs%]',
|
||||
'24-48 [%hrs%]',
|
||||
'2-7 [%days%]',
|
||||
'7-30 [%days%]',
|
||||
'30+ [%days%]'
|
||||
);
|
||||
my %tmcuts = (
|
||||
$tmlst[0] => 24*3600,
|
||||
$tmlst[1] => 48*3600,
|
||||
$tmlst[2] => 168*3600,
|
||||
$tmlst[3] => 720*3600,
|
||||
$tmlst[4] => 0
|
||||
);
|
||||
my $img = $cfg->get('imgurl')."/dot.gif";
|
||||
my @fltr = (
|
||||
{ 'col' => 'status', 'expr' => '^CLS$' }
|
||||
);
|
||||
my $now = time();
|
||||
my %drange = (
|
||||
fld => 'created',
|
||||
stm => int ($now - 365*24*3600),
|
||||
etm => $now
|
||||
);
|
||||
$| = 1;
|
||||
my $tickets = TTXCommon::dbtik();
|
||||
my $tmp = $cfg->set('hideoldsolved', '');
|
||||
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
|
||||
$cfg->set('hideoldsolved', $tmp);
|
||||
my @bardata;
|
||||
my $heartbeat = 0;
|
||||
foreach my $tid (@{$browser->{list}}) {
|
||||
my $t = $tickets->ticket($tid, 1);
|
||||
next if $t eq undef;
|
||||
my $tm = $t->{closed} - $t->{open};
|
||||
my $i = 0;
|
||||
foreach my $cut (@tmlst) {
|
||||
last if $tm < $tmcuts{$cut} || !$tmcuts{$cut};
|
||||
++$i;
|
||||
}
|
||||
++$bardata[$i]->{val};
|
||||
++$heartbeat;
|
||||
if ($heartbeat > 100) {
|
||||
print "\n"; #keep browser alive
|
||||
$heartbeat = 0;
|
||||
}
|
||||
#
|
||||
# Purge ticket out of memory
|
||||
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
|
||||
# If using Standard (palin text database) Edition the consequent
|
||||
# $tickets->save would destroy the database.
|
||||
#
|
||||
delete $tickets->{TICKETS}->{$tid};
|
||||
}
|
||||
my $i = 0;
|
||||
foreach my $cut (@tmlst) {
|
||||
$bardata[$i]->{lbl} = $cut;
|
||||
++$i;
|
||||
}
|
||||
my $chart = TTXBarChart::hbar(\@bardata, 18, 125, 'red', 0.8, 1);
|
||||
$data->{REPORT} .=<<EOT;
|
||||
<table cellpadding=0 cellspacing=0 width="100%">
|
||||
<tr>
|
||||
<td align=center>
|
||||
<b>[%Breakdown of time to close a ticket%]</b><br />
|
||||
<span class=sm>([%tickets submitted during last 365 days%])</span>
|
||||
<br /><br />
|
||||
$chart
|
||||
<br /><br />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
EOT
|
||||
}
|
||||
# ======================================================================== aging
|
||||
|
||||
sub aging {
|
||||
my ($cfg, $query, $data) = @_;
|
||||
my @tmlst = (
|
||||
'0-24 [%hrs%]',
|
||||
'24-48 [%hrs%]',
|
||||
'2-7 [%days%]',
|
||||
'7-30 [%days%]',
|
||||
'30+ [%days%]'
|
||||
);
|
||||
my %tmcuts = (
|
||||
$tmlst[0] => 24*3600,
|
||||
$tmlst[1] => 48*3600,
|
||||
$tmlst[2] => 168*3600,
|
||||
$tmlst[3] => 720*3600,
|
||||
$tmlst[4] => 0
|
||||
);
|
||||
my $img = $cfg->get('imgurl')."/dot.gif";
|
||||
my @fltr = (
|
||||
{ 'col' => 'status', 'expr' => '^(PND|OPN)$' }
|
||||
);
|
||||
my $now = time();
|
||||
my %drange = (
|
||||
fld => 'created',
|
||||
stm => int ($now - 365*24*3600),
|
||||
etm => $now
|
||||
);
|
||||
$| = 1;
|
||||
my $tickets = TTXCommon::dbtik();
|
||||
my $tmp = $cfg->set('hideoldsolved', '');
|
||||
my $browser = $tickets->list(0, 999999, 'open', 'A', \@fltr, \%drange);
|
||||
$cfg->set('hideoldsolved', $tmp);
|
||||
my @bardata;
|
||||
my $heartbeat = 0;
|
||||
foreach my $tid (@{$browser->{list}}) {
|
||||
my $t = $tickets->ticket($tid, 1);
|
||||
next if $t eq undef;
|
||||
my $tm = $now - $t->{open};
|
||||
my $i = 0;
|
||||
foreach my $cut (@tmlst) {
|
||||
last if $tm < $tmcuts{$cut} || !$tmcuts{$cut};
|
||||
++$i;
|
||||
}
|
||||
++$bardata[$i]->{val};
|
||||
++$heartbeat;
|
||||
if ($heartbeat > 100) {
|
||||
print "\n"; #keep browser alive
|
||||
$heartbeat = 0;
|
||||
}
|
||||
#
|
||||
# Purge ticket out of memory
|
||||
# This is pretty safe if using SQL Edition (both MySQL and SQL Server).
|
||||
# If using Standard (palin text database) Edition the consequent
|
||||
# $tickets->save would destroy the database.
|
||||
#
|
||||
delete $tickets->{TICKETS}->{$tid};
|
||||
}
|
||||
my $i = 0;
|
||||
foreach my $cut (@tmlst) {
|
||||
$bardata[$i]->{lbl} = $cut;
|
||||
++$i;
|
||||
}
|
||||
my $chart = TTXBarChart::hbar(\@bardata, 18, 125, 'red', 0.8, 1);
|
||||
$data->{REPORT} .=<<EOT;
|
||||
<table cellpadding=0 cellspacing=0 width="100%">
|
||||
<tr>
|
||||
<td align=center>
|
||||
<b>[%Hot Tickets%]</b><br />
|
||||
<span class=sm>([%tickets in open or pending state%])</span>
|
||||
<br /><br />
|
||||
$chart
|
||||
<br /><br />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
EOT
|
||||
}
|
||||
# ===================================================================== cuttimes
|
||||
|
||||
sub cuttimes {
|
||||
my $cfg = $_[0];
|
||||
my $cuts;
|
||||
my $now = time() + 60 * int($cfg->get('timezone'));
|
||||
$cuts->{total}->{start} = 0;
|
||||
$cuts->{total}->{stop} = $now;
|
||||
$cuts->{yesterday}->{stop} = $now - ($now % (3600 * 24));
|
||||
$cuts->{yesterday}->{start} = $cuts->{yesterday}->{stop} - (3600 * 24);
|
||||
my ($sec,$min,$hour,$mday,$mon,$year, $wday) = gmtime($now);
|
||||
--$wday;
|
||||
$wday = 6 if $wday < 0; # Sunday is last week day
|
||||
# $wdaytoday = $wday;
|
||||
$cuts->{lastweek}->{stop} = $cuts->{yesterday}->{stop} - $wday * (3600 * 24);
|
||||
$cuts->{lastweek}->{start} = $cuts->{lastweek}->{stop} - (7 * 3600 * 24);
|
||||
$cuts->{thisweek}->{start} = $cuts->{lastweek}->{stop}; # current week
|
||||
$cuts->{thisweek}->{stop} = $now;
|
||||
$cuts->{lastmonth}->{stop} = $cuts->{yesterday}->{stop} - ($mday - 1) * (3600 * 24);
|
||||
$cuts->{thismonth}->{start} = $cuts->{lastmonth}->{stop};
|
||||
$cuts->{thismonth}->{stop} = $now;
|
||||
$cuts->{today}->{start} = $cuts->{yesterday}->{stop};
|
||||
$cuts->{today}->{stop} = $cuts->{today}->{start} + (3600 * 24);
|
||||
my ($sec1,$min1,$hour1,$mday1,$mon1,$year1, $wday1) = gmtime($cuts->{month}->{stop} - 3600);
|
||||
$cuts->{lastmonth}->{start} = $cuts->{lastmonth}->{stop} - $mday1 * (3600 * 24);
|
||||
foreach my $col ('today', 'yesterday', 'lastweek', 'lastmonth', 'thismonth', 'thisweek') {
|
||||
$cuts->{$col}->{start} -= 60 * int($cfg->get('timezone'));
|
||||
$cuts->{$col}->{stop} -= 60 * int($cfg->get('timezone'));
|
||||
}
|
||||
$cuts->{Mon}->{start} = $cuts->{lastweek}->{stop};
|
||||
$cuts->{Mon}->{stop} = $cuts->{Mon}->{start} + (3600 * 24);
|
||||
my $priorday = 'Mon';
|
||||
foreach my $day ('Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun') {
|
||||
$cuts->{$day}->{stop} = $cuts->{$priorday}->{stop} + (3600 * 24);
|
||||
$cuts->{$day}->{start} = $cuts->{$day}->{stop} - (3600 * 24);
|
||||
$priorday = $day;
|
||||
}
|
||||
#
|
||||
# Trailings
|
||||
#
|
||||
# 30 Days
|
||||
#
|
||||
$cuts->{trail}->{days30}->{stop} = $cuts->{yesterday}->{stop};
|
||||
$cuts->{trail}->{days30}->{start} = $cuts->{trail}->{days30}->{stop} - 30 * 24 * 3600;
|
||||
#
|
||||
# 12 weeks
|
||||
#
|
||||
$cuts->{trail}->{weeks12}->{stop} = $cuts->{lastweek}->{stop};
|
||||
$cuts->{trail}->{weeks12}->{start} = $cuts->{trail}->{weeks12}->{stop} - 12 * 7 * 24 * 3600;
|
||||
#
|
||||
# 12 months
|
||||
#
|
||||
$cuts->{trail}->{months12}->{stop} = $cuts->{lastmonth}->{stop};
|
||||
for (my $i=11; $i >= 0; --$i) {
|
||||
if ($i == 11) {
|
||||
$cuts->{trail}->{months12}->{11}->{stop} = $cuts->{trail}->{months12}->{stop};
|
||||
} else {
|
||||
$cuts->{trail}->{months12}->{$i}->{stop} = $cuts->{trail}->{months12}->{($i+1)}->{start};
|
||||
}
|
||||
my ($md,$mn) = (gmtime($cuts->{trail}->{months12}->{$i}->{stop} - 3600 + 60 * int($cfg->get('timezone'))))[3,4];
|
||||
$cuts->{trail}->{months12}->{$i}->{start} = $cuts->{trail}->{months12}->{$i}->{stop} - $md * 3600 * 24;
|
||||
$cuts->{trail}->{months12}->{$i}->{idx} = $mn;
|
||||
}
|
||||
$cuts->{trail}->{months12}->{start} = $cuts->{trail}->{months12}->{0}->{start};
|
||||
return $cuts;
|
||||
}
|
||||
|
||||
1;
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user