618 lines
22 KiB
Perl
618 lines
22 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::Ticket::Event::TicketStatusLink;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Kernel::System::VariableCheck qw(:all);
|
|
|
|
our @ObjectDependencies = (
|
|
'Kernel::Config',
|
|
'Kernel::System::Log',
|
|
'Kernel::System::Ticket',
|
|
'Kernel::System::User',
|
|
'Kernel::System::ITSMConfigItem',
|
|
'Kernel::System::GeneralCatalog',
|
|
'Kernel::System::LinkObject',
|
|
);
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# allocate new hash for object
|
|
my $Self = {};
|
|
bless( $Self, $Type );
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub Run {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# check needed stuff
|
|
for my $Needed (qw(Data Event Config)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# check if functionality is enabled
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
return 1 if !$ConfigObject->Get('ITSMConfigItem::SetIncidentStateOnLink');
|
|
|
|
# get ticket id depending on event
|
|
my $TicketID;
|
|
if ( $Param{Event} eq 'LinkAdd' || $Param{Event} eq 'LinkDelete' ) {
|
|
for my $Needed (qw(ConfigItemID Comment)) {
|
|
if ( !$Param{Data}->{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed in Data!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( $Param{Event} eq 'LinkAdd' ) {
|
|
if ( !$Param{Data}->{Type} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need Type in Data!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# check if link event concerns a ticket
|
|
return 1 if $Param{Data}->{Comment} !~ m{ \A ( \d+ ) %%Ticket \z }xms;
|
|
$TicketID = $1;
|
|
}
|
|
else {
|
|
if ( !$Param{Data}->{TicketID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need TicketID in Data!",
|
|
);
|
|
return;
|
|
}
|
|
$TicketID = $Param{Data}->{TicketID};
|
|
}
|
|
|
|
my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
|
|
my %Ticket = $TicketObject->TicketGet(
|
|
TicketID => $TicketID,
|
|
UserID => 1,
|
|
);
|
|
return 1 if !%Ticket;
|
|
|
|
# check if ticket type is relevant (optional functionality)
|
|
my $OldTicketTypeRelevant;
|
|
my $NewTicketTypeRelevant;
|
|
my $TicketTypes = $ConfigObject->Get('ITSMConfigItem::LinkStatus::TicketTypes');
|
|
if ( $Param{Event} eq 'TicketTypeUpdate' ) {
|
|
|
|
# ticket types are not used, changes don't affect CI incident states
|
|
return 1 if !IsArrayRefWithData($TicketTypes);
|
|
|
|
# determine type of ticket before last update
|
|
my $OldTicketType;
|
|
my @HistoryLines = $TicketObject->HistoryGet(
|
|
TicketID => $TicketID,
|
|
UserID => 1,
|
|
);
|
|
LINE:
|
|
for my $Line ( reverse @HistoryLines ) {
|
|
next LINE if $Line->{HistoryType} ne 'TypeUpdate';
|
|
my @CommentParts = split '%%', $Line->{Name};
|
|
$OldTicketType = $CommentParts[3];
|
|
last LINE;
|
|
}
|
|
if ( !$OldTicketType ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Found no previous ticket type for ticket id $TicketID!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# only changes relevant->irrelevant and irrelevant->relevant are of interest
|
|
$OldTicketTypeRelevant = 1 if grep { $_ eq $OldTicketType } @{$TicketTypes};
|
|
$NewTicketTypeRelevant = 1 if grep { $_ eq $Ticket{Type} } @{$TicketTypes};
|
|
return 1 if ( $OldTicketTypeRelevant || '' ) eq ( $NewTicketTypeRelevant || '' );
|
|
}
|
|
|
|
# shortcut for other events (check if ticket type is in scope)
|
|
elsif ( IsArrayRefWithData($TicketTypes) ) {
|
|
return 1 if !$Ticket{Type};
|
|
return 1 if !grep { $_ eq $Ticket{Type} } @{$TicketTypes};
|
|
}
|
|
|
|
# check if ticket state is relevant
|
|
my $OldTicketStateRelevant;
|
|
my $NewTicketStateRelevant;
|
|
my @OpenStateTypes = ( 'new', 'open', 'pending reminder', 'pending auto' );
|
|
if ( $Param{Event} eq 'TicketStateUpdate' ) {
|
|
if ( !$Param{Data}->{OldTicketData} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need TicketID in OldTicketData!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# only changes open->close and close->open are of interest
|
|
$NewTicketStateRelevant = 1 if grep { $_ eq $Ticket{StateType} } @OpenStateTypes;
|
|
$OldTicketStateRelevant = 1 if grep { $_ eq $Param{Data}->{OldTicketData}->{StateType} } @OpenStateTypes;
|
|
return 1 if ( $NewTicketStateRelevant || '' ) eq ( $OldTicketStateRelevant || '' );
|
|
}
|
|
|
|
# shortcut for other events (check if ticket state is in scope)
|
|
else {
|
|
return 1 if !grep { $_ eq $Ticket{StateType} } @OpenStateTypes;
|
|
}
|
|
|
|
# shortcut for ticket events (check if ticket has any potentially relevant links)
|
|
if ( $Param{Event} eq 'TicketStateUpdate' || $Param{Event} eq 'TicketTypeUpdate' ) {
|
|
my %LinkKeyList = $Kernel::OM->Get('Kernel::System::LinkObject')->LinkKeyList(
|
|
Object1 => 'Ticket',
|
|
Key1 => $TicketID,
|
|
Object2 => 'ITSMConfigItem',
|
|
State => 'Valid',
|
|
UserID => 1,
|
|
);
|
|
return 1 if !IsHashRefWithData( \%LinkKeyList );
|
|
}
|
|
|
|
# prepare incident states and relevant link types per incident state
|
|
my $IncidentStates = $ConfigObject->Get('ITSMConfigItem::LinkStatus::IncidentStates');
|
|
my $LinkTypes = $ConfigObject->Get('ITSMConfigItem::LinkStatus::LinkTypes');
|
|
if ( !IsHashRefWithData($LinkTypes) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need configuration for 'ITSMConfigItem::LinkStatus::LinkTypes'!",
|
|
);
|
|
return;
|
|
}
|
|
my %LinkTypesByIncidentState;
|
|
|
|
if ( $Param{Event} eq 'LinkAdd' ) {
|
|
for my $LinkType ( sort keys %{$LinkTypes} ) {
|
|
if ( $LinkType eq $Param{Data}->{Type} ) {
|
|
push @{ $LinkTypesByIncidentState{ $LinkTypes->{$LinkType} } }, $LinkType;
|
|
}
|
|
}
|
|
return 1 if !IsHashRefWithData( \%LinkTypesByIncidentState );
|
|
}
|
|
else {
|
|
for my $LinkType ( sort keys %{$LinkTypes} ) {
|
|
push @{ $LinkTypesByIncidentState{ $LinkTypes->{$LinkType} } }, $LinkType;
|
|
}
|
|
}
|
|
|
|
# handle added or removed links
|
|
if ( $Param{Event} eq 'LinkAdd' || $Param{Event} eq 'LinkDelete' ) {
|
|
my $ConfigItemID = $Param{Data}->{ConfigItemID};
|
|
my $Version = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->VersionGet(
|
|
ConfigItemID => $ConfigItemID,
|
|
);
|
|
|
|
# optional: check if CI deployment state is relevant
|
|
my $DeploymentStates = $ConfigObject->Get('ITSMConfigItem::LinkStatus::DeploymentStates');
|
|
if ( IsArrayRefWithData($DeploymentStates) ) {
|
|
return 1 if !grep { $_ eq $Version->{DeplState} } @{$DeploymentStates};
|
|
}
|
|
|
|
# raise incident state if necessary
|
|
if ( $Param{Event} eq 'LinkAdd' ) {
|
|
return $Self->_CheckRaiseIncidentState(
|
|
Version => $Version,
|
|
IncidentStates => $IncidentStates,
|
|
LinkTypesByIncidentState => \%LinkTypesByIncidentState,
|
|
TicketID => $TicketID,
|
|
);
|
|
}
|
|
|
|
# lower incident state if necessary
|
|
return $Self->_CheckLowerIncidentState(
|
|
Version => $Version,
|
|
IncidentStates => $IncidentStates,
|
|
LinkTypesByIncidentState => \%LinkTypesByIncidentState,
|
|
TicketID => $TicketID,
|
|
);
|
|
}
|
|
|
|
# handle ticket closure/re-open and relevant/irrelevant type change
|
|
elsif ( $Param{Event} eq 'TicketStateUpdate' || $Param{Event} eq 'TicketTypeUpdate' ) {
|
|
|
|
# relevant ticket state and type updates are handled the same way
|
|
# both mean a ticket is relevant for CI incident state changes or not
|
|
# ticket re-open or change to relevant type = might have to raise incident state of CIs
|
|
# ticket closure or change to irrelevant type = might have to lower incident state of CIs
|
|
my $RelevantNow;
|
|
if (
|
|
( $Param{Event} eq 'TicketStateUpdate' && $NewTicketStateRelevant )
|
|
|| ( $Param{Event} eq 'TicketTypeUpdate' && $NewTicketTypeRelevant )
|
|
)
|
|
{
|
|
$RelevantNow = 1;
|
|
}
|
|
|
|
# loop through all link types and check links to see if there are possibly affected CIs
|
|
my $DeploymentStates = $ConfigObject->Get('ITSMConfigItem::LinkStatus::DeploymentStates');
|
|
INCIDENTSTATE:
|
|
for my $IncidentState ( @{$IncidentStates} ) {
|
|
LINKTYPE:
|
|
for my $LinkType ( @{ $LinkTypesByIncidentState{$IncidentState} } ) {
|
|
my @LinkedCIs = $Self->_CheckTicketLinks(
|
|
TicketID => $TicketID,
|
|
Type => $LinkType,
|
|
);
|
|
next LINKTYPE if !@LinkedCIs;
|
|
|
|
CONFIGITEMID:
|
|
for my $ConfigItemID (@LinkedCIs) {
|
|
my $Version = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->VersionGet(
|
|
ConfigItemID => $ConfigItemID,
|
|
);
|
|
|
|
# optional: check if CI deployment state is relevant
|
|
if ( IsArrayRefWithData($DeploymentStates) ) {
|
|
next CONFIGITEMID if !grep { $_ eq $Version->{DeplState} } @{$DeploymentStates};
|
|
}
|
|
|
|
# check current incident state vs state caused by link
|
|
|
|
# current incident state is lower than caused by link -> set
|
|
if ($RelevantNow) {
|
|
|
|
# shortcut: nothing to do if CI is already in highest incident state
|
|
next CONFIGITEMID if $Version->{InciState} eq $IncidentStates->[0];
|
|
|
|
# shortcut: nothing to do if CI is already in same incident state
|
|
next CONFIGITEMID if $Version->{InciState} eq $IncidentState;
|
|
|
|
# check if CI is in higher incident state already
|
|
TMPINCIDENTSTATE:
|
|
for my $TmpIncidentState ( @{$IncidentStates} ) {
|
|
|
|
# all further incident states are lower than current one -> set new state
|
|
last TMPINCIDENTSTATE if $TmpIncidentState eq $IncidentState;
|
|
|
|
next CONFIGITEMID if $Version->{InciState} eq $TmpIncidentState;
|
|
}
|
|
|
|
# set new incident state
|
|
$Self->_SetCIStatus(
|
|
Version => $Version,
|
|
IncidentState => $IncidentState,
|
|
TicketID => $TicketID,
|
|
);
|
|
}
|
|
|
|
# current incident state is same as caused by link -> re-calculate
|
|
else {
|
|
|
|
# shortcut: nothing to do if CI is already in lowest incident state
|
|
next CONFIGITEMID if $Version->{InciState} eq $IncidentStates->[-1];
|
|
|
|
# shortcut: nothing to do if CI is not in same incident state
|
|
next CONFIGITEMID if $Version->{InciState} ne $IncidentState;
|
|
|
|
# recalculate incident state exactly
|
|
$Self->_CheckLowerIncidentState(
|
|
Version => $Version,
|
|
IncidentStates => $IncidentStates,
|
|
LinkTypesByIncidentState => \%LinkTypesByIncidentState,
|
|
TicketID => $TicketID,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# unknown/irrelevant event
|
|
else {
|
|
return 1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
# Rationale:
|
|
# Start at highest (worst) incident state and loop down to current incident state,
|
|
# checking for links on all types configured for the corresponding incident state.
|
|
# If any link for a higher incident state than the current one is found,
|
|
# set this state and exit.
|
|
# Due to top-to-bottom method, no higher incident state can occur later.
|
|
sub _CheckRaiseIncidentState {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# check needed stuff
|
|
for my $Needed (qw(Version IncidentStates LinkTypesByIncidentState TicketID)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# loop through target states and check if it needs to be changed
|
|
INCIDENTSTATE:
|
|
for my $IncidentState ( @{ $Param{IncidentStates} } ) {
|
|
|
|
# CI already in target state - nothing to do
|
|
return 1 if $Param{Version}->{InciState} eq $IncidentState;
|
|
|
|
# check if we have linked tickets that lead to incident state
|
|
LINKTYPE:
|
|
for my $LinkType ( @{ $Param{LinkTypesByIncidentState}->{$IncidentState} } ) {
|
|
next LINKTYPE if !$Self->_CheckConfigItemLinks(
|
|
ConfigItemID => $Param{Version}->{ConfigItemID},
|
|
Type => $LinkType,
|
|
);
|
|
|
|
# we have at least one linked ticket - set incident state and exit
|
|
return $Self->_SetCIStatus(
|
|
Version => $Param{Version},
|
|
IncidentState => $IncidentState,
|
|
TicketID => $Param{TicketID},
|
|
);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
# Rationale:
|
|
# Shortcut if CI is alredy in lowest (best) incident state = can't have changed after link delete.
|
|
# Start at highest (worst) incident state and loop down to current incident state,
|
|
# checking for links on all types configured for the corresponding incident states.
|
|
# If a link for the current incident state is found, exit immediately (no change).
|
|
# Otherwise set incident state for first occurance of a link, then exit.
|
|
# If no link is found, set the lowest state.
|
|
# Due to top-to-bottom method, first remembered incident state is the highest possible.
|
|
sub _CheckLowerIncidentState {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# check needed stuff
|
|
for my $Needed (qw(Version IncidentStates LinkTypesByIncidentState TicketID)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# shortcut for lowest level
|
|
return 1 if $Param{Version}->{InciState} eq $Param{IncidentStates}->[-1];
|
|
|
|
# loop through target states and check if it needs to be changed
|
|
my $LowerIncidentState;
|
|
INCIDENTSTATE:
|
|
for my $IncidentState ( @{ $Param{IncidentStates} } ) {
|
|
|
|
# skip level if current CI incident state is not on this or any higher level
|
|
next INCIDENTSTATE if $Param{Version}->{InciState} ne $IncidentState && !$LowerIncidentState;
|
|
|
|
# check if we have linked tickets that keep incident state
|
|
LINKTYPE:
|
|
for my $LinkType ( @{ $Param{LinkTypesByIncidentState}->{$IncidentState} } ) {
|
|
next LINKTYPE if !$Self->_CheckConfigItemLinks(
|
|
ConfigItemID => $Param{Version}->{ConfigItemID},
|
|
Type => $LinkType,
|
|
);
|
|
|
|
# we have at least one linked ticket
|
|
|
|
# keep incident state
|
|
return 1 if $Param{Version}->{InciState} eq $IncidentState;
|
|
|
|
# otherwise set new (lower) incident state and exit
|
|
return $Self->_SetCIStatus(
|
|
Version => $Param{Version},
|
|
IncidentState => $IncidentState,
|
|
TicketID => $Param{TicketID},
|
|
);
|
|
}
|
|
|
|
# remember that state needs to be changed (= current level isn'T justified by links anymore)
|
|
$LowerIncidentState = 1;
|
|
}
|
|
|
|
# no relevant links have been found, but CI wasn't in lowest incident state before - set it now and exit
|
|
return $Self->_SetCIStatus(
|
|
Version => $Param{Version},
|
|
IncidentState => $Param{IncidentStates}->[-1],
|
|
TicketID => $Param{TicketID},
|
|
);
|
|
}
|
|
|
|
# set CI to a specified incident state and log change in corresponding ticket
|
|
sub _SetCIStatus {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# check needed stuff
|
|
for my $Needed (qw(Version IncidentState TicketID)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
# get incident state list
|
|
my $IncidentStateList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
|
|
Class => 'ITSM::Core::IncidentState',
|
|
);
|
|
return if !IsHashRefWithData($IncidentStateList);
|
|
|
|
# check if incident state is valid
|
|
my %ReverseIncidentStateList = reverse %{$IncidentStateList};
|
|
if ( !$ReverseIncidentStateList{ $Param{IncidentState} } ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Have invalid incident state '$Param{IncidentState}'!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# add a new version with the new incident state
|
|
my $VersionID = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->VersionAdd(
|
|
%{ $Param{Version} },
|
|
InciStateID => $ReverseIncidentStateList{ $Param{IncidentState} },
|
|
UserID => 1,
|
|
);
|
|
return if !$VersionID;
|
|
|
|
# log change in ticket
|
|
$Kernel::OM->Get('Kernel::System::Ticket')->HistoryAdd(
|
|
TicketID => $Param{TicketID},
|
|
HistoryType => 'Misc',
|
|
Name => "Updated incident state of config item '$Param{Version}->{Number}' to '$Param{IncidentState}'.",
|
|
CreateUserID => 1,
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
# check if relevant CIs are linked to a ticket
|
|
sub _CheckTicketLinks {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# check needed stuff
|
|
for my $Needed (qw(TicketID Type)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# get link type lookup
|
|
my $LinkTypeLookup = $Self->_LinkTypeLookupGet();
|
|
|
|
my %LinkKeyList = $Kernel::OM->Get('Kernel::System::LinkObject')->LinkKeyList(
|
|
Object1 => 'Ticket',
|
|
Key1 => $Param{TicketID},
|
|
Object2 => 'ITSMConfigItem',
|
|
State => 'Valid',
|
|
Type => $LinkTypeLookup->{ $Param{Type} }->{Name},
|
|
Direction => $LinkTypeLookup->{ $Param{Type} }->{Direction}->{Ticket},
|
|
UserID => 1,
|
|
);
|
|
return if !IsHashRefWithData( \%LinkKeyList );
|
|
return ( sort keys %LinkKeyList );
|
|
}
|
|
|
|
# check if relevant open tickets are linked to a CI
|
|
sub _CheckConfigItemLinks {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# check needed stuff
|
|
for my $Needed (qw(ConfigItemID Type)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# get link type lookup
|
|
my $LinkTypeLookup = $Self->_LinkTypeLookupGet();
|
|
|
|
my %LinkKeyList = $Kernel::OM->Get('Kernel::System::LinkObject')->LinkKeyList(
|
|
Object1 => 'ITSMConfigItem',
|
|
Key1 => $Param{ConfigItemID},
|
|
Object2 => 'Ticket',
|
|
State => 'Valid',
|
|
Type => $LinkTypeLookup->{ $Param{Type} }->{Name},
|
|
Direction => $LinkTypeLookup->{ $Param{Type} }->{Direction}->{ITSMConfigItem},
|
|
UserID => 1,
|
|
);
|
|
return if !IsHashRefWithData( \%LinkKeyList );
|
|
|
|
# list of relevant state types
|
|
my @OpenStateTypes = ( 'new', 'open', 'pending reminder', 'pending auto' );
|
|
|
|
# use ticket type check?
|
|
my $TicketTypes = $Kernel::OM->Get('Kernel::Config')->Get('ITSMConfigItem::LinkStatus::TicketTypes');
|
|
my $CheckTicketTypes;
|
|
$CheckTicketTypes = 1 if IsArrayRefWithData($TicketTypes);
|
|
|
|
my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
|
|
TICKETID:
|
|
for my $TicketID ( sort keys %LinkKeyList ) {
|
|
my %Ticket = $TicketObject->TicketGet(
|
|
TicketID => $TicketID,
|
|
UserID => 1,
|
|
);
|
|
next TICKETID if !grep { $_ eq $Ticket{StateType} } @OpenStateTypes;
|
|
if ($CheckTicketTypes) {
|
|
next TICKETID if !$Ticket{Type};
|
|
next TICKETID if !grep { $_ eq $Ticket{Type} } @{$TicketTypes};
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
# compile list of internal link type names and directions to use for LinkKeyList
|
|
sub _LinkTypeLookupGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# if we have generated lookup before
|
|
return $Self->{LinkTypeLookup} if $Self->{LinkTypeLookup};
|
|
|
|
my %LinkTypeLookup;
|
|
my %TypeList = $Kernel::OM->Get('Kernel::System::LinkObject')->TypeList();
|
|
for my $TypeNameInternal ( sort keys %TypeList ) {
|
|
my $SourceName = $TypeList{$TypeNameInternal}->{SourceName};
|
|
my $TargetName = $TypeList{$TypeNameInternal}->{TargetName};
|
|
$LinkTypeLookup{$SourceName} = {
|
|
Name => $TypeNameInternal,
|
|
Direction => {
|
|
ITSMConfigItem => $SourceName eq $TargetName ? 'Both' : 'Target',
|
|
Ticket => $SourceName eq $TargetName ? 'Both' : 'Source',
|
|
},
|
|
};
|
|
$LinkTypeLookup{$TargetName} = {
|
|
Name => $TypeNameInternal,
|
|
Direction => {
|
|
ITSMConfigItem => $SourceName eq $TargetName ? 'Both' : 'Source',
|
|
Ticket => $SourceName eq $TargetName ? 'Both' : 'Target',
|
|
},
|
|
};
|
|
}
|
|
|
|
# remember result
|
|
$Self->{LinkTypeLookup} = \%LinkTypeLookup;
|
|
|
|
return \%LinkTypeLookup;
|
|
}
|
|
|
|
1;
|