# -- # 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::ITSMTicketFirstLevelSolutionRate; use strict; use warnings; use Kernel::System::VariableCheck qw(:all); our @ObjectDependencies = ( 'Kernel::Config', 'Kernel::System::DateTime', 'Kernel::System::DB', 'Kernel::System::DynamicField', 'Kernel::System::DynamicField::Backend', 'Kernel::System::Priority', 'Kernel::System::Queue', 'Kernel::System::SLA', 'Kernel::System::Service', 'Kernel::System::State', 'Kernel::System::Ticket', 'Kernel::System::Ticket::Article', 'Kernel::System::Type', 'Kernel::System::User', ); sub new { my ( $Type, %Param ) = @_; # allocate new hash for object my $Self = {}; bless( $Self, $Type ); $Self->{DBSlaveObject} = $Param{DBSlaveObject} || $Kernel::OM->Get('Kernel::System::DB'); # get the dynamic fields for ticket object $Self->{DynamicField} = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet( Valid => 1, ObjectType => ['Ticket'], ); return $Self; } sub GetObjectName { my ( $Self, %Param ) = @_; return 'ITSMTicketFirstLevelSolutionRate'; } sub GetObjectBehaviours { my ( $Self, %Param ) = @_; my %Behaviours = ( ProvidesDashboardWidget => 1, ); return %Behaviours; } sub GetObjectAttributes { my ( $Self, %Param ) = @_; # get user list my %UserList = $Kernel::OM->Get('Kernel::System::User')->UserList( Type => 'Long', Valid => 0, ); # get state list my %StateList = $Kernel::OM->Get('Kernel::System::State')->StateGetStatesByType( StateType => ['closed'], Result => 'HASH', UserID => 1, ); # get queue list my %QueueList = $Kernel::OM->Get('Kernel::System::Queue')->GetAllQueues(); # get priority list my %PriorityList = $Kernel::OM->Get('Kernel::System::Priority')->PriorityList( UserID => 1, ); # get current time to fix bug#3830 my $Today = $Kernel::OM->Create('Kernel::System::DateTime')->Format( Format => '%Y-%m-%d 23:59:59' ); my @ObjectAttributes = ( { Name => 'Queue', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'QueueIDs', Block => 'MultiSelectField', Translation => 0, Values => \%QueueList, }, { Name => 'State', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'StateIDs', Block => 'MultiSelectField', Values => \%StateList, }, { Name => 'Priority', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'PriorityIDs', Block => 'MultiSelectField', Values => \%PriorityList, }, { Name => 'Created in Queue', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'CreatedQueueIDs', Block => 'MultiSelectField', Translation => 0, Values => \%QueueList, }, { Name => 'Created Priority', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'CreatedPriorityIDs', Block => 'MultiSelectField', Values => \%PriorityList, }, { Name => 'Created State', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'CreatedStateIDs', Block => 'MultiSelectField', Values => \%StateList, }, { Name => 'Title', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'Title', Block => 'InputField', }, { Name => 'CustomerUserLogin', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'CustomerUserLogin', Block => 'InputField', }, { Name => 'From', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'From', Block => 'InputField', }, { Name => 'To', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'To', Block => 'InputField', }, { Name => 'Cc', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'Cc', Block => 'InputField', }, { Name => 'Subject', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'Subject', Block => 'InputField', }, { Name => 'Text', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'Body', Block => 'InputField', }, { Name => 'Create Time', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'CreateTime', TimePeriodFormat => 'DateInputFormat', # 'DateInputFormatLong', Block => 'Time', TimeStop => $Today, Values => { TimeStart => 'TicketCreateTimeNewerDate', TimeStop => 'TicketCreateTimeOlderDate', }, }, ); if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Service') ) { # get service list my %Service = $Kernel::OM->Get('Kernel::System::Service')->ServiceList( UserID => 1, ); # get sla list my %SLA = $Kernel::OM->Get('Kernel::System::SLA')->SLAList( UserID => 1, ); my @ObjectAttributeAdd = ( { Name => 'Service', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'ServiceIDs', Block => 'MultiSelectField', Translation => 0, Values => \%Service, }, { Name => 'SLA', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'SLAIDs', Block => 'MultiSelectField', Translation => 0, Values => \%SLA, }, ); unshift @ObjectAttributes, @ObjectAttributeAdd; } if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Type') ) { # get ticket type list my %Type = $Kernel::OM->Get('Kernel::System::Type')->TypeList( UserID => 1, ); my %ObjectAttribute1 = ( Name => 'Type', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'TypeIDs', Block => 'MultiSelectField', Translation => 0, Values => \%Type, ); unshift @ObjectAttributes, \%ObjectAttribute1; } if ( $Kernel::OM->Get('Kernel::Config')->Get('Stats::UseAgentElementInStats') ) { my @ObjectAttributeAdd = ( { Name => 'Agent/Owner', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'OwnerIDs', Block => 'MultiSelectField', Translation => 0, Values => \%UserList, }, { Name => 'Created by Agent/Owner', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'CreatedUserIDs', Block => 'MultiSelectField', Translation => 0, Values => \%UserList, }, { Name => 'Responsible', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'ResponsibleIDs', Block => 'MultiSelectField', Translation => 0, Values => \%UserList, }, ); push @ObjectAttributes, @ObjectAttributeAdd; } if ( $Kernel::OM->Get('Kernel::Config')->Get('Stats::CustomerIDAsMultiSelect') ) { # Get CustomerID # (This way also can be the solution for the CustomerUserID) $Self->{DBSlaveObject}->Prepare( SQL => 'SELECT DISTINCT customer_id FROM ticket', ); # fetch the result my %CustomerID; while ( my @Row = $Self->{DBSlaveObject}->FetchrowArray() ) { if ( $Row[0] ) { $CustomerID{ $Row[0] } = $Row[0]; } } my %ObjectAttribute = ( Name => 'CustomerID', UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => 'CustomerID', Block => 'MultiSelectField', Values => \%CustomerID, ); push @ObjectAttributes, \%ObjectAttribute; } else { my %ObjectAttribute = ( Name => 'CustomerID', UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => 'CustomerID', Block => 'InputField', ); push @ObjectAttributes, \%ObjectAttribute; } # cycle trough the activated Dynamic Fields for this screen DYNAMICFIELD: for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) { next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); my $PossibleValuesFilter; # set possible values filter from ACLs my $ACL = $Kernel::OM->Get('Kernel::System::Ticket')->TicketAcl( Action => 'AgentStats', Type => 'DynamicField_' . $DynamicFieldConfig->{Name}, ReturnType => 'Ticket', ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name}, Data => $DynamicFieldConfig->{Config}->{PossibleValues} || {}, UserID => 1, ); if ($ACL) { my %Filter = $Kernel::OM->Get('Kernel::System::Ticket')->TicketAclData(); $PossibleValuesFilter = \%Filter; } # get field html my $DynamicFieldStatsParameter = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->StatsFieldParameterBuild( DynamicFieldConfig => $DynamicFieldConfig, PossibleValuesFilter => $PossibleValuesFilter, ); if ( IsHashRefWithData($DynamicFieldStatsParameter) ) { if ( IsHashRefWithData( $DynamicFieldStatsParameter->{Values} ) ) { my %ObjectAttribute = ( Name => $DynamicFieldStatsParameter->{Name}, UseAsXvalue => 1, UseAsValueSeries => 1, UseAsRestriction => 1, Element => $DynamicFieldStatsParameter->{Element}, Block => 'MultiSelectField', Values => $DynamicFieldStatsParameter->{Values}, Translation => 0, ); push @ObjectAttributes, \%ObjectAttribute; } else { my %ObjectAttribute = ( Name => $DynamicFieldStatsParameter->{Name}, UseAsXvalue => 0, UseAsValueSeries => 0, UseAsRestriction => 1, Element => $DynamicFieldStatsParameter->{Element}, Block => 'InputField', ); push @ObjectAttributes, \%ObjectAttribute; } } } return @ObjectAttributes; } sub GetStatElementPreview { my ( $Self, %Param ) = @_; return int rand 50; } sub GetStatElement { my ( $Self, %Param ) = @_; # use all closed stats if no states are given if ( !$Param{StateIDs} ) { $Param{StateType} = ['closed']; } # start ticket search my @TicketSearchIDs = $Kernel::OM->Get('Kernel::System::Ticket')->TicketSearch( %Param, Result => 'ARRAY', Limit => 100_000_000, UserID => 1, Permission => 'ro', ); return 0 if !@TicketSearchIDs; my $ArticleObject = $Kernel::OM->Get('Kernel::System::Ticket::Article'); my $FirstLevelSolutionTickets = 0; TICKETID: for my $TicketID (@TicketSearchIDs) { my @Articles = $ArticleObject->ArticleList( TicketID => $TicketID, IsVisibleForCustomer => 1, ); next TICKETID if !@Articles; next TICKETID if scalar @Articles > 2; # get sender type of first article my $SenderTypeFirstArticle = $ArticleObject->ArticleSenderTypeLookup( SenderTypeID => $Articles[0]->{SenderTypeID}, ); next TICKETID if $SenderTypeFirstArticle eq 'system'; # if the ticket could be solved within the first contact if ( !$Articles[1] ) { $FirstLevelSolutionTickets++; next TICKETID; } # noe we handle the case where the first article is from the customer next TICKETID if $SenderTypeFirstArticle ne 'customer'; # get sender type of second article my $SenderTypeSecondArticle = $ArticleObject->ArticleSenderTypeLookup( SenderTypeID => $Articles[1]->{SenderTypeID}, ); # the scond article is from the agent next TICKETID if $SenderTypeSecondArticle ne 'agent'; $FirstLevelSolutionTickets++; } return $FirstLevelSolutionTickets; } sub ExportWrapper { my ( $Self, %Param ) = @_; return \%Param; } sub ImportWrapper { my ( $Self, %Param ) = @_; return \%Param; } 1;