369 lines
11 KiB
Perl
369 lines
11 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::System::Stats::Dynamic::ITSMChangeManagementChangesPerCIClasses;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
our @ObjectDependencies = (
|
|
'Kernel::System::DateTime',
|
|
'Kernel::System::DB',
|
|
'Kernel::System::GeneralCatalog',
|
|
'Kernel::System::ITSMChange',
|
|
'Kernel::System::LinkObject',
|
|
'Kernel::System::Log',
|
|
);
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# allocate new hash for object
|
|
my $Self = {};
|
|
bless( $Self, $Type );
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub GetObjectName {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
return 'ITSMChangeManagementChangesPerCIClasses';
|
|
}
|
|
|
|
sub GetObjectBehaviours {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my %Behaviours = (
|
|
ProvidesDashboardWidget => 1,
|
|
);
|
|
|
|
return %Behaviours;
|
|
}
|
|
|
|
sub GetObjectAttributes {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get cip lists
|
|
my $Categories = $Kernel::OM->Get('Kernel::System::ITSMChange')->ChangePossibleCIPGet(
|
|
Type => 'Category',
|
|
UserID => 1,
|
|
);
|
|
my %CategoryList = map { $_->{Key} => $_->{Value} } @{$Categories};
|
|
|
|
# get class list
|
|
my $ClassList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::ConfigItem::Class',
|
|
);
|
|
|
|
# get deployment state list
|
|
my $DeplStateList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::ConfigItem::DeploymentState',
|
|
);
|
|
|
|
# get incident state list
|
|
my $InciStateList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::Core::IncidentState',
|
|
);
|
|
|
|
# get current time to fix bug#4870
|
|
my $Today = $Kernel::OM->Create('Kernel::System::DateTime')->Format( Format => '%Y-%m-%d 23:59:59' );
|
|
|
|
my @ObjectAttributes = (
|
|
{
|
|
Name => 'ConfigItem Classes',
|
|
UseAsXvalue => 0,
|
|
UseAsValueSeries => 1,
|
|
UseAsRestriction => 0,
|
|
Element => 'CIClassIDs',
|
|
Block => 'MultiSelectField',
|
|
Translation => 0,
|
|
Values => $ClassList,
|
|
},
|
|
{
|
|
Name => 'Category',
|
|
UseAsXvalue => 1,
|
|
UseAsValueSeries => 0,
|
|
UseAsRestriction => 0,
|
|
Element => 'CategoryIDs',
|
|
Block => 'MultiSelectField',
|
|
Values => \%CategoryList,
|
|
},
|
|
{
|
|
Name => 'ConfigItem Status',
|
|
UseAsXvalue => 0,
|
|
UseAsValueSeries => 0,
|
|
UseAsRestriction => 1,
|
|
Element => 'CIStateIDs',
|
|
Block => 'MultiSelectField',
|
|
Translation => 0,
|
|
Values => $InciStateList,
|
|
},
|
|
{
|
|
Name => 'Timeperiod',
|
|
UseAsXvalue => 0,
|
|
UseAsValueSeries => 0,
|
|
UseAsRestriction => 1,
|
|
Element => 'TimePeriod',
|
|
TimePeriodFormat => 'DateInputFormat', # 'DateInputFormatLong',
|
|
Block => 'Time',
|
|
TimeStop => $Today,
|
|
Values => {
|
|
TimeStart => 'CreateTimeNewerDate',
|
|
TimeStop => 'CreateTimeOlderDate',
|
|
},
|
|
},
|
|
);
|
|
|
|
return @ObjectAttributes;
|
|
}
|
|
|
|
sub GetStatElementPreview {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
return int rand 50;
|
|
}
|
|
|
|
sub GetStatElement {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get object ids for change and config item
|
|
my $ConfigItemObjectID = $Kernel::OM->Get('Kernel::System::LinkObject')->ObjectLookup(
|
|
Name => 'ITSMConfigItem',
|
|
UserID => 1,
|
|
);
|
|
|
|
return if !$ConfigItemObjectID;
|
|
|
|
my $ChangeObjectID = $Kernel::OM->Get('Kernel::System::LinkObject')->ObjectLookup(
|
|
Name => 'ITSMWorkOrder',
|
|
UserID => 1,
|
|
);
|
|
|
|
return if !$ChangeObjectID;
|
|
|
|
# get change id and config item id
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
|
|
SQL => 'SELECT chi.id AS change_id, ci.id AS ci_id '
|
|
. 'FROM change_item chi, change_workorder chw, link_relation lr, configitem ci '
|
|
. 'WHERE chi.id = chw.change_id '
|
|
. 'AND chi.category_id = ? '
|
|
. 'AND ( '
|
|
. '( '
|
|
. 'chw.id = lr.target_key '
|
|
. 'AND lr.target_object_id = ? '
|
|
. 'AND lr.source_object_id = ? '
|
|
. 'AND lr.source_key = ci.id '
|
|
. 'AND ci.class_id = ? '
|
|
. ') '
|
|
. 'OR '
|
|
. '( '
|
|
. 'chw.id = lr.source_key '
|
|
. 'AND lr.source_object_id = ? '
|
|
. 'AND lr.target_object_id = ? '
|
|
. 'AND lr.target_key = ci.id '
|
|
. 'AND ci.class_id = ? '
|
|
. ') '
|
|
. ')',
|
|
Bind => [
|
|
\( $Param{CategoryIDs}->[0] ),
|
|
\$ChangeObjectID,
|
|
\$ConfigItemObjectID,
|
|
\( $Param{CIClassIDs}->[0] ),
|
|
\$ChangeObjectID,
|
|
\$ConfigItemObjectID,
|
|
\( $Param{CIClassIDs}->[0] ),
|
|
],
|
|
);
|
|
|
|
# fetch change and config item ids
|
|
my @Matches;
|
|
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
|
|
push @Matches, \@Row;
|
|
}
|
|
|
|
# check for each change if the config item is in appropriate status
|
|
# if so, count the change
|
|
my %ChangesAlreadyCounted;
|
|
MATCH:
|
|
for my $Match (@Matches) {
|
|
next MATCH if $ChangesAlreadyCounted{ $Match->[0] };
|
|
|
|
# get current state of the config item
|
|
next MATCH if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
|
|
SQL => 'SELECT inci_state_id FROM configitem_version '
|
|
. 'WHERE configitem_id = ? '
|
|
. 'AND create_time >= ? AND create_time <= ?',
|
|
Bind => [
|
|
\( $Match->[1] ),
|
|
\( $Param{CreateTimeNewerDate} ),
|
|
\( $Param{CreateTimeOlderDate} ),
|
|
],
|
|
Limit => 1,
|
|
);
|
|
|
|
# fetch current incident state
|
|
my $IncidentStateID;
|
|
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
|
|
$IncidentStateID = $Row[0];
|
|
}
|
|
|
|
next MATCH if !$IncidentStateID;
|
|
|
|
# check if user has selected this state
|
|
my ($Found) = grep { $_ == $IncidentStateID } @{ $Param{CIStateIDs} };
|
|
|
|
next MATCH if !$Found;
|
|
|
|
$ChangesAlreadyCounted{ $Match->[0] }++;
|
|
}
|
|
|
|
# return the number of changes
|
|
my $Count = keys %ChangesAlreadyCounted;
|
|
return $Count;
|
|
}
|
|
|
|
sub ExportWrapper {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get class list
|
|
my $ClassList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::ConfigItem::Class',
|
|
);
|
|
|
|
# get incident state list
|
|
my $InciStateList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::Core::IncidentState',
|
|
);
|
|
|
|
# wrap ids to used spelling
|
|
for my $Use (qw(UseAsValueSeries UseAsRestriction UseAsXvalue)) {
|
|
ELEMENT:
|
|
for my $Element ( @{ $Param{$Use} } ) {
|
|
next ELEMENT if !$Element || !$Element->{SelectedValues};
|
|
my $ElementName = $Element->{Element};
|
|
my $Values = $Element->{SelectedValues};
|
|
|
|
if ( $ElementName eq 'CIStateIDs' ) {
|
|
ID:
|
|
for my $ID ( @{$Values} ) {
|
|
next ID if !$ID;
|
|
|
|
$ID->{Content} = $InciStateList->{ $ID->{Content} };
|
|
}
|
|
}
|
|
elsif ( $ElementName eq 'CIClassIDs' ) {
|
|
ID:
|
|
for my $ID ( @{$Values} ) {
|
|
next ID if !$ID;
|
|
|
|
$ID->{Content} = $ClassList->{ $ID->{Content} };
|
|
}
|
|
}
|
|
elsif ( $ElementName eq 'CategoryIDs' ) {
|
|
|
|
my $CIPList = $Kernel::OM->Get('Kernel::System::ITSMChange')->ChangePossibleCIPGet(
|
|
Type => 'Category',
|
|
UserID => 1,
|
|
);
|
|
|
|
ID:
|
|
for my $ID ( @{$Values} ) {
|
|
next ID if !$ID;
|
|
|
|
ELEMENT:
|
|
for my $Element ( @{$CIPList} ) {
|
|
next ELEMENT if $ID->{Content} ne $Element->{Key};
|
|
$ID->{Content} = $Element->{Value};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return \%Param;
|
|
}
|
|
|
|
sub ImportWrapper {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get class list
|
|
my $ClassList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::ConfigItem::Class',
|
|
);
|
|
|
|
# get incident state list
|
|
my $InciStateList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::Core::IncidentState',
|
|
);
|
|
|
|
# wrap used spelling to ids
|
|
for my $Use (qw(UseAsValueSeries UseAsRestriction UseAsXvalue)) {
|
|
ELEMENT:
|
|
for my $Element ( @{ $Param{$Use} } ) {
|
|
next ELEMENT if !$Element || !$Element->{SelectedValues};
|
|
my $ElementName = $Element->{Element};
|
|
my $Values = $Element->{SelectedValues};
|
|
|
|
if ( $ElementName eq 'CIStateIDs' ) {
|
|
ID:
|
|
for my $ID ( @{$Values} ) {
|
|
next ID if !$ID;
|
|
|
|
KEY:
|
|
for my $Key ( sort keys %{$InciStateList} ) {
|
|
if ( $ID->{Content} eq $InciStateList->{$Key} ) {
|
|
$ID->{Content} = $Key;
|
|
last KEY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elsif ( $ElementName eq 'CIClassIDs' ) {
|
|
ID:
|
|
for my $ID ( @{$Values} ) {
|
|
next ID if !$ID;
|
|
|
|
for my $Key ( sort keys %{$ClassList} ) {
|
|
if ( $ID->{Content} eq $ClassList->{$Key} ) {
|
|
$ID->{Content} = $Key;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# import wrapper for CIP
|
|
for my $Type (qw(Category)) {
|
|
if ( $ElementName eq $Type . 'IDs' ) {
|
|
ID:
|
|
for my $ID ( @{$Values} ) {
|
|
next ID if !$ID;
|
|
|
|
my $CIPID = $Kernel::OM->Get('Kernel::System::ITSMChange')->ChangeCIPLookup(
|
|
CIP => $ID->{Content},
|
|
Type => $Type,
|
|
);
|
|
if ($CIPID) {
|
|
$ID->{Content} = $CIPID;
|
|
}
|
|
else {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Import: Can' find $Type $ID->{Content}!"
|
|
);
|
|
$ID = undef;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return \%Param;
|
|
}
|
|
|
|
1;
|