Files
scripts/Perl OTRS/Kernel/Modules/AgentStatistics.pm
2024-10-14 00:08:40 +02:00

1093 lines
36 KiB
Perl

# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::Modules::AgentStatistics;
use strict;
use warnings;
use List::Util qw( first );
use Kernel::System::VariableCheck qw(:all);
use Kernel::Language qw(Translatable);
our $ObjectManagerDisabled = 1;
sub new {
my ( $Type, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
for my $NeededData (qw( UserID Subaction AccessRo SessionID ))
{
if ( !$Param{$NeededData} ) {
$LayoutObject->FatalError(
Message => $LayoutObject->{LanguageObject}->Translate( 'Parameter %s is missing.', $NeededData ),
);
}
$Self->{$NeededData} = $Param{$NeededData};
}
# AccessRw controls the adding/editing of statistics.
for my $Param (qw( AccessRw RequestedURL )) {
if ( $Param{$Param} ) {
$Self->{$Param} = $Param{$Param};
}
}
return $Self;
}
sub Run {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# set breadcrumbpath for overview screen and it will be used as base for other screens
@{ $Self->{BreadcrumbPath} } = (
{
Name =>
$LayoutObject->{LanguageObject}->Translate('Statistics Overview'),
Link => 'AgentStatistics;Subaction=Overview',
}
);
my $Subaction = $Self->{Subaction};
my %RoSubactions = (
Overview => 'OverviewScreen',
View => 'ViewScreen',
Run => 'RunAction',
);
if ( $RoSubactions{$Subaction} ) {
if ( !$Self->{AccessRo} ) {
return $LayoutObject->NoPermission( WithHeader => 'yes' );
}
my $Method = $RoSubactions{$Subaction};
return $Self->$Method();
}
my %RwSubactions = (
Add => 'AddScreen',
AddAction => 'AddAction',
Edit => 'EditScreen',
EditAction => 'EditAction',
Import => 'ImportScreen',
ImportAction => 'ImportAction',
ExportAction => 'ExportAction',
DeleteAction => 'DeleteAction',
ExportAction => 'ExportAction',
GeneralSpecificationsWidgetAJAX => 'GeneralSpecificationsWidgetAJAX',
);
if ( $RwSubactions{$Subaction} ) {
if ( !$Self->{AccessRw} ) {
return $LayoutObject->NoPermission( WithHeader => 'yes' );
}
my $Method = $RwSubactions{$Subaction};
return $Self->$Method();
}
# No (known) subaction?
return $LayoutObject->ErrorScreen(
Message => Translatable('Invalid Subaction.'),
);
}
sub OverviewScreen {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# Get Params
$Param{SearchPageShown} = $ConfigObject->Get('Stats::SearchPageShown') || 50;
$Param{SearchLimit} = $ConfigObject->Get('Stats::SearchLimit') || 1000;
$Param{OrderBy} = $ParamObject->GetParam( Param => 'OrderBy' ) || 'ID';
$Param{Direction} = $ParamObject->GetParam( Param => 'Direction' ) || 'ASC';
$Param{StartHit} = int( $ParamObject->GetParam( Param => 'StartHit' ) || 1 );
# get all Stats from the db
my $Result = $Kernel::OM->Get('Kernel::System::Stats')->GetStatsList(
AccessRw => $Self->{AccessRw},
OrderBy => $Param{OrderBy},
Direction => $Param{Direction},
UserID => $Self->{UserID},
);
if ( $Param{StartHit} > 1 && $Param{StartHit} > scalar @{ $Result || [] } ) {
return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Overview" );
}
my %Order2CSSSort = (
ASC => 'SortAscending',
DESC => 'SortDescending',
);
my %InverseSorting = (
ASC => 'DESC',
DESC => 'ASC',
);
$Param{ 'CSSSort' . $Param{OrderBy} } = $Order2CSSSort{ $Param{Direction} };
for my $Type (qw(ID Title Object)) {
$Param{"LinkSort$Type"} = ( $Param{OrderBy} eq $Type ) ? $InverseSorting{ $Param{Direction} } : 'ASC';
}
# build the info
my %Pagination = $LayoutObject->PageNavBar(
Limit => $Param{SearchLimit},
StartHit => $Param{StartHit},
PageShown => $Param{SearchPageShown},
AllHits => $#{$Result} + 1,
Action => 'Action=AgentStatistics;Subaction=Overview',
Link => ";Direction=$Param{Direction};OrderBy=$Param{OrderBy};",
IDPrefix => 'AgentStatisticsOverview'
);
# list result
my $Index = -1;
for ( my $Z = 0; ( $Z < $Param{SearchPageShown} && $Index < $#{$Result} ); $Z++ ) {
$Index = $Param{StartHit} + $Z - 1;
my $StatID = $Result->[$Index];
my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet(
StatID => $StatID,
NoObjectAttributes => 1,
UserID => $Self->{UserID},
);
# get the object name
if ( $Stat->{StatType} eq 'static' ) {
$Stat->{ObjectName} = $Stat->{File};
}
# if no object name is defined use an empty string
$Stat->{ObjectName} ||= '';
$LayoutObject->Block(
Name => 'Result',
Data => {
%$Stat,
AccessRw => $Self->{AccessRw},
},
);
}
# build output
my $Output = $LayoutObject->Header(
Title => Translatable('Overview'),
Area => 'Statistics',
);
$Output .= $LayoutObject->NavigationBar();
$Output .= $LayoutObject->Output(
Data => {
%Pagination,
%Param,
AccessRw => $Self->{AccessRw},
BreadcrumbPath => $Self->{BreadcrumbPath},
},
TemplateFile => 'AgentStatisticsOverview',
);
$Output .= $LayoutObject->Footer();
return $Output;
}
sub ImportScreen {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my %Errors = %{ $Param{Errors} // {} };
my $Output = $LayoutObject->Header(
Title => Translatable('Import'),
Area => 'Statistics',
);
$Output .= $LayoutObject->NavigationBar();
$Output .= $LayoutObject->Output(
TemplateFile => 'AgentStatisticsImport',
Data => {
%Errors,
BreadcrumbPath => $Self->{BreadcrumbPath},
},
);
$Output .= $LayoutObject->Footer();
return $Output;
}
sub ImportAction {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my %Errors;
# challenge token check for write action
$LayoutObject->ChallengeTokenCheck();
my $UploadFile = $ParamObject->GetParam( Param => 'File' );
if ($UploadFile) {
my %UploadStuff = $ParamObject->GetUploadAll(
Param => 'File',
Encoding => 'Raw'
);
if ( $UploadStuff{Content} =~ m{<otrs_stats>}x ) {
my $StatID = $Kernel::OM->Get('Kernel::System::Stats')->Import(
Content => $UploadStuff{Content},
UserID => $Self->{UserID},
);
if ( !$StatID ) {
$Errors{FileServerError} = 'ServerError';
$Errors{FileServerErrorMessage} = Translatable("Statistic could not be imported.");
}
else {
# Redirect to statistic edit page.
return $LayoutObject->Redirect(
OP => "Action=AgentStatistics;Subaction=Edit;StatID=$StatID"
);
}
}
else {
$Errors{FileServerError} = 'ServerError';
$Errors{FileServerErrorMessage} = Translatable("Please upload a valid statistic file.");
}
}
else {
$Errors{FileServerError} = 'ServerError';
$Errors{FileServerErrorMessage} = Translatable("This field is required.");
}
return $Self->ImportScreen( Errors => \%Errors );
}
sub ExportAction {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
$LayoutObject->ChallengeTokenCheck();
my $StatID = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'StatID' );
if ( !$StatID ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Export: Need StatID!'),
);
}
my $ExportFile = $Kernel::OM->Get('Kernel::System::Stats')->Export(
StatID => $StatID,
UserID => $Self->{UserID},
);
return $LayoutObject->Attachment(
Filename => $ExportFile->{Filename},
Content => $ExportFile->{Content},
ContentType => 'text/xml',
);
}
sub DeleteAction {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $StatID = $ParamObject->GetParam( Param => 'StatID' );
if ( !$StatID ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Delete: Get no StatID!'),
);
}
# challenge token check for write action
$LayoutObject->ChallengeTokenCheck();
$Kernel::OM->Get('Kernel::System::Stats')->StatsDelete(
StatID => $StatID,
UserID => $Self->{UserID},
);
return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Overview" );
}
sub EditScreen {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# get param
if ( !( $Param{StatID} = $ParamObject->GetParam( Param => 'StatID' ) ) ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Need StatID!'),
);
}
my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet(
StatID => $Param{StatID},
UserID => $Self->{UserID},
);
my %Frontend;
$Frontend{GeneralSpecificationsWidget}
= $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->GeneralSpecificationsWidget(
StatID => $Stat->{StatID},
UserID => $Self->{UserID},
);
if ( $Stat->{StatType} eq 'dynamic' ) {
$Frontend{XAxisWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->XAxisWidget(
Stat => $Stat,
UserID => $Self->{UserID},
);
$Frontend{YAxisWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->YAxisWidget(
Stat => $Stat,
UserID => $Self->{UserID},
);
$Frontend{RestrictionsWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->RestrictionsWidget(
Stat => $Stat,
UserID => $Self->{UserID},
);
$Frontend{PreviewWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->PreviewWidget(
Stat => $Stat,
UserID => $Self->{UserID},
);
}
my $Output = $LayoutObject->Header(
Title => Translatable('Edit'),
Area => 'Statistics',
);
$Output .= $LayoutObject->NavigationBar();
$Output .= $LayoutObject->Output(
TemplateFile => 'AgentStatisticsEdit',
Data => {
%Frontend,
%{$Stat},
BreadcrumbPath => $Self->{BreadcrumbPath},
},
);
$Output .= $LayoutObject->Footer();
return $Output;
}
sub EditAction {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my %Errors;
my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet(
StatID => $ParamObject->GetParam( Param => 'StatID' ),
UserID => $Self->{UserID},
);
if ( !$Stat ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Need StatID!'),
);
}
#
# General Specification
#
my %Data;
for my $Key (qw(Title Description Valid)) {
$Data{$Key} = $ParamObject->GetParam( Param => $Key ) // '';
if ( !length $Data{$Key} ) { # Valid can be 0
$Errors{ $Key . 'ServerError' } = 'ServerError';
}
}
if ( length $ParamObject->GetParam( Param => 'TimeZone' ) ) {
$Data{TimeZone} = $ParamObject->GetParam( Param => 'TimeZone' );
}
for my $Key (qw(SumRow SumCol Cache ShowAsDashboardWidget)) {
$Data{$Key} = $ParamObject->GetParam( Param => $Key ) // '';
}
for my $Key (qw(Permission Format)) {
$Data{$Key} = [ $ParamObject->GetArray( Param => $Key ) ];
if ( !@{ $Data{$Key} } ) {
$Errors{ $Key . 'ServerError' } = 'ServerError';
#$Data{$Key} = '';
}
}
#
# X Axis
#
if ( $Stat->{StatType} eq 'dynamic' ) {
my $SelectedElement = $ParamObject->GetParam( Param => 'XAxisSelectedElement' );
$Data{StatType} = $Stat->{StatType};
OBJECTATTRIBUTE:
for my $ObjectAttribute ( @{ $Stat->{UseAsXvalue} } ) {
next OBJECTATTRIBUTE if !defined $SelectedElement;
next OBJECTATTRIBUTE if $SelectedElement ne 'XAxis' . $ObjectAttribute->{Element};
my @Array = $ParamObject->GetArray( Param => $SelectedElement );
$Data{UseAsXvalue}[0]{SelectedValues} = \@Array;
$Data{UseAsXvalue}[0]{Element} = $ObjectAttribute->{Element};
$Data{UseAsXvalue}[0]{Block} = $ObjectAttribute->{Block};
$Data{UseAsXvalue}[0]{Selected} = 1;
my $Fixed = $ParamObject->GetParam( Param => 'Fixed' . $SelectedElement );
$Data{UseAsXvalue}[0]{Fixed} = $Fixed ? 1 : 0;
# Check if Time was selected
next OBJECTATTRIBUTE if $ObjectAttribute->{Block} ne 'Time';
# This part is only needed if the block time is selected
# perhaps a separate function is better
my %Time;
$Data{UseAsXvalue}[0]{TimeScaleCount}
= $ParamObject->GetParam( Param => $SelectedElement . 'TimeScaleCount' ) || 1;
my $TimeSelect = $ParamObject->GetParam( Param => $SelectedElement . 'TimeSelect' ) || 'Absolut';
if ( $TimeSelect eq 'Absolut' ) {
for my $Limit (qw(Start Stop)) {
for my $Unit (qw(Year Month Day Hour Minute Second)) {
if ( defined( $ParamObject->GetParam( Param => "$SelectedElement$Limit$Unit" ) ) ) {
$Time{ $Limit . $Unit } = $ParamObject->GetParam(
Param => "$SelectedElement$Limit$Unit",
);
}
}
if ( !defined( $Time{ $Limit . 'Hour' } ) ) {
if ( $Limit eq 'Start' ) {
$Time{StartHour} = 0;
$Time{StartMinute} = 0;
$Time{StartSecond} = 0;
}
elsif ( $Limit eq 'Stop' ) {
$Time{StopHour} = 23;
$Time{StopMinute} = 59;
$Time{StopSecond} = 59;
}
}
elsif ( !defined( $Time{ $Limit . 'Second' } ) ) {
if ( $Limit eq 'Start' ) {
$Time{StartSecond} = 0;
}
elsif ( $Limit eq 'Stop' ) {
$Time{StopSecond} = 59;
}
}
$Data{UseAsXvalue}[0]{"Time$Limit"} = sprintf(
"%04d-%02d-%02d %02d:%02d:%02d",
$Time{ $Limit . 'Year' },
$Time{ $Limit . 'Month' },
$Time{ $Limit . 'Day' },
$Time{ $Limit . 'Hour' },
$Time{ $Limit . 'Minute' },
$Time{ $Limit . 'Second' },
);
}
}
else {
$Data{UseAsXvalue}[0]{TimeRelativeUnit} = $ParamObject->GetParam(
Param => $SelectedElement . 'TimeRelativeUnit'
);
$Data{UseAsXvalue}[0]{TimeRelativeCount} = $ParamObject->GetParam(
Param => $SelectedElement . 'TimeRelativeCount'
);
$Data{UseAsXvalue}[0]{TimeRelativeUpcomingCount} = $ParamObject->GetParam(
Param => $SelectedElement . 'TimeRelativeUpcomingCount'
);
}
}
}
#
# Y Axis
#
if ( $Stat->{StatType} eq 'dynamic' ) {
my $Index = 0;
$Data{StatType} = $Stat->{StatType};
OBJECTATTRIBUTE:
for my $ObjectAttribute ( @{ $Stat->{UseAsValueSeries} } ) {
my $Element = 'YAxis' . $ObjectAttribute->{Element};
if ( !$ParamObject->GetParam( Param => "Select$Element" ) ) {
next OBJECTATTRIBUTE;
}
my @Array = $ParamObject->GetArray( Param => $Element );
$Data{UseAsValueSeries}[$Index]{SelectedValues} = \@Array;
$Data{UseAsValueSeries}[$Index]{Element} = $ObjectAttribute->{Element};
$Data{UseAsValueSeries}[$Index]{Block} = $ObjectAttribute->{Block};
$Data{UseAsValueSeries}[$Index]{Selected} = 1;
my $FixedElement = 'Fixed' . $Element;
my $Fixed = $ParamObject->GetParam( Param => $FixedElement );
$Data{UseAsValueSeries}[$Index]{Fixed} = $Fixed ? 1 : 0;
# Check if Time was selected
if ( $ObjectAttribute->{Block} eq 'Time' ) {
# for working with extended time
$Data{UseAsValueSeries}[$Index]{TimeScaleCount} = $ParamObject->GetParam(
Param => $Element . 'TimeScaleCount'
) || 1;
# check if the current selected value is allowed for the x axis selected time scale
my $SelectedXAxisTimeScaleValue = $Data{UseAsXvalue}[0]{SelectedValues}[0];
my $TimeScale = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->_TimeScale(
SelectedXAxisValue => $SelectedXAxisTimeScaleValue,
);
my %TimeScaleLookup = map { $_ => 1 } sort keys %{$TimeScale};
# set the first allowed time scale value as default
if (
!$Data{UseAsValueSeries}[$Index]{SelectedValues}[0]
|| !exists $TimeScaleLookup{ $Data{UseAsValueSeries}[$Index]{SelectedValues}[0] }
)
{
my @TimeScaleSorted
= sort { $TimeScale->{$a}->{Position} <=> $TimeScale->{$b}->{Position} } keys %{$TimeScale};
$Data{UseAsValueSeries}[$Index]{SelectedValues}[0] = $TimeScaleSorted[0];
}
}
$Index++;
}
$Data{UseAsValueSeries} ||= [];
}
#
# Restrictions
#
if ( $Stat->{StatType} eq 'dynamic' ) {
my $Index = 0;
$Data{StatType} = $Stat->{StatType};
OBJECTATTRIBUTE:
for my $ObjectAttribute ( @{ $Stat->{UseAsRestriction} } ) {
my $Element = 'Restrictions' . $ObjectAttribute->{Element};
if ( !$ParamObject->GetParam( Param => "Select$Element" ) ) {
next OBJECTATTRIBUTE;
}
my @Array = $ParamObject->GetArray( Param => $Element );
$Data{UseAsRestriction}[$Index]{SelectedValues} = \@Array;
$Data{UseAsRestriction}[$Index]{Element} = $ObjectAttribute->{Element};
$Data{UseAsRestriction}[$Index]{Block} = $ObjectAttribute->{Block};
$Data{UseAsRestriction}[$Index]{Selected} = 1;
my $Fixed = $ParamObject->GetParam( Param => 'Fixed' . $Element );
$Data{UseAsRestriction}[$Index]{Fixed} = $Fixed ? 1 : 0;
if ( $ObjectAttribute->{Block} eq 'Time' ) {
my %Time;
my $TimeSelect = $ParamObject->GetParam( Param => $Element . 'TimeSelect' )
|| 'Absolut';
if ( $TimeSelect eq 'Absolut' ) {
for my $Limit (qw(Start Stop)) {
for my $Unit (qw(Year Month Day Hour Minute Second)) {
if ( defined( $ParamObject->GetParam( Param => "$Element$Limit$Unit" ) ) )
{
$Time{ $Limit . $Unit } = $ParamObject->GetParam(
Param => "$Element$Limit$Unit",
);
}
}
if ( !defined( $Time{ $Limit . 'Hour' } ) ) {
if ( $Limit eq 'Start' ) {
$Time{StartHour} = 0;
$Time{StartMinute} = 0;
$Time{StartSecond} = 0;
}
elsif ( $Limit eq 'Stop' ) {
$Time{StopHour} = 23;
$Time{StopMinute} = 59;
$Time{StopSecond} = 59;
}
}
elsif ( !defined( $Time{ $Limit . 'Second' } ) ) {
if ( $Limit eq 'Start' ) {
$Time{StartSecond} = 0;
}
elsif ( $Limit eq 'Stop' ) {
$Time{StopSecond} = 59;
}
}
$Data{UseAsRestriction}[$Index]{"Time$Limit"} = sprintf(
"%04d-%02d-%02d %02d:%02d:%02d",
$Time{ $Limit . 'Year' },
$Time{ $Limit . 'Month' },
$Time{ $Limit . 'Day' },
$Time{ $Limit . 'Hour' },
$Time{ $Limit . 'Minute' },
$Time{ $Limit . 'Second' },
);
}
}
else {
$Data{UseAsRestriction}[$Index]{TimeRelativeUnit} = $ParamObject->GetParam(
Param => $Element . 'TimeRelativeUnit'
);
$Data{UseAsRestriction}[$Index]{TimeRelativeCount} = $ParamObject->GetParam(
Param => $Element . 'TimeRelativeCount'
);
$Data{UseAsRestriction}[$Index]{TimeRelativeUpcomingCount} = $ParamObject->GetParam(
Param => $Element . 'TimeRelativeUpcomingCount'
);
}
}
$Index++;
}
$Data{UseAsRestriction} ||= [];
}
# my @Notify = $Kernel::OM->Get('Kernel::System::Stats')->CompletenessCheck(
# StatData => {
# %{$Stat},
# %Data,
# },
# Section => 'Specification'
# );
if (%Errors) {
return $Self->EditScreen(
Errors => \%Errors,
GetParam => \%Data,
);
}
$Kernel::OM->Get('Kernel::System::Stats')->StatsUpdate(
StatID => $Stat->{StatID},
Hash => \%Data,
UserID => $Self->{UserID},
);
if ( $ParamObject->GetParam( Param => 'ReturnToStatisticOverview' ) ) {
return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Overview" );
}
return $LayoutObject->Redirect(
OP => "Action=AgentStatistics;Subaction=Edit;StatID=$Stat->{StatID}"
);
}
sub ViewScreen {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my @Errors;
if ( ref $Param{Errors} eq 'ARRAY' ) {
@Errors = @{ $Param{Errors} || [] };
}
# get StatID
my $StatID = $ParamObject->GetParam( Param => 'StatID' );
if ( !$StatID ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Need StatID!'),
);
}
# get message if one available
#my $Message = $ParamObject->GetParam( Param => 'Message' );
# Get all statistics that the current user may see (does permission check).
my $StatsList = $Kernel::OM->Get('Kernel::System::Stats')->StatsListGet(
UserID => $Self->{UserID},
);
if ( !IsHashRefWithData( $StatsList->{$StatID} ) ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Could not load stat.'),
);
}
my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet(
StatID => $StatID,
UserID => $Self->{UserID},
);
# get param
if ( !IsHashRefWithData($Stat) ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Could not load stat.'),
);
}
my %Frontend;
$Frontend{StatsParamsWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->StatsParamsWidget(
Stat => $Stat,
UserID => $Self->{UserID},
);
my $Output = $LayoutObject->Header(
Title => Translatable('View'),
Area => 'Statistics',
);
$Output .= $LayoutObject->NavigationBar();
$Output .= $LayoutObject->Output(
TemplateFile => 'AgentStatisticsView',
Data => {
AccessRw => $Self->{AccessRw},
Errors => \@Errors,
%Frontend,
%{$Stat},
BreadcrumbPath => $Self->{BreadcrumbPath},
},
);
$Output .= $LayoutObject->Footer();
return $Output;
}
sub AddScreen {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
# In case of page reload because of errors
my %Errors = %{ $Param{Errors} // {} };
my %GetParam = %{ $Param{GetParam} // {} };
my %Frontend;
my $DynamicFiles = $Kernel::OM->Get('Kernel::System::Stats')->GetDynamicFiles();
DYNAMIC_FILE:
for my $DynamicFile ( sort keys %{ $DynamicFiles // {} } ) {
my $ObjectName = 'Kernel::System::Stats::Dynamic::' . $DynamicFile;
next DYNAMIC_FILE if !$Kernel::OM->Get('Kernel::System::Main')->Require($ObjectName);
my $Object = $ObjectName->new();
next DYNAMIC_FILE if !$Object;
if ( $Object->can('GetStatElement') ) {
$Frontend{ShowAddDynamicMatrixButton}++;
}
else {
$Frontend{ShowAddDynamicListButton}++;
}
}
my $StaticFiles = $Kernel::OM->Get('Kernel::System::Stats')->GetStaticFiles(
OnlyUnusedFiles => 1,
UserID => $Self->{UserID},
);
if ( scalar keys %{$StaticFiles} ) {
$Frontend{ShowAddStaticButton}++;
}
# This is a page reload because of validation errors
if (%Errors) {
$Frontend{StatisticPreselection} = $ParamObject->GetParam( Param => 'StatisticPreselection' );
$Frontend{GeneralSpecificationsWidget}
= $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->GeneralSpecificationsWidget(
Errors => \%Errors,
GetParam => \%GetParam,
UserID => $Self->{UserID},
);
$Frontend{ShowFormInitially} = 1;
}
# generate manual link
my $ManualVersion = $Kernel::OM->Get('Kernel::Config')->Get('Version');
$ManualVersion =~ m{^(\d{1,2}).+};
$ManualVersion = $1;
# build output
my $Output = $LayoutObject->Header(
Title => Translatable('Add New Statistic'),
Area => 'Statistics',
);
$Output .= $LayoutObject->NavigationBar();
$Output .= $LayoutObject->Output(
TemplateFile => 'AgentStatisticsAdd',
Data => {
%Frontend,
%Errors,
ManualVersion => $ManualVersion,
BreadcrumbPath => $Self->{BreadcrumbPath},
},
);
$Output .= $LayoutObject->Footer();
return $Output;
}
sub AddAction {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my %Errors;
my %Data;
for my $Key (qw(Title Description ObjectModule StatType Valid)) {
$Data{$Key} = $ParamObject->GetParam( Param => $Key ) // '';
if ( !length $Data{$Key} ) { # Valid can be 0
$Errors{ $Key . 'ServerError' } = 'ServerError';
}
}
if ( length $ParamObject->GetParam( Param => 'TimeZone' ) ) {
$Data{TimeZone} = $ParamObject->GetParam( Param => 'TimeZone' );
}
# This seems to be historical metadata that is needed for display.
my $Object = $Data{ObjectModule};
$Object = [ split( m{::}, $Object ) ]->[-1];
if ( $Data{StatType} eq 'static' ) {
$Data{File} = $Object;
}
else {
$Data{Object} = $Object;
}
my $StatsObject = $Kernel::OM->Get('Kernel::System::Stats');
my $ObjectModuleCheck = $StatsObject->ObjectModuleCheck(
StatType => $Data{StatType},
ObjectModule => $Data{ObjectModule},
CheckAlreadyUsedStaticObject => 1,
);
if ( !$ObjectModuleCheck ) {
$Errors{ObjectModuleServerError} = 'ServerError';
}
for my $Key (qw(SumRow SumCol Cache ShowAsDashboardWidget)) {
$Data{$Key} = $ParamObject->GetParam( Param => $Key ) // '';
}
for my $Key (qw(Permission Format)) {
$Data{$Key} = [ $ParamObject->GetArray( Param => $Key ) ];
if ( !@{ $Data{$Key} } ) {
$Errors{ $Key . 'ServerError' } = 'ServerError';
#$Data{$Key} = '';
}
}
# my @Notify = $Kernel::OM->Get('Kernel::System::Stats')->CompletenessCheck(
# StatData => \%Data,
# Section => 'Specification'
# );
if (%Errors) {
return $Self->AddScreen(
Errors => \%Errors,
GetParam => \%Data,
);
}
$Param{StatID} = $StatsObject->StatsAdd(
UserID => $Self->{UserID},
);
if ( !$Param{StatID} ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Could not create statistic.'),
);
}
$StatsObject->StatsUpdate(
StatID => $Param{StatID},
Hash => \%Data,
UserID => $Self->{UserID},
);
# For static stats, the configuration is finished
if ( $Data{StatType} eq 'static' ) {
return $LayoutObject->Redirect(
OP => "Action=AgentStatistics;Subaction=View;StatID=$Param{StatID}",
);
}
# Continue configuration for dynamic stats
return $LayoutObject->Redirect(
OP => "Action=AgentStatistics;Subaction=Edit;StatID=$Param{StatID}",
);
}
sub RunAction {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
for my $Name (qw(Format StatID Name Cached)) {
$Param{$Name} = $ParamObject->GetParam( Param => $Name );
}
my @RequiredParams = (qw(Format StatID));
if ( $Param{Cached} ) {
push @RequiredParams, 'Name';
}
for my $Required (@RequiredParams) {
if ( !$Param{$Required} ) {
return $LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate( 'Run: Get no %s!', $Required ),
);
}
}
my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet(
StatID => $Param{StatID},
UserID => $Self->{UserID},
);
# permission check
if ( !$Self->{AccessRw} ) {
my $UserPermission = 0;
return $LayoutObject->NoPermission( WithHeader => 'yes' ) if !$Stat->{Valid};
# get user groups
my %GroupList = $Kernel::OM->Get('Kernel::System::Group')->PermissionUserGet(
UserID => $Self->{UserID},
Type => 'ro',
);
GROUPID:
for my $GroupID ( @{ $Stat->{Permission} } ) {
next GROUPID if !$GroupID;
next GROUPID if !$GroupList{$GroupID};
$UserPermission = 1;
last GROUPID;
}
return $LayoutObject->NoPermission( WithHeader => 'yes' ) if !$UserPermission;
}
# get params
my %GetParam = eval {
$Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->StatsParamsGet(
Stat => $Stat,
UserID => $Self->{UserID},
);
};
if ($@) {
return $Self->ViewScreen( Errors => $@ );
}
# run stat...
my @StatArray;
# called from within the dashboard. will use the same mechanism and configuration like in
# the dashboard stats - the (cached) result will be the same as seen in the dashboard
if ( $Param{Cached} ) {
# get settings for specified stats by using the dashboard configuration for the agent
my %Preferences = $Kernel::OM->Get('Kernel::System::User')->GetPreferences(
UserID => $Self->{UserID},
);
my $PrefKeyStatsConfiguration = 'UserDashboardStatsStatsConfiguration' . $Param{Name};
my $StatsSettings = {};
if ( $Preferences{$PrefKeyStatsConfiguration} ) {
$StatsSettings = $Kernel::OM->Get('Kernel::System::JSON')->Decode(
Data => $Preferences{$PrefKeyStatsConfiguration},
);
}
@StatArray = @{
$Kernel::OM->Get('Kernel::System::Stats')->StatsResultCacheGet(
StatID => $Param{StatID},
UserGetParam => $StatsSettings,
UserID => $Self->{UserID},
);
};
}
# called normally within the stats area - generate stats now and use provided configuraton
else {
@StatArray = @{
$Kernel::OM->Get('Kernel::System::Stats')->StatsRun(
StatID => $Param{StatID},
GetParam => \%GetParam,
UserID => $Self->{UserID},
);
};
}
return $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->StatsResultRender(
StatArray => \@StatArray,
Stat => $Stat,
TimeZone => $GetParam{TimeZone},
UserID => $Self->{UserID},
%Param
);
}
sub GeneralSpecificationsWidgetAJAX {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
return $LayoutObject->Attachment(
ContentType => 'text/html',
Content => $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')
->GeneralSpecificationsWidget( UserID => $Self->{UserID} ),
Type => 'inline',
NoCache => 1,
);
}
# ATTENTION: this function delivers only approximations!!!
sub _TimeInSeconds {
my ( $Self, %Param ) = @_;
# check if need params are available
if ( !$Param{TimeUnit} ) {
return $Kernel::OM->Get('Kernel::Output::HTML::Layout')
->ErrorScreen( Message => '_TimeInSeconds: Need TimeUnit!' );
}
my %TimeInSeconds = (
Year => 31536000, # 60 * 60 * 24 * 365
HalfYear => 15724800, # 60 * 60 * 24 * 182
Quarter => 7862400, # 60 * 60 * 24 * 91
Month => 2592000, # 60 * 60 * 24 * 30
Week => 604800, # 60 * 60 * 24 * 7
Day => 86400, # 60 * 60 * 24
Hour => 3600, # 60 * 60
Minute => 60,
Second => 1,
);
return $TimeInSeconds{ $Param{TimeUnit} };
}
1;