3047 lines
109 KiB
Perl
3047 lines
109 KiB
Perl
# --
|
|
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
|
|
# --
|
|
# $origin: otrs - aeb33d800716e2a6653597aa86314c4cbdadb678 - Kernel/Modules/AgentTicketPhone.pm
|
|
# --
|
|
# 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::AgentTicketPhone;
|
|
## nofilter(TidyAll::Plugin::OTRS::Perl::DBObject)
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Mail::Address;
|
|
|
|
use Kernel::System::VariableCheck qw(:all);
|
|
use Kernel::Language qw(Translatable);
|
|
|
|
our $ObjectManagerDisabled = 1;
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# allocate new hash for object
|
|
my $Self = {%Param};
|
|
bless( $Self, $Type );
|
|
|
|
#get config object
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# get the dynamic fields for this screen
|
|
$Self->{DynamicField} = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
|
|
Valid => 1,
|
|
ObjectType => [ 'Ticket', 'Article' ],
|
|
FieldFilter => $ConfigObject->Get("Ticket::Frontend::$Self->{Action}")->{DynamicField} || {},
|
|
);
|
|
|
|
# get form id
|
|
$Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' );
|
|
|
|
# create form id
|
|
if ( !$Self->{FormID} ) {
|
|
$Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate();
|
|
}
|
|
# ---
|
|
# ITSMIncidentProblemManagement
|
|
# ---
|
|
|
|
# Check if ITSMIncidentProblemManagement is used.
|
|
my $OutputFilterConfig = $Kernel::OM->Get('Kernel::Config')->Get('Frontend::Output::FilterElementPost');
|
|
if ( $OutputFilterConfig->{ITSMIncidentProblemManagement} ) {
|
|
$Self->{ITSMIncidentProblemManagement} = 1;
|
|
}
|
|
# ---
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub Run {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get params
|
|
my %GetParam;
|
|
|
|
# get param object
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
for my $Key (
|
|
qw(ArticleID LinkTicketID PriorityID NewUserID
|
|
From Subject Body NextStateID TimeUnits
|
|
Year Month Day Hour Minute
|
|
NewResponsibleID ResponsibleAll OwnerAll TypeID ServiceID SLAID
|
|
StandardTemplateID FromChatID Dest
|
|
)
|
|
)
|
|
{
|
|
$GetParam{$Key} = $ParamObject->GetParam( Param => $Key );
|
|
}
|
|
|
|
# ACL compatibility translation
|
|
my %ACLCompatGetParam;
|
|
$ACLCompatGetParam{OwnerID} = $GetParam{NewUserID};
|
|
|
|
# MultipleCustomer From-field
|
|
my @MultipleCustomer;
|
|
my $CustomersNumber = $ParamObject->GetParam( Param => 'CustomerTicketCounterFromCustomer' ) || 0;
|
|
my $Selected = $ParamObject->GetParam( Param => 'CustomerSelected' ) || '';
|
|
|
|
# hash for check duplicated entries
|
|
my %AddressesList;
|
|
|
|
# get check item object
|
|
my $CheckItemObject = $Kernel::OM->Get('Kernel::System::CheckItem');
|
|
|
|
if ($CustomersNumber) {
|
|
my $CustomerCounter = 1;
|
|
for my $Count ( 1 ... $CustomersNumber ) {
|
|
my $CustomerElement = $ParamObject->GetParam( Param => 'CustomerTicketText_' . $Count );
|
|
my $CustomerSelected = ( $Selected eq $Count ? 'checked="checked"' : '' );
|
|
my $CustomerKey = $ParamObject->GetParam( Param => 'CustomerKey_' . $Count )
|
|
|| '';
|
|
|
|
if ($CustomerElement) {
|
|
|
|
my $CountAux = $CustomerCounter++;
|
|
my $CustomerError = '';
|
|
my $CustomerErrorMsg = 'CustomerGenericServerErrorMsg';
|
|
my $CustomerDisabled = '';
|
|
|
|
if ( $GetParam{From} ) {
|
|
$GetParam{From} .= ', ' . $CustomerElement;
|
|
}
|
|
else {
|
|
$GetParam{From} = $CustomerElement;
|
|
}
|
|
|
|
# check email address
|
|
for my $Email ( Mail::Address->parse($CustomerElement) ) {
|
|
if ( !$CheckItemObject->CheckEmail( Address => $Email->address() ) )
|
|
{
|
|
$CustomerErrorMsg = $CheckItemObject->CheckErrorType()
|
|
. 'ServerErrorMsg';
|
|
$CustomerError = 'ServerError';
|
|
}
|
|
}
|
|
|
|
# check for duplicated entries
|
|
if ( defined $AddressesList{$CustomerElement} && $CustomerError eq '' ) {
|
|
$CustomerErrorMsg = 'IsDuplicatedServerErrorMsg';
|
|
$CustomerError = 'ServerError';
|
|
}
|
|
|
|
if ( $CustomerError ne '' ) {
|
|
$CustomerDisabled = 'disabled="disabled"';
|
|
$CountAux = $Count . 'Error';
|
|
}
|
|
|
|
push @MultipleCustomer, {
|
|
Count => $CountAux,
|
|
CustomerElement => $CustomerElement,
|
|
CustomerSelected => $CustomerSelected,
|
|
CustomerKey => $CustomerKey,
|
|
CustomerError => $CustomerError,
|
|
CustomerErrorMsg => $CustomerErrorMsg,
|
|
CustomerDisabled => $CustomerDisabled,
|
|
};
|
|
$AddressesList{$CustomerElement} = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
# get Dynamic fields form ParamObject
|
|
my %DynamicFieldValues;
|
|
# ---
|
|
# ITSMIncidentProblemManagement
|
|
# ---
|
|
# to store the reference to the dynamic field for the impact
|
|
my $ImpactDynamicFieldConfig;
|
|
# ---
|
|
|
|
# get needed objects
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
my $CustomerUserObject = $Kernel::OM->Get('Kernel::System::CustomerUser');
|
|
my $UploadCacheObject = $Kernel::OM->Get('Kernel::System::Web::UploadCache');
|
|
my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
|
|
my $QueueObject = $Kernel::OM->Get('Kernel::System::Queue');
|
|
|
|
my $Config = $ConfigObject->Get("Ticket::Frontend::$Self->{Action}");
|
|
|
|
# cycle trough the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
|
|
# extract the dynamic field value from the web request
|
|
$DynamicFieldValues{ $DynamicFieldConfig->{Name} } = $DynamicFieldBackendObject->EditFieldValueGet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
ParamObject => $ParamObject,
|
|
LayoutObject => $LayoutObject,
|
|
);
|
|
# ---
|
|
# ITSMIncidentProblemManagement
|
|
# ---
|
|
# Impact field was found.
|
|
if ( $DynamicFieldConfig->{Name} eq 'ITSMImpact' ) {
|
|
|
|
# store the reference to the impact field
|
|
$ImpactDynamicFieldConfig = $DynamicFieldConfig;
|
|
}
|
|
# ---
|
|
}
|
|
|
|
# convert dynamic field values into a structure for ACLs
|
|
my %DynamicFieldACLParameters;
|
|
DYNAMICFIELD:
|
|
for my $DynamicField ( sort keys %DynamicFieldValues ) {
|
|
next DYNAMICFIELD if !$DynamicField;
|
|
next DYNAMICFIELD if !$DynamicFieldValues{$DynamicField};
|
|
|
|
$DynamicFieldACLParameters{ 'DynamicField_' . $DynamicField } = $DynamicFieldValues{$DynamicField};
|
|
}
|
|
$GetParam{DynamicField} = \%DynamicFieldACLParameters;
|
|
# ---
|
|
# ITSMIncidentProblemManagement
|
|
# ---
|
|
my %Service;
|
|
|
|
if ( $Self->{ITSMIncidentProblemManagement} ) {
|
|
|
|
# get needed stuff
|
|
$GetParam{DynamicField_ITSMCriticality} = $ParamObject->GetParam(Param => 'DynamicField_ITSMCriticality');
|
|
$GetParam{DynamicField_ITSMImpact} = $ParamObject->GetParam(Param => 'DynamicField_ITSMImpact');
|
|
$GetParam{PriorityRC} = $ParamObject->GetParam(Param => 'PriorityRC');
|
|
$GetParam{ElementChanged} = $ParamObject->GetParam(Param => 'ElementChanged') || '';
|
|
|
|
# check if priority needs to be recalculated
|
|
if ( $GetParam{ElementChanged} eq 'ServiceID' || $GetParam{ElementChanged} eq 'DynamicField_ITSMImpact' || $GetParam{ElementChanged} eq 'DynamicField_ITSMCriticality' ) {
|
|
$GetParam{PriorityRC} = 1;
|
|
}
|
|
|
|
# service was selected
|
|
if ( $GetParam{ServiceID} ) {
|
|
|
|
# get service
|
|
%Service = $Kernel::OM->Get('Kernel::System::Service')->ServiceGet(
|
|
ServiceID => $GetParam{ServiceID},
|
|
IncidentState => $Config->{ShowIncidentState} || 0,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
if ( $GetParam{ElementChanged} eq 'ServiceID' ) {
|
|
$GetParam{DynamicField_ITSMCriticality} = $Service{Criticality};
|
|
}
|
|
|
|
# recalculate impact if impact is not set until now
|
|
if ( !$GetParam{DynamicField_ITSMImpact} && $GetParam{ElementChanged} ne 'DynamicField_ITSMImpact' ) {
|
|
|
|
# get default selection
|
|
my $DefaultSelection = $ImpactDynamicFieldConfig->{Config}->{DefaultValue};
|
|
|
|
if ($DefaultSelection) {
|
|
|
|
# get default impact
|
|
$GetParam{DynamicField_ITSMImpact} = $DefaultSelection;
|
|
$GetParam{PriorityRC} = 1;
|
|
}
|
|
}
|
|
|
|
# recalculate priority
|
|
if ( $GetParam{PriorityRC} && $GetParam{DynamicField_ITSMImpact} ) {
|
|
|
|
# get priority
|
|
$GetParam{PriorityID} = $Kernel::OM->Get('Kernel::System::ITSMCIPAllocate')->PriorityAllocationGet(
|
|
Criticality => $GetParam{DynamicField_ITSMCriticality} || $Service{Criticality},
|
|
Impact => $GetParam{DynamicField_ITSMImpact},
|
|
);
|
|
}
|
|
}
|
|
|
|
# no service was selected
|
|
else {
|
|
|
|
# do not show the default selection
|
|
$ImpactDynamicFieldConfig->{Config}->{DefaultValue} = '';
|
|
|
|
# show only the empty selection
|
|
$ImpactDynamicFieldConfig->{Config}->{PossibleValues} = {};
|
|
$GetParam{DynamicField_ITSMImpact} = '';
|
|
}
|
|
|
|
# set the selected impact and criticality
|
|
$DynamicFieldValues{ITSMCriticality} = $GetParam{DynamicField_ITSMCriticality};
|
|
$DynamicFieldValues{ITSMImpact} = $GetParam{DynamicField_ITSMImpact};
|
|
|
|
# Send config data to JS.
|
|
$LayoutObject->AddJSData(
|
|
Key => $Self->{Action} . 'ShowIncidentState',
|
|
Value => $Config->{ShowIncidentState},
|
|
);
|
|
}
|
|
|
|
# ---
|
|
|
|
# transform pending time, time stamp based on user time zone
|
|
if (
|
|
defined $GetParam{Year}
|
|
&& defined $GetParam{Month}
|
|
&& defined $GetParam{Day}
|
|
&& defined $GetParam{Hour}
|
|
&& defined $GetParam{Minute}
|
|
)
|
|
{
|
|
%GetParam = $LayoutObject->TransformDateSelection(
|
|
%GetParam,
|
|
);
|
|
}
|
|
|
|
if ( $GetParam{FromChatID} ) {
|
|
if ( !$ConfigObject->Get('ChatEngine::Active') ) {
|
|
return $LayoutObject->FatalError(
|
|
Message => Translatable('Chat is not active.'),
|
|
);
|
|
}
|
|
|
|
# Ok, take the chat
|
|
my %ChatParticipant = $Kernel::OM->Get('Kernel::System::Chat')->ChatParticipantCheck(
|
|
ChatID => $GetParam{FromChatID},
|
|
ChatterType => 'User',
|
|
ChatterID => $Self->{UserID},
|
|
ChatterActive => 1,
|
|
);
|
|
|
|
if ( !%ChatParticipant ) {
|
|
return $LayoutObject->FatalError(
|
|
Message => Translatable('No permission.'),
|
|
);
|
|
}
|
|
|
|
# Get permissions
|
|
my $PermissionLevel = $Kernel::OM->Get('Kernel::System::Chat')->ChatPermissionLevelGet(
|
|
ChatID => $GetParam{FromChatID},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# Check if observer
|
|
if ( $PermissionLevel ne 'Owner' && $PermissionLevel ne 'Participant' ) {
|
|
return $LayoutObject->FatalError(
|
|
Message => Translatable('No permission.'),
|
|
Comment => $PermissionLevel,
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( !$Self->{Subaction} || $Self->{Subaction} eq 'Created' ) {
|
|
my %Ticket;
|
|
if ( $Self->{TicketID} ) {
|
|
%Ticket = $TicketObject->TicketGet( TicketID => $Self->{TicketID} );
|
|
}
|
|
|
|
# header
|
|
my $Output = $LayoutObject->Header();
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
|
|
# if there is no ticket id!
|
|
if ( $Self->{TicketID} && $Self->{Subaction} eq 'Created' ) {
|
|
|
|
# notify info
|
|
$Output .= $LayoutObject->Notify(
|
|
Info => $LayoutObject->{LanguageObject}->Translate(
|
|
'Ticket "%s" created!',
|
|
$Ticket{TicketNumber},
|
|
),
|
|
Link => $LayoutObject->{Baselink}
|
|
. 'Action=AgentTicketZoom;TicketID='
|
|
. $Ticket{TicketID},
|
|
);
|
|
}
|
|
|
|
# store last queue screen
|
|
if (
|
|
$Self->{LastScreenOverview}
|
|
&& $Self->{LastScreenOverview} !~ /Action=AgentTicketPhone/
|
|
&& $Self->{RequestedURL} !~ /Action=AgentTicketPhone.*LinkTicketID=/
|
|
)
|
|
{
|
|
$Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => 'LastScreenOverview',
|
|
Value => $Self->{RequestedURL},
|
|
);
|
|
}
|
|
|
|
# get split article if given
|
|
# get ArticleID
|
|
my %Article;
|
|
my %CustomerData;
|
|
my $ArticleFrom = '';
|
|
my %SplitTicketData;
|
|
if ( $GetParam{ArticleID} ) {
|
|
|
|
my $Access = $TicketObject->TicketPermission(
|
|
Type => 'ro',
|
|
TicketID => $Self->{TicketID},
|
|
UserID => $Self->{UserID}
|
|
);
|
|
|
|
if ( !$Access ) {
|
|
return $LayoutObject->NoPermission(
|
|
Message => Translatable('You need ro permission!'),
|
|
WithHeader => 'yes',
|
|
);
|
|
}
|
|
|
|
# Get information from original ticket (SplitTicket).
|
|
%SplitTicketData = $TicketObject->TicketGet(
|
|
TicketID => $Self->{TicketID},
|
|
DynamicFields => 1,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
my $ArticleBackendObject = $Kernel::OM->Get('Kernel::System::Ticket::Article')->BackendForArticle(
|
|
TicketID => $Self->{TicketID},
|
|
ArticleID => $GetParam{ArticleID},
|
|
);
|
|
|
|
%Article = $ArticleBackendObject->ArticleGet(
|
|
TicketID => $Self->{TicketID},
|
|
ArticleID => $GetParam{ArticleID},
|
|
);
|
|
|
|
# check if article is from the same TicketID as we checked permissions for.
|
|
if ( $Article{TicketID} ne $Self->{TicketID} ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => $LayoutObject->{LanguageObject}
|
|
->Translate( 'Article does not belong to ticket %s!', $Self->{TicketID} ),
|
|
);
|
|
}
|
|
|
|
$Article{Subject} = $TicketObject->TicketSubjectClean(
|
|
TicketNumber => $Ticket{TicketNumber},
|
|
Subject => $Article{Subject} || '',
|
|
);
|
|
|
|
# save article from for addresses list
|
|
$ArticleFrom = $Article{From};
|
|
|
|
# if To is present
|
|
# and is no a queue
|
|
# and also is no a system address
|
|
# set To as article from
|
|
if ( IsStringWithData( $Article{To} ) ) {
|
|
my %Queues = $QueueObject->QueueList();
|
|
|
|
if ( $ConfigObject->{CustomerPanelOwnSelection} ) {
|
|
for my $Queue ( sort keys %{ $ConfigObject->{CustomerPanelOwnSelection} } ) {
|
|
my $Value = $ConfigObject->{CustomerPanelOwnSelection}->{$Queue};
|
|
$Queues{$Queue} = $Value;
|
|
}
|
|
}
|
|
|
|
my %QueueLookup = reverse %Queues;
|
|
my %SystemAddressLookup
|
|
= reverse $Kernel::OM->Get('Kernel::System::SystemAddress')->SystemAddressList();
|
|
my @ArticleFromAddress;
|
|
my $SystemAddressEmail;
|
|
|
|
if ($ArticleFrom) {
|
|
@ArticleFromAddress = Mail::Address->parse($ArticleFrom);
|
|
$SystemAddressEmail = $ArticleFromAddress[0]->address();
|
|
}
|
|
|
|
if ( !defined $QueueLookup{ $Article{To} } && defined $SystemAddressLookup{$SystemAddressEmail} ) {
|
|
$ArticleFrom = $Article{To};
|
|
}
|
|
}
|
|
|
|
# body preparation for plain text processing
|
|
$Article{Body} = $LayoutObject->ArticleQuote(
|
|
TicketID => $Article{TicketID},
|
|
ArticleID => $GetParam{ArticleID},
|
|
FormID => $Self->{FormID},
|
|
UploadCacheObject => $UploadCacheObject,
|
|
AttachmentsInclude => 1,
|
|
);
|
|
if ( $LayoutObject->{BrowserRichText} ) {
|
|
$Article{ContentType} = 'text/html';
|
|
}
|
|
else {
|
|
$Article{ContentType} = 'text/plain';
|
|
}
|
|
|
|
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
|
|
String => $Article{Body},
|
|
|
|
# Strip out external content if BlockLoadingRemoteContent is enabled.
|
|
NoExtSrcLoad => $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent'),
|
|
|
|
# Disallow potentially unsafe content.
|
|
NoApplet => 1,
|
|
NoObject => 1,
|
|
NoEmbed => 1,
|
|
NoSVG => 1,
|
|
NoJavaScript => 1,
|
|
);
|
|
$Article{Body} = $SafetyCheckResult{String};
|
|
|
|
# show customer info
|
|
if ( $ConfigObject->Get('Ticket::Frontend::CustomerInfoCompose') ) {
|
|
if ( $SplitTicketData{CustomerUserID} ) {
|
|
%CustomerData = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $SplitTicketData{CustomerUserID},
|
|
);
|
|
}
|
|
elsif ( $SplitTicketData{CustomerID} ) {
|
|
%CustomerData = $CustomerUserObject->CustomerUserDataGet(
|
|
CustomerID => $SplitTicketData{CustomerID},
|
|
);
|
|
}
|
|
}
|
|
if ( $SplitTicketData{CustomerUserID} ) {
|
|
my %CustomerUserList = $CustomerUserObject->CustomerSearch(
|
|
UserLogin => $SplitTicketData{CustomerUserID},
|
|
);
|
|
for my $KeyCustomerUserList ( sort keys %CustomerUserList ) {
|
|
$Article{From} = $CustomerUserList{$KeyCustomerUserList};
|
|
}
|
|
}
|
|
}
|
|
|
|
# multiple addresses list
|
|
# check email address
|
|
my $CountFrom = scalar @MultipleCustomer || 1;
|
|
my %CustomerDataFrom;
|
|
if ( $Article{CustomerUserID} ) {
|
|
%CustomerDataFrom = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $Article{CustomerUserID},
|
|
);
|
|
}
|
|
|
|
for my $Email ( Mail::Address->parse($ArticleFrom) ) {
|
|
|
|
my $CountAux = $CountFrom;
|
|
my $CustomerError = '';
|
|
my $CustomerErrorMsg = 'CustomerGenericServerErrorMsg';
|
|
my $CustomerDisabled = '';
|
|
my $CustomerSelected = $CountFrom eq '1' ? 'checked="checked"' : '';
|
|
my $EmailAddress = $Email->address();
|
|
if ( !$CheckItemObject->CheckEmail( Address => $EmailAddress ) )
|
|
{
|
|
$CustomerErrorMsg = $CheckItemObject->CheckErrorType()
|
|
. 'ServerErrorMsg';
|
|
$CustomerError = 'ServerError';
|
|
}
|
|
|
|
# check for duplicated entries
|
|
if ( defined $AddressesList{$Email} && $CustomerError eq '' ) {
|
|
$CustomerErrorMsg = 'IsDuplicatedServerErrorMsg';
|
|
$CustomerError = 'ServerError';
|
|
}
|
|
|
|
if ( $CustomerError ne '' ) {
|
|
$CustomerDisabled = 'disabled="disabled"';
|
|
$CountAux = $CountFrom . 'Error';
|
|
}
|
|
|
|
my $Phrase = '';
|
|
if ( $Email->phrase() ) {
|
|
$Phrase = $Email->phrase();
|
|
}
|
|
|
|
my $CustomerKey = '';
|
|
if (
|
|
defined $CustomerDataFrom{UserEmail}
|
|
&& $CustomerDataFrom{UserEmail} eq $EmailAddress
|
|
)
|
|
{
|
|
$CustomerKey = $Article{CustomerUserID};
|
|
}
|
|
elsif ($EmailAddress) {
|
|
my %List = $CustomerUserObject->CustomerSearch(
|
|
PostMasterSearch => $EmailAddress,
|
|
);
|
|
|
|
for my $UserLogin ( sort keys %List ) {
|
|
|
|
# Set right one if there is more than one customer user with the same email address.
|
|
if ( $Phrase && $List{$UserLogin} =~ /$Phrase/ ) {
|
|
$CustomerKey = $UserLogin;
|
|
}
|
|
}
|
|
}
|
|
|
|
my $CustomerElement = $EmailAddress;
|
|
if ($Phrase) {
|
|
$CustomerElement = $Phrase . " <$EmailAddress>";
|
|
}
|
|
|
|
if ( $CustomerSelected && $CustomerKey ) {
|
|
%CustomerData = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $CustomerKey,
|
|
);
|
|
}
|
|
|
|
push @MultipleCustomer, {
|
|
Count => $CountAux,
|
|
CustomerElement => $CustomerElement,
|
|
CustomerSelected => $CustomerSelected,
|
|
CustomerKey => $CustomerKey,
|
|
CustomerError => $CustomerError,
|
|
CustomerErrorMsg => $CustomerErrorMsg,
|
|
CustomerDisabled => $CustomerDisabled,
|
|
};
|
|
$AddressesList{$EmailAddress} = 1;
|
|
$CountFrom++;
|
|
}
|
|
|
|
# get user preferences
|
|
my %UserPreferences = $Kernel::OM->Get('Kernel::System::User')->GetUserData(
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# store the dynamic fields default values or used specific default values to be used as
|
|
# ACLs info for all fields
|
|
my %DynamicFieldDefaults;
|
|
|
|
# cycle trough the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
next DYNAMICFIELD if !IsHashRefWithData( $DynamicFieldConfig->{Config} );
|
|
next DYNAMICFIELD if !$DynamicFieldConfig->{Name};
|
|
|
|
# get default value from dynamic field config (if any)
|
|
my $DefaultValue = $DynamicFieldConfig->{Config}->{DefaultValue} || '';
|
|
|
|
# override the value from user preferences if is set
|
|
if ( $UserPreferences{ 'UserDynamicField_' . $DynamicFieldConfig->{Name} } ) {
|
|
$DefaultValue = $UserPreferences{ 'UserDynamicField_' . $DynamicFieldConfig->{Name} };
|
|
}
|
|
|
|
next DYNAMICFIELD if $DefaultValue eq '';
|
|
next DYNAMICFIELD if ref $DefaultValue eq 'ARRAY' && !IsArrayRefWithData($DefaultValue);
|
|
|
|
$DynamicFieldDefaults{ 'DynamicField_' . $DynamicFieldConfig->{Name} } = $DefaultValue;
|
|
}
|
|
$GetParam{DynamicField} = \%DynamicFieldDefaults;
|
|
|
|
# create html strings for all dynamic fields
|
|
my %DynamicFieldHTML;
|
|
|
|
my %SplitTicketParam;
|
|
|
|
# in case of split a TicketID and ArticleID are always given, send the TicketID to calculate
|
|
# ACLs based on parent information
|
|
if ( $Self->{TicketID} && $Article{ArticleID} ) {
|
|
$SplitTicketParam{TicketID} = $Self->{TicketID};
|
|
}
|
|
|
|
# fix to bug# 8068 Field & DynamicField preselection on TicketSplit
|
|
# when splitting a ticket the selected attributes must remain in the new ticket screen
|
|
# this information will be available in the SplitTicketParam hash
|
|
if ( $SplitTicketParam{TicketID} ) {
|
|
|
|
# Get information from original ticket (SplitTicket).
|
|
my %SplitTicketData = $TicketObject->TicketGet(
|
|
TicketID => $SplitTicketParam{TicketID},
|
|
DynamicFields => 1,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# set simple IDs to pass them to the mask
|
|
for my $SplitedParam (qw(TypeID ServiceID SLAID PriorityID)) {
|
|
$SplitTicketParam{$SplitedParam} = $SplitTicketData{$SplitedParam};
|
|
}
|
|
|
|
# set StateID as NextStateID
|
|
$SplitTicketParam{NextStateID} = $SplitTicketData{StateID};
|
|
|
|
# set Owner and Responsible
|
|
$SplitTicketParam{UserSelected} = $SplitTicketData{OwnerID};
|
|
$SplitTicketParam{ResponsibleUserSelected} = $SplitTicketData{ResponsibleID};
|
|
|
|
# set additional information needed for Owner and Responsible
|
|
if ( $SplitTicketData{QueueID} ) {
|
|
$SplitTicketParam{QueueID} = $SplitTicketData{QueueID};
|
|
}
|
|
$SplitTicketParam{AllUsers} = 1;
|
|
|
|
# set the selected queue in format ID||Name
|
|
$SplitTicketParam{ToSelected} = $SplitTicketData{QueueID} . '||' . $SplitTicketData{Queue};
|
|
|
|
for my $Key ( sort keys %SplitTicketData ) {
|
|
if ( $Key =~ /DynamicField\_(.*)/ ) {
|
|
$SplitTicketParam{DynamicField}{$1} = $SplitTicketData{$Key};
|
|
delete $SplitTicketParam{$Key};
|
|
}
|
|
}
|
|
}
|
|
|
|
# cycle through the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
|
|
my $PossibleValuesFilter;
|
|
|
|
my $IsACLReducible = $DynamicFieldBackendObject->HasBehavior(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
Behavior => 'IsACLReducible',
|
|
);
|
|
|
|
if ($IsACLReducible) {
|
|
|
|
# get PossibleValues
|
|
my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
);
|
|
|
|
# check if field has PossibleValues property in its configuration
|
|
if ( IsHashRefWithData($PossibleValues) ) {
|
|
|
|
# convert possible values key => value to key => key for ACLs using a Hash slice
|
|
my %AclData = %{$PossibleValues};
|
|
@AclData{ keys %AclData } = keys %AclData;
|
|
|
|
# set possible values filter from ACLs
|
|
my $ACL = $TicketObject->TicketAcl(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
Action => $Self->{Action},
|
|
ReturnType => 'Ticket',
|
|
ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
|
|
Data => \%AclData,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
if ($ACL) {
|
|
my %Filter = $TicketObject->TicketAclData();
|
|
|
|
# convert Filer key => key back to key => value using map
|
|
%{$PossibleValuesFilter} = map { $_ => $PossibleValues->{$_} }
|
|
keys %Filter;
|
|
}
|
|
}
|
|
}
|
|
|
|
# to store dynamic field value from database (or undefined)
|
|
my $Value;
|
|
|
|
# in case of split a TicketID and ArticleID are always given, Get the value
|
|
# from DB this cases
|
|
if ( $Self->{TicketID} && $Article{ArticleID} ) {
|
|
|
|
# select TicketID or ArticleID to get the value depending on dynamic field configuration
|
|
my $ObjectID = $DynamicFieldConfig->{ObjectType} eq 'Ticket'
|
|
? $Self->{TicketID}
|
|
: $Article{ArticleID};
|
|
|
|
# get value stored on the database (split)
|
|
$Value = $DynamicFieldBackendObject->ValueGet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
ObjectID => $ObjectID,
|
|
);
|
|
}
|
|
|
|
# otherwise (on a new ticket). Check if the user has a user specific default value for
|
|
# the dynamic field, otherwise will use Dynamic Field default value
|
|
else {
|
|
|
|
# override the value from user preferences if is set
|
|
if ( $UserPreferences{ 'UserDynamicField_' . $DynamicFieldConfig->{Name} } ) {
|
|
$Value = $UserPreferences{ 'UserDynamicField_' . $DynamicFieldConfig->{Name} };
|
|
}
|
|
}
|
|
|
|
# get field html
|
|
$DynamicFieldHTML{ $DynamicFieldConfig->{Name} } = $DynamicFieldBackendObject->EditFieldRender(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
PossibleValuesFilter => $PossibleValuesFilter,
|
|
Value => $Value,
|
|
LayoutObject => $LayoutObject,
|
|
ParamObject => $ParamObject,
|
|
AJAXUpdate => 1,
|
|
UpdatableFields => $Self->_GetFieldsToUpdate(),
|
|
Mandatory => $Config->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2,
|
|
);
|
|
}
|
|
|
|
# get all attachments meta data
|
|
my @Attachments = $UploadCacheObject->FormIDGetAllFilesMeta(
|
|
FormID => $Self->{FormID},
|
|
);
|
|
|
|
# get and format default subject and body
|
|
my $Subject = $Article{Subject};
|
|
if ( !$Subject ) {
|
|
$Subject = $LayoutObject->Output(
|
|
Template => $Config->{Subject} || '',
|
|
);
|
|
}
|
|
my $Body = $Article{Body} || '';
|
|
if ( !$Body ) {
|
|
$Body = $LayoutObject->Output(
|
|
Template => $Config->{Body} || '',
|
|
);
|
|
}
|
|
|
|
# make sure body is rich text (if body is based on config)
|
|
if ( !$GetParam{ArticleID} && $LayoutObject->{BrowserRichText} ) {
|
|
$Body = $LayoutObject->Ascii2RichText(
|
|
String => $Body,
|
|
);
|
|
}
|
|
|
|
# in case of ticket split set $Self->{QueueID} as the QueueID of the original ticket,
|
|
# in order to set correct ACLs on page load (initial). See bug 8687.
|
|
if (
|
|
IsHashRefWithData( \%SplitTicketParam )
|
|
&& $SplitTicketParam{QueueID}
|
|
&& !$Self->{QueueID}
|
|
)
|
|
{
|
|
$Self->{QueueID} = $SplitTicketParam{QueueID};
|
|
}
|
|
|
|
# Get predefined QueueID (if no queue from split ticket is set).
|
|
if ( !$Self->{QueueID} && $GetParam{Dest} ) {
|
|
|
|
my @QueueParts = split( /\|\|/, $GetParam{Dest} );
|
|
$Self->{QueueID} = $QueueParts[0];
|
|
$SplitTicketParam{ToSelected} = $GetParam{Dest};
|
|
}
|
|
|
|
# html output
|
|
my $Services = $Self->_GetServices(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
CustomerUserID => $CustomerData{UserLogin} || '',
|
|
QueueID => $Self->{QueueID} || 1,
|
|
);
|
|
my $SLAs = $Self->_GetSLAs(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
CustomerUserID => $CustomerData{UserLogin} || '',
|
|
QueueID => $Self->{QueueID} || 1,
|
|
Services => $Services,
|
|
);
|
|
$Output .= $Self->_MaskPhoneNew(
|
|
QueueID => $Self->{QueueID},
|
|
NextStates => $Self->_GetNextStates(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
CustomerUserID => $CustomerData{UserLogin} || '',
|
|
QueueID => $Self->{QueueID} || 1,
|
|
),
|
|
Priorities => $Self->_GetPriorities(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
CustomerUserID => $CustomerData{UserLogin} || '',
|
|
QueueID => $Self->{QueueID} || 1,
|
|
),
|
|
Types => $Self->_GetTypes(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
CustomerUserID => $CustomerData{UserLogin} || '',
|
|
QueueID => $Self->{QueueID} || 1,
|
|
),
|
|
Services => $Services,
|
|
SLAs => $SLAs,
|
|
StandardTemplates => $Self->_GetStandardTemplates(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
QueueID => $Self->{QueueID} || '',
|
|
),
|
|
Users => $Self->_GetUsers(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $Self->{QueueID},
|
|
%SplitTicketParam,
|
|
),
|
|
ResponsibleUsers => $Self->_GetResponsibles(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $Self->{QueueID},
|
|
%SplitTicketParam,
|
|
),
|
|
To => $Self->_GetTos(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
CustomerUserID => $CustomerData{UserLogin} || '',
|
|
QueueID => $Self->{QueueID},
|
|
),
|
|
TimeUnits => $Self->_GetTimeUnits(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
%SplitTicketParam,
|
|
ArticleID => $Article{ArticleID},
|
|
),
|
|
From => $Article{From},
|
|
Subject => $Subject,
|
|
Body => $Body,
|
|
CustomerUser => $SplitTicketData{CustomerUserID},
|
|
CustomerID => $SplitTicketData{CustomerID},
|
|
CustomerData => \%CustomerData,
|
|
Attachments => \@Attachments,
|
|
LinkTicketID => $GetParam{LinkTicketID} || '',
|
|
FromChatID => $GetParam{FromChatID} || '',
|
|
%SplitTicketParam,
|
|
DynamicFieldHTML => \%DynamicFieldHTML,
|
|
MultipleCustomer => \@MultipleCustomer,
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# create new ticket and article
|
|
elsif ( $Self->{Subaction} eq 'StoreNew' ) {
|
|
|
|
my %Error;
|
|
my %StateData;
|
|
if ( $GetParam{NextStateID} ) {
|
|
%StateData = $Kernel::OM->Get('Kernel::System::State')->StateGet(
|
|
ID => $GetParam{NextStateID},
|
|
);
|
|
}
|
|
my $NextState = $StateData{Name} || '';
|
|
my $Dest = $ParamObject->GetParam( Param => 'Dest' ) || '';
|
|
|
|
# see if only a name has been passed
|
|
if ( $Dest && $Dest !~ m{ \A (\d+)? \| \| .+ \z }xms ) {
|
|
|
|
# see if we can get an ID for this queue name
|
|
my $DestID = $QueueObject->QueueLookup(
|
|
Queue => $Dest,
|
|
);
|
|
|
|
if ($DestID) {
|
|
$Dest = $DestID . '||' . $Dest;
|
|
}
|
|
else {
|
|
$Dest = '';
|
|
}
|
|
}
|
|
|
|
my ( $NewQueueID, $To ) = split( /\|\|/, $Dest );
|
|
$GetParam{QueueID} = $NewQueueID;
|
|
|
|
my $CustomerUser = $ParamObject->GetParam( Param => 'CustomerUser' )
|
|
|| $ParamObject->GetParam( Param => 'PreSelectedCustomerUser' )
|
|
|| $ParamObject->GetParam( Param => 'SelectedCustomerUser' )
|
|
|| '';
|
|
my $SelectedCustomerUser = $ParamObject->GetParam( Param => 'SelectedCustomerUser' )
|
|
|| '';
|
|
my $CustomerID = $ParamObject->GetParam( Param => 'CustomerID' ) || '';
|
|
my $ExpandCustomerName = $ParamObject->GetParam( Param => 'ExpandCustomerName' )
|
|
|| 0;
|
|
my %FromExternalCustomer;
|
|
$FromExternalCustomer{Customer} = $ParamObject->GetParam( Param => 'PreSelectedCustomerUser' )
|
|
|| $ParamObject->GetParam( Param => 'CustomerUser' )
|
|
|| '';
|
|
|
|
if ( $ParamObject->GetParam( Param => 'OwnerAllRefresh' ) ) {
|
|
$GetParam{OwnerAll} = 1;
|
|
$ExpandCustomerName = 3;
|
|
}
|
|
if ( $ParamObject->GetParam( Param => 'ResponsibleAllRefresh' ) ) {
|
|
$GetParam{ResponsibleAll} = 1;
|
|
$ExpandCustomerName = 3;
|
|
}
|
|
if ( $ParamObject->GetParam( Param => 'ClearFrom' ) ) {
|
|
$GetParam{From} = '';
|
|
$ExpandCustomerName = 3;
|
|
}
|
|
for my $Count ( 1 .. 2 ) {
|
|
my $Item = $ParamObject->GetParam( Param => "ExpandCustomerName$Count" ) || 0;
|
|
if ( $Count == 1 && $Item ) {
|
|
$ExpandCustomerName = 1;
|
|
}
|
|
elsif ( $Count == 2 && $Item ) {
|
|
$ExpandCustomerName = 2;
|
|
}
|
|
}
|
|
|
|
# rewrap body if no rich text is used
|
|
if ( $GetParam{Body} && !$LayoutObject->{BrowserRichText} ) {
|
|
$GetParam{Body} = $LayoutObject->WrapPlainText(
|
|
MaxCharacters => $ConfigObject->Get('Ticket::Frontend::TextAreaNote'),
|
|
PlainText => $GetParam{Body},
|
|
);
|
|
}
|
|
|
|
# get all attachments meta data
|
|
my @Attachments = $UploadCacheObject->FormIDGetAllFilesMeta(
|
|
FormID => $Self->{FormID},
|
|
);
|
|
|
|
# check pending date
|
|
if ( !$ExpandCustomerName && $StateData{TypeName} && $StateData{TypeName} =~ /^pending/i ) {
|
|
|
|
# create a datetime object based on pending date
|
|
my $PendingDateTimeObject = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
%GetParam,
|
|
Second => 0,
|
|
},
|
|
);
|
|
|
|
# get current system epoch
|
|
my $CurSystemDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
if ( !$PendingDateTimeObject || $PendingDateTimeObject < $CurSystemDateTimeObject ) {
|
|
$Error{'DateInvalid'} = 'ServerError';
|
|
}
|
|
}
|
|
|
|
# create html strings for all dynamic fields
|
|
my %DynamicFieldHTML;
|
|
|
|
# cycle through the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
|
|
my $PossibleValuesFilter;
|
|
|
|
my $IsACLReducible = $DynamicFieldBackendObject->HasBehavior(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
Behavior => 'IsACLReducible',
|
|
);
|
|
|
|
if ($IsACLReducible) {
|
|
|
|
# get PossibleValues
|
|
my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
);
|
|
|
|
# check if field has PossibleValues property in its configuration
|
|
if ( IsHashRefWithData($PossibleValues) ) {
|
|
|
|
# convert possible values key => value to key => key for ACLs using a Hash slice
|
|
my %AclData = %{$PossibleValues};
|
|
@AclData{ keys %AclData } = keys %AclData;
|
|
|
|
# set possible values filter from ACLs
|
|
my $ACL = $TicketObject->TicketAcl(
|
|
%GetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
Action => $Self->{Action},
|
|
ReturnType => 'Ticket',
|
|
ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
|
|
Data => \%AclData,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
if ($ACL) {
|
|
my %Filter = $TicketObject->TicketAclData();
|
|
|
|
# convert Filer key => key back to key => value using map
|
|
%{$PossibleValuesFilter} = map { $_ => $PossibleValues->{$_} }
|
|
keys %Filter;
|
|
}
|
|
}
|
|
}
|
|
|
|
my $ValidationResult;
|
|
|
|
# do not validate on attachment upload
|
|
if ( !$ExpandCustomerName ) {
|
|
|
|
$ValidationResult = $DynamicFieldBackendObject->EditFieldValueValidate(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
PossibleValuesFilter => $PossibleValuesFilter,
|
|
ParamObject => $ParamObject,
|
|
Mandatory =>
|
|
$Config->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2,
|
|
);
|
|
|
|
if ( !IsHashRefWithData($ValidationResult) ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message =>
|
|
$LayoutObject->{LanguageObject}
|
|
->Translate( 'Could not perform validation on field %s!', $DynamicFieldConfig->{Label} ),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
# propagate validation error to the Error variable to be detected by the frontend
|
|
if ( $ValidationResult->{ServerError} ) {
|
|
$Error{ $DynamicFieldConfig->{Name} } = ' ServerError';
|
|
}
|
|
}
|
|
|
|
# get field html
|
|
$DynamicFieldHTML{ $DynamicFieldConfig->{Name} } = $DynamicFieldBackendObject->EditFieldRender(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
PossibleValuesFilter => $PossibleValuesFilter,
|
|
ServerError => $ValidationResult->{ServerError} || '',
|
|
ErrorMessage => $ValidationResult->{ErrorMessage} || '',
|
|
LayoutObject => $LayoutObject,
|
|
ParamObject => $ParamObject,
|
|
AJAXUpdate => 1,
|
|
UpdatableFields => $Self->_GetFieldsToUpdate(),
|
|
Mandatory => $Config->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2,
|
|
);
|
|
}
|
|
|
|
# expand customer name
|
|
my %CustomerUserData;
|
|
if ( $ExpandCustomerName == 1 ) {
|
|
|
|
# search customer
|
|
my %CustomerUserList;
|
|
%CustomerUserList = $CustomerUserObject->CustomerSearch(
|
|
Search => $GetParam{From},
|
|
CustomerUserOnly => 1,
|
|
);
|
|
|
|
# check if just one customer user exists
|
|
# if just one, fillup CustomerUserID and CustomerID
|
|
$Param{CustomerUserListCount} = 0;
|
|
for my $KeyCustomerUser ( sort keys %CustomerUserList ) {
|
|
$Param{CustomerUserListCount}++;
|
|
$Param{CustomerUserListLast} = $CustomerUserList{$KeyCustomerUser};
|
|
$Param{CustomerUserListLastUser} = $KeyCustomerUser;
|
|
}
|
|
if ( $Param{CustomerUserListCount} == 1 ) {
|
|
$GetParam{From} = $Param{CustomerUserListLast};
|
|
$Error{ExpandCustomerName} = 1;
|
|
my %CustomerUserData = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $Param{CustomerUserListLastUser},
|
|
);
|
|
if ( $CustomerUserData{UserCustomerID} ) {
|
|
$CustomerID = $CustomerUserData{UserCustomerID};
|
|
}
|
|
if ( $CustomerUserData{UserLogin} ) {
|
|
$CustomerUser = $CustomerUserData{UserLogin};
|
|
$FromExternalCustomer{Customer} = $CustomerUserData{UserLogin};
|
|
}
|
|
if ( $FromExternalCustomer{Customer} ) {
|
|
my %ExternalCustomerUserData = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $FromExternalCustomer{Customer},
|
|
);
|
|
$FromExternalCustomer{Email} = $ExternalCustomerUserData{UserEmail};
|
|
}
|
|
}
|
|
|
|
# if more than one customer user exist, show list
|
|
# and clean CustomerUserID and CustomerID
|
|
else {
|
|
|
|
# don't check email syntax on multi customer select
|
|
$ConfigObject->Set(
|
|
Key => 'CheckEmailAddresses',
|
|
Value => 0
|
|
);
|
|
$CustomerID = '';
|
|
|
|
# clear from if there is no customer found
|
|
if ( !%CustomerUserList ) {
|
|
$GetParam{From} = '';
|
|
}
|
|
$Error{ExpandCustomerName} = 1;
|
|
}
|
|
}
|
|
|
|
# get from and customer id if customer user is given
|
|
elsif ( $ExpandCustomerName == 2 ) {
|
|
%CustomerUserData = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $CustomerUser,
|
|
);
|
|
my %CustomerUserList = $CustomerUserObject->CustomerSearch(
|
|
UserLogin => $CustomerUser,
|
|
);
|
|
for my $KeyCustomerUser ( sort keys %CustomerUserList ) {
|
|
$GetParam{From} = $CustomerUserList{$KeyCustomerUser};
|
|
}
|
|
if ( $CustomerUserData{UserCustomerID} ) {
|
|
$CustomerID = $CustomerUserData{UserCustomerID};
|
|
}
|
|
if ( $CustomerUserData{UserLogin} ) {
|
|
$CustomerUser = $CustomerUserData{UserLogin};
|
|
}
|
|
if ( $FromExternalCustomer{Customer} ) {
|
|
my %ExternalCustomerUserData = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $FromExternalCustomer{Customer},
|
|
);
|
|
$FromExternalCustomer{Email} = $ExternalCustomerUserData{UserMailString};
|
|
}
|
|
$Error{ExpandCustomerName} = 1;
|
|
}
|
|
|
|
# if a new destination queue is selected
|
|
elsif ( $ExpandCustomerName == 3 ) {
|
|
$Error{NoSubmit} = 1;
|
|
$CustomerUser = $SelectedCustomerUser;
|
|
}
|
|
|
|
# 'just' no submit
|
|
elsif ( $ExpandCustomerName == 4 ) {
|
|
$Error{NoSubmit} = 1;
|
|
}
|
|
|
|
# show customer info
|
|
my %CustomerData;
|
|
if ( $ConfigObject->Get('Ticket::Frontend::CustomerInfoCompose') ) {
|
|
if ( $CustomerUser || $SelectedCustomerUser ) {
|
|
%CustomerData = $CustomerUserObject->CustomerUserDataGet(
|
|
User => $CustomerUser || $SelectedCustomerUser,
|
|
);
|
|
}
|
|
elsif ($CustomerID) {
|
|
%CustomerData = $CustomerUserObject->CustomerUserDataGet(
|
|
CustomerID => $CustomerID,
|
|
);
|
|
}
|
|
}
|
|
|
|
# check email address
|
|
for my $Email ( Mail::Address->parse( $GetParam{From} ) ) {
|
|
if ( !$CheckItemObject->CheckEmail( Address => $Email->address() ) ) {
|
|
$Error{ErrorType} = $CheckItemObject->CheckErrorType() . 'ServerErrorMsg';
|
|
$Error{FromInvalid} = ' ServerError';
|
|
}
|
|
}
|
|
|
|
if ( !$ExpandCustomerName ) {
|
|
if ( !$GetParam{From} )
|
|
{
|
|
$Error{'FromInvalid'} = ' ServerError';
|
|
}
|
|
if ( !$GetParam{Subject} ) {
|
|
$Error{'SubjectInvalid'} = ' ServerError';
|
|
}
|
|
if ( !$NewQueueID ) {
|
|
$Error{'DestinationInvalid'} = ' ServerError';
|
|
}
|
|
if (
|
|
$ConfigObject->Get('Ticket::Service')
|
|
&& $GetParam{SLAID}
|
|
&& !$GetParam{ServiceID}
|
|
)
|
|
{
|
|
$Error{'ServiceInvalid'} = ' ServerError';
|
|
}
|
|
|
|
# check mandatory service
|
|
if (
|
|
$ConfigObject->Get('Ticket::Service')
|
|
&& $Config->{ServiceMandatory}
|
|
&& !$GetParam{ServiceID}
|
|
)
|
|
{
|
|
$Error{'ServiceInvalid'} = ' ServerError';
|
|
}
|
|
|
|
# check mandatory sla
|
|
if (
|
|
$ConfigObject->Get('Ticket::Service')
|
|
&& $Config->{SLAMandatory}
|
|
&& !$GetParam{SLAID}
|
|
)
|
|
{
|
|
$Error{'SLAInvalid'} = ' ServerError';
|
|
}
|
|
|
|
if ( ( !$GetParam{TypeID} ) && ( $ConfigObject->Get('Ticket::Type') ) ) {
|
|
$Error{'TypeIDInvalid'} = ' ServerError';
|
|
}
|
|
if ( !$GetParam{Body} ) {
|
|
$Error{'RichTextInvalid'} = ' ServerError';
|
|
}
|
|
if (
|
|
$ConfigObject->Get('Ticket::Frontend::AccountTime')
|
|
&& $ConfigObject->Get('Ticket::Frontend::NeedAccountedTime')
|
|
&& $GetParam{TimeUnits} eq ''
|
|
)
|
|
{
|
|
$Error{'TimeUnitsInvalid'} = ' ServerError';
|
|
}
|
|
}
|
|
|
|
if (%Error) {
|
|
|
|
# get and format default subject and body
|
|
my $Subject = $LayoutObject->Output(
|
|
Template => $Config->{Subject} || '',
|
|
);
|
|
|
|
my $Body = $LayoutObject->Output(
|
|
Template => $Config->{Body} || '',
|
|
);
|
|
|
|
# make sure body is rich text
|
|
if ( $LayoutObject->{BrowserRichText} ) {
|
|
$Body = $LayoutObject->Ascii2RichText(
|
|
String => $Body,
|
|
);
|
|
}
|
|
|
|
#set Body and Subject parameters for Output
|
|
if ( !$GetParam{Subject} ) {
|
|
$GetParam{Subject} = $Subject;
|
|
}
|
|
|
|
if ( !$GetParam{Body} ) {
|
|
$GetParam{Body} = $Body;
|
|
}
|
|
|
|
# get services
|
|
my $Services = $Self->_GetServices(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
QueueID => $NewQueueID || 1,
|
|
);
|
|
|
|
# reset previous ServiceID to reset SLA-List if no service is selected
|
|
if ( !$GetParam{ServiceID} || !$Services->{ $GetParam{ServiceID} } ) {
|
|
$GetParam{ServiceID} = '';
|
|
}
|
|
|
|
my $SLAs = $Self->_GetSLAs(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || $SelectedCustomerUser || '',
|
|
QueueID => $NewQueueID || 1,
|
|
Services => $Services,
|
|
);
|
|
|
|
# header
|
|
my $Output = $LayoutObject->Header();
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
|
|
# html output
|
|
$Output .= $Self->_MaskPhoneNew(
|
|
QueueID => $Self->{QueueID},
|
|
Users => $Self->_GetUsers(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $NewQueueID,
|
|
AllUsers => $GetParam{OwnerAll},
|
|
),
|
|
UserSelected => $GetParam{NewUserID},
|
|
ResponsibleUsers => $Self->_GetResponsibles(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $NewQueueID,
|
|
AllUsers => $GetParam{ResponsibleAll}
|
|
),
|
|
ResponsibleUserSelected => $GetParam{NewResponsibleID},
|
|
NextStates => $Self->_GetNextStates(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || $SelectedCustomerUser || '',
|
|
QueueID => $NewQueueID || 1,
|
|
),
|
|
NextState => $NextState,
|
|
Priorities => $Self->_GetPriorities(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || $SelectedCustomerUser || '',
|
|
QueueID => $NewQueueID || 1,
|
|
),
|
|
Types => $Self->_GetTypes(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || $SelectedCustomerUser || '',
|
|
QueueID => $NewQueueID || 1,
|
|
),
|
|
Services => $Services,
|
|
SLAs => $SLAs,
|
|
StandardTemplates => $Self->_GetStandardTemplates(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $NewQueueID || '',
|
|
),
|
|
CustomerID => $LayoutObject->Ascii2Html( Text => $CustomerID ),
|
|
CustomerUser => $CustomerUser,
|
|
CustomerData => \%CustomerData,
|
|
To => $Self->_GetTos(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $NewQueueID
|
|
),
|
|
ToSelected => $Dest,
|
|
Errors => \%Error,
|
|
Attachments => \@Attachments,
|
|
%GetParam,
|
|
DynamicFieldHTML => \%DynamicFieldHTML,
|
|
MultipleCustomer => \@MultipleCustomer,
|
|
FromExternalCustomer => \%FromExternalCustomer,
|
|
);
|
|
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# challenge token check for write action
|
|
$LayoutObject->ChallengeTokenCheck();
|
|
|
|
# create new ticket, do db insert
|
|
my $TicketID = $TicketObject->TicketCreate(
|
|
Title => $GetParam{Subject},
|
|
QueueID => $NewQueueID,
|
|
Subject => $GetParam{Subject},
|
|
Lock => 'unlock',
|
|
TypeID => $GetParam{TypeID},
|
|
ServiceID => $GetParam{ServiceID},
|
|
SLAID => $GetParam{SLAID},
|
|
StateID => $GetParam{NextStateID},
|
|
PriorityID => $GetParam{PriorityID},
|
|
OwnerID => 1,
|
|
CustomerNo => $CustomerID,
|
|
CustomerUser => $SelectedCustomerUser,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# set ticket dynamic fields
|
|
# cycle through the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
next DYNAMICFIELD if $DynamicFieldConfig->{ObjectType} ne 'Ticket';
|
|
|
|
# set the value
|
|
my $Success = $DynamicFieldBackendObject->ValueSet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
ObjectID => $TicketID,
|
|
Value => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
# ---
|
|
# ITSMIncidentProblemManagement
|
|
# ---
|
|
if ( $Self->{ITSMIncidentProblemManagement} && $GetParam{ServiceID} && $Service{Criticality} && !$GetParam{DynamicField_ITSMCriticality} ) {
|
|
|
|
# get config for criticality dynamic field
|
|
my $CriticalityDynamicFieldConfig = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldGet(
|
|
Name => 'ITSMCriticality',
|
|
);
|
|
|
|
# get possible values for criticality
|
|
my $CriticalityPossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
|
|
DynamicFieldConfig => $CriticalityDynamicFieldConfig,
|
|
);
|
|
|
|
# reverse the list to find out the key
|
|
my %ReverseCriticalityPossibleValues = reverse %{ $CriticalityPossibleValues };
|
|
|
|
# set the criticality
|
|
$DynamicFieldBackendObject->ValueSet(
|
|
DynamicFieldConfig => $CriticalityDynamicFieldConfig,
|
|
ObjectID => $TicketID,
|
|
Value => $ReverseCriticalityPossibleValues{ $Service{Criticality} },
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
# ---
|
|
|
|
# get pre loaded attachment
|
|
my @AttachmentData = $UploadCacheObject->FormIDGetAllFilesData(
|
|
FormID => $Self->{FormID},
|
|
);
|
|
|
|
# get submit attachment
|
|
my %UploadStuff = $ParamObject->GetUploadAll(
|
|
Param => 'FileUpload',
|
|
);
|
|
if (%UploadStuff) {
|
|
push @AttachmentData, \%UploadStuff;
|
|
}
|
|
|
|
my $MimeType = 'text/plain';
|
|
if ( $LayoutObject->{BrowserRichText} ) {
|
|
$MimeType = 'text/html';
|
|
|
|
# remove unused inline images
|
|
my @NewAttachmentData;
|
|
ATTACHMENT:
|
|
for my $Attachment (@AttachmentData) {
|
|
my $ContentID = $Attachment->{ContentID};
|
|
if (
|
|
$ContentID
|
|
&& ( $Attachment->{ContentType} =~ /image/i )
|
|
&& ( $Attachment->{Disposition} eq 'inline' )
|
|
)
|
|
{
|
|
my $ContentIDHTMLQuote = $LayoutObject->Ascii2Html(
|
|
Text => $ContentID,
|
|
);
|
|
|
|
# workaround for link encode of rich text editor, see bug#5053
|
|
my $ContentIDLinkEncode = $LayoutObject->LinkEncode($ContentID);
|
|
$GetParam{Body} =~ s/(ContentID=)$ContentIDLinkEncode/$1$ContentID/g;
|
|
|
|
# ignore attachment if not linked in body
|
|
next ATTACHMENT
|
|
if $GetParam{Body} !~ /(\Q$ContentIDHTMLQuote\E|\Q$ContentID\E)/i;
|
|
}
|
|
|
|
# remember inline images and normal attachments
|
|
push @NewAttachmentData, \%{$Attachment};
|
|
}
|
|
@AttachmentData = @NewAttachmentData;
|
|
|
|
# verify html document
|
|
$GetParam{Body} = $LayoutObject->RichTextDocumentComplete(
|
|
String => $GetParam{Body},
|
|
);
|
|
}
|
|
|
|
my $PlainBody = $GetParam{Body};
|
|
|
|
if ( $LayoutObject->{BrowserRichText} ) {
|
|
$PlainBody = $LayoutObject->RichText2Ascii( String => $GetParam{Body} );
|
|
}
|
|
|
|
# check if new owner is given (then send no agent notify)
|
|
my $NoAgentNotify = 0;
|
|
if ( $GetParam{NewUserID} ) {
|
|
$NoAgentNotify = 1;
|
|
}
|
|
my $ArticleObject = $Kernel::OM->Get('Kernel::System::Ticket::Article');
|
|
my $ArticleBackendObject = $ArticleObject->BackendForChannel( ChannelName => 'Phone' );
|
|
my $ArticleID = $ArticleBackendObject->ArticleCreate(
|
|
NoAgentNotify => $NoAgentNotify,
|
|
TicketID => $TicketID,
|
|
SenderType => $Config->{SenderType},
|
|
IsVisibleForCustomer => $Config->{IsVisibleForCustomer},
|
|
From => $GetParam{From},
|
|
To => $To,
|
|
Subject => $GetParam{Subject},
|
|
Body => $GetParam{Body},
|
|
MimeType => $MimeType,
|
|
Charset => $LayoutObject->{UserCharset},
|
|
UserID => $Self->{UserID},
|
|
HistoryType => $Config->{HistoryType},
|
|
HistoryComment => $Config->{HistoryComment} || '%%',
|
|
AutoResponseType => ( $ConfigObject->Get('AutoResponseForWebTickets') )
|
|
? 'auto reply'
|
|
: '',
|
|
OrigHeader => {
|
|
From => $GetParam{From},
|
|
To => $GetParam{To},
|
|
Subject => $GetParam{Subject},
|
|
Body => $PlainBody,
|
|
|
|
},
|
|
Queue => $QueueObject->QueueLookup( QueueID => $NewQueueID ),
|
|
);
|
|
if ( !$ArticleID ) {
|
|
return $LayoutObject->ErrorScreen();
|
|
}
|
|
|
|
# set article dynamic fields
|
|
# cycle through the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
next DYNAMICFIELD if $DynamicFieldConfig->{ObjectType} ne 'Article';
|
|
|
|
# set the value
|
|
my $Success = $DynamicFieldBackendObject->ValueSet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
ObjectID => $ArticleID,
|
|
Value => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# Permissions check were done earlier
|
|
if ( $GetParam{FromChatID} ) {
|
|
my $ChatObject = $Kernel::OM->Get('Kernel::System::Chat');
|
|
my %Chat = $ChatObject->ChatGet(
|
|
ChatID => $GetParam{FromChatID},
|
|
);
|
|
my @ChatMessageList = $ChatObject->ChatMessageList(
|
|
ChatID => $GetParam{FromChatID},
|
|
);
|
|
my $ChatArticleID;
|
|
|
|
if (@ChatMessageList) {
|
|
for my $Message (@ChatMessageList) {
|
|
$Message->{MessageText} = $LayoutObject->Ascii2Html(
|
|
Text => $Message->{MessageText},
|
|
LinkFeature => 1,
|
|
);
|
|
}
|
|
|
|
my $ArticleChatBackend = $ArticleObject->BackendForChannel( ChannelName => 'Chat' );
|
|
$ChatArticleID = $ArticleChatBackend->ArticleCreate(
|
|
TicketID => $TicketID,
|
|
SenderType => $Config->{SenderType},
|
|
ChatMessageList => \@ChatMessageList,
|
|
IsVisibleForCustomer => $Config->{IsVisibleForCustomer},
|
|
UserID => $Self->{UserID},
|
|
HistoryType => $Config->{HistoryType},
|
|
HistoryComment => $Config->{HistoryComment} || '%%',
|
|
);
|
|
}
|
|
if ($ChatArticleID) {
|
|
|
|
# check is customer actively present
|
|
# it means customer has accepted this chat and not left it!
|
|
my $CustomerPresent = $ChatObject->CustomerPresent(
|
|
ChatID => $GetParam{FromChatID},
|
|
Active => 1,
|
|
);
|
|
|
|
my $Success;
|
|
|
|
# if there is no customer present in the chat
|
|
# just remove the chat
|
|
if ( !$CustomerPresent ) {
|
|
$Success = $ChatObject->ChatDelete(
|
|
ChatID => $GetParam{FromChatID},
|
|
);
|
|
}
|
|
|
|
# otherwise set chat status to closed and inform other agents
|
|
else {
|
|
$Success = $ChatObject->ChatUpdate(
|
|
ChatID => $GetParam{FromChatID},
|
|
Status => 'closed',
|
|
Deprecated => 1,
|
|
);
|
|
|
|
# get user data
|
|
my %User = $Kernel::OM->Get('Kernel::System::User')->GetUserData(
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
my $RequesterName = $User{UserFullname};
|
|
$RequesterName ||= $Self->{UserID};
|
|
|
|
my $LeaveMessage = $Kernel::OM->Get('Kernel::Language')->Translate(
|
|
"%s has left the chat.",
|
|
$RequesterName,
|
|
);
|
|
|
|
$Success = $ChatObject->ChatMessageAdd(
|
|
ChatID => $GetParam{FromChatID},
|
|
ChatterID => $Self->{UserID},
|
|
ChatterType => 'User',
|
|
MessageText => $LeaveMessage,
|
|
SystemGenerated => 1,
|
|
);
|
|
|
|
# time after chat will be removed
|
|
my $ChatTTL = $Kernel::OM->Get('Kernel::Config')->Get('ChatEngine::ChatTTL');
|
|
|
|
my $ChatClosedMessage = $Kernel::OM->Get('Kernel::Language')->Translate(
|
|
"This chat has been closed and will be removed in %s hours.",
|
|
$ChatTTL,
|
|
);
|
|
|
|
$Success = $ChatObject->ChatMessageAdd(
|
|
ChatID => $GetParam{FromChatID},
|
|
ChatterID => $Self->{UserID},
|
|
ChatterType => 'User',
|
|
MessageText => $ChatClosedMessage,
|
|
SystemGenerated => 1,
|
|
);
|
|
|
|
# remove all AGENT participants from chat
|
|
my @ParticipantsList = $ChatObject->ChatParticipantList(
|
|
ChatID => $GetParam{FromChatID},
|
|
);
|
|
CHATPARTICIPANT:
|
|
for my $ChatParticipant (@ParticipantsList) {
|
|
|
|
# skip it this participant is not agent
|
|
next CHATPARTICIPANT if $ChatParticipant->{ChatterType} ne 'User';
|
|
|
|
# remove this participants from the chat
|
|
$Success = $ChatObject->ChatParticipantRemove(
|
|
ChatID => $GetParam{FromChatID},
|
|
ChatterID => $ChatParticipant->{ChatterID},
|
|
ChatterType => 'User',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# set owner (if new user id is given)
|
|
if ( $GetParam{NewUserID} ) {
|
|
$TicketObject->TicketOwnerSet(
|
|
TicketID => $TicketID,
|
|
NewUserID => $GetParam{NewUserID},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# set lock
|
|
$TicketObject->TicketLockSet(
|
|
TicketID => $TicketID,
|
|
Lock => 'lock',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# else set owner to current agent but do not lock it
|
|
else {
|
|
$TicketObject->TicketOwnerSet(
|
|
TicketID => $TicketID,
|
|
NewUserID => $Self->{UserID},
|
|
SendNoNotification => 1,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# set responsible (if new user id is given)
|
|
if ( $GetParam{NewResponsibleID} ) {
|
|
$TicketObject->TicketResponsibleSet(
|
|
TicketID => $TicketID,
|
|
NewUserID => $GetParam{NewResponsibleID},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# time accounting
|
|
if ( $GetParam{TimeUnits} ) {
|
|
$TicketObject->TicketAccountTime(
|
|
TicketID => $TicketID,
|
|
ArticleID => $ArticleID,
|
|
TimeUnit => $GetParam{TimeUnits},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# write attachments
|
|
for my $Attachment (@AttachmentData) {
|
|
$ArticleBackendObject->ArticleWriteAttachment(
|
|
%{$Attachment},
|
|
TicketID => $TicketID,
|
|
ArticleID => $ArticleID,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# remove pre submited attachments
|
|
$UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} );
|
|
|
|
# link tickets
|
|
if (
|
|
$GetParam{LinkTicketID}
|
|
&& $Config->{SplitLinkType}
|
|
&& $Config->{SplitLinkType}->{LinkType}
|
|
&& $Config->{SplitLinkType}->{Direction}
|
|
)
|
|
{
|
|
my $Access = $TicketObject->TicketPermission(
|
|
Type => 'ro',
|
|
TicketID => $GetParam{LinkTicketID},
|
|
UserID => $Self->{UserID}
|
|
);
|
|
|
|
if ( !$Access ) {
|
|
return $LayoutObject->NoPermission(
|
|
Message => Translatable('You need ro permission!'),
|
|
WithHeader => 'yes',
|
|
);
|
|
}
|
|
|
|
my $SourceKey = $GetParam{LinkTicketID};
|
|
my $TargetKey = $TicketID;
|
|
|
|
if ( $Config->{SplitLinkType}->{Direction} eq 'Source' ) {
|
|
$SourceKey = $TicketID;
|
|
$TargetKey = $GetParam{LinkTicketID};
|
|
}
|
|
|
|
# link the tickets
|
|
$Kernel::OM->Get('Kernel::System::LinkObject')->LinkAdd(
|
|
SourceObject => 'Ticket',
|
|
SourceKey => $SourceKey,
|
|
TargetObject => 'Ticket',
|
|
TargetKey => $TargetKey,
|
|
Type => $Config->{SplitLinkType}->{LinkType} || 'Normal',
|
|
State => 'Valid',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# closed tickets get unlocked
|
|
if ( $StateData{TypeName} =~ /^close/i ) {
|
|
|
|
# set lock
|
|
$TicketObject->TicketLockSet(
|
|
TicketID => $TicketID,
|
|
Lock => 'unlock',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# set pending time
|
|
elsif ( $StateData{TypeName} =~ /^pending/i ) {
|
|
|
|
# set pending time
|
|
$TicketObject->TicketPendingTimeSet(
|
|
UserID => $Self->{UserID},
|
|
TicketID => $TicketID,
|
|
%GetParam,
|
|
);
|
|
}
|
|
# ---
|
|
# ITSMIncidentProblemManagement
|
|
# ---
|
|
if ( $Self->{ITSMIncidentProblemManagement} ) {
|
|
|
|
# get the temporarily links
|
|
my $TempLinkList = $Kernel::OM->Get('Kernel::System::LinkObject')->LinkList(
|
|
Object => 'Ticket',
|
|
Key => $Self->{FormID},
|
|
State => 'Temporary',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
if ( $TempLinkList && ref $TempLinkList eq 'HASH' && %{$TempLinkList} ) {
|
|
|
|
for my $TargetObjectOrg ( sort keys %{$TempLinkList} ) {
|
|
|
|
# extract typelist
|
|
my $TypeList = $TempLinkList->{$TargetObjectOrg};
|
|
|
|
for my $Type ( sort keys %{$TypeList} ) {
|
|
|
|
# extract direction list
|
|
my $DirectionList = $TypeList->{$Type};
|
|
|
|
for my $Direction ( sort keys %{$DirectionList} ) {
|
|
|
|
for my $TargetKeyOrg ( sort keys %{ $DirectionList->{$Direction} } ) {
|
|
|
|
# delete the temp link
|
|
$Kernel::OM->Get('Kernel::System::LinkObject')->LinkDelete(
|
|
Object1 => 'Ticket',
|
|
Key1 => $Self->{FormID},
|
|
Object2 => $TargetObjectOrg,
|
|
Key2 => $TargetKeyOrg,
|
|
Type => $Type,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
my $SourceObject = $TargetObjectOrg;
|
|
my $SourceKey = $TargetKeyOrg;
|
|
my $TargetObject = 'Ticket';
|
|
my $TargetKey = $TicketID;
|
|
|
|
if ( $Direction eq 'Target' ) {
|
|
$SourceObject = 'Ticket';
|
|
$SourceKey = $TicketID;
|
|
$TargetObject = $TargetObjectOrg;
|
|
$TargetKey = $TargetKeyOrg;
|
|
}
|
|
|
|
# add the permanently link
|
|
my $Success = $Kernel::OM->Get('Kernel::System::LinkObject')->LinkAdd(
|
|
SourceObject => $SourceObject,
|
|
SourceKey => $SourceKey,
|
|
TargetObject => $TargetObject,
|
|
TargetKey => $TargetKey,
|
|
Type => $Type,
|
|
State => 'Valid',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
# ---
|
|
|
|
# get redirect screen
|
|
my $NextScreen = $Self->{UserCreateNextMask} || 'AgentTicketPhone';
|
|
|
|
# redirect
|
|
return $LayoutObject->Redirect(
|
|
OP => "Action=$NextScreen;Subaction=Created;TicketID=$TicketID",
|
|
);
|
|
}
|
|
elsif ( $Self->{Subaction} eq 'AJAXUpdate' ) {
|
|
my $Dest = $ParamObject->GetParam( Param => 'Dest' ) || '';
|
|
my $CustomerUser = $ParamObject->GetParam( Param => 'SelectedCustomerUser' );
|
|
my $ElementChanged = $ParamObject->GetParam( Param => 'ElementChanged' ) || '';
|
|
my $QueueID = '';
|
|
if ( $Dest =~ /^(\d{1,100})\|\|.+?$/ ) {
|
|
$QueueID = $1;
|
|
}
|
|
|
|
# get list type
|
|
my $TreeView = 0;
|
|
if ( $ConfigObject->Get('Ticket::Frontend::ListType') eq 'tree' ) {
|
|
$TreeView = 1;
|
|
}
|
|
|
|
my $Tos = $Self->_GetTos(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
QueueID => $QueueID,
|
|
);
|
|
|
|
my $NewTos;
|
|
|
|
if ($Tos) {
|
|
TOs:
|
|
for my $KeyTo ( sort keys %{$Tos} ) {
|
|
next TOs if ( $Tos->{$KeyTo} eq '-' );
|
|
$NewTos->{"$KeyTo||$Tos->{$KeyTo}"} = $Tos->{$KeyTo};
|
|
}
|
|
}
|
|
my $Users = $Self->_GetUsers(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $QueueID,
|
|
AllUsers => $GetParam{OwnerAll},
|
|
);
|
|
my $ResponsibleUsers = $Self->_GetResponsibles(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $QueueID,
|
|
AllUsers => $GetParam{ResponsibleAll},
|
|
);
|
|
my $NextStates = $Self->_GetNextStates(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
QueueID => $QueueID || 1,
|
|
);
|
|
my $Priorities = $Self->_GetPriorities(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
QueueID => $QueueID || 1,
|
|
);
|
|
my $Services = $Self->_GetServices(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
QueueID => $QueueID || 1,
|
|
);
|
|
my $SLAs = $Self->_GetSLAs(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
QueueID => $QueueID || 1,
|
|
Services => $Services,
|
|
);
|
|
my $StandardTemplates = $Self->_GetStandardTemplates(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
QueueID => $QueueID || '',
|
|
);
|
|
my $Types = $Self->_GetTypes(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
QueueID => $QueueID || 1,
|
|
);
|
|
|
|
# update Dynamic Fields Possible Values via AJAX
|
|
my @DynamicFieldAJAX;
|
|
|
|
# cycle through the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
|
|
my $IsACLReducible = $DynamicFieldBackendObject->HasBehavior(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
Behavior => 'IsACLReducible',
|
|
);
|
|
next DYNAMICFIELD if !$IsACLReducible;
|
|
|
|
my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
);
|
|
|
|
# convert possible values key => value to key => key for ACLs using a Hash slice
|
|
my %AclData = %{$PossibleValues};
|
|
@AclData{ keys %AclData } = keys %AclData;
|
|
|
|
# set possible values filter from ACLs
|
|
my $ACL = $TicketObject->TicketAcl(
|
|
%GetParam,
|
|
%ACLCompatGetParam,
|
|
CustomerUserID => $CustomerUser || '',
|
|
Action => $Self->{Action},
|
|
QueueID => $QueueID || 0,
|
|
ReturnType => 'Ticket',
|
|
ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
|
|
Data => \%AclData,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
if ($ACL) {
|
|
my %Filter = $TicketObject->TicketAclData();
|
|
|
|
# convert Filer key => key back to key => value using map
|
|
%{$PossibleValues} = map { $_ => $PossibleValues->{$_} } keys %Filter;
|
|
}
|
|
|
|
my $DataValues = $DynamicFieldBackendObject->BuildSelectionDataGet(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
PossibleValues => $PossibleValues,
|
|
Value => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
|
|
) || $PossibleValues;
|
|
|
|
# add dynamic field to the list of fields to update
|
|
push @DynamicFieldAJAX, {
|
|
Name => 'DynamicField_' . $DynamicFieldConfig->{Name},
|
|
Data => $DataValues,
|
|
SelectedID => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
|
|
Translation => $DynamicFieldConfig->{Config}->{TranslatableValues} || 0,
|
|
Max => 100,
|
|
};
|
|
}
|
|
|
|
my @TemplateAJAX;
|
|
|
|
# update ticket body and attachements if needed.
|
|
if ( $ElementChanged eq 'StandardTemplateID' ) {
|
|
my @TicketAttachments;
|
|
my $TemplateText;
|
|
|
|
# remove all attachments from the Upload cache
|
|
my $RemoveSuccess = $UploadCacheObject->FormIDRemove(
|
|
FormID => $Self->{FormID},
|
|
);
|
|
if ( !$RemoveSuccess ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Form attachments could not be deleted!",
|
|
);
|
|
}
|
|
|
|
# get the template text and set new attachments if a template is selected
|
|
if ( IsPositiveInteger( $GetParam{StandardTemplateID} ) ) {
|
|
my $TemplateGenerator = $Kernel::OM->Get('Kernel::System::TemplateGenerator');
|
|
|
|
# set template text, replace smart tags (limited as ticket is not created)
|
|
$TemplateText = $TemplateGenerator->Template(
|
|
TemplateID => $GetParam{StandardTemplateID},
|
|
UserID => $Self->{UserID},
|
|
CustomerUserID => $CustomerUser,
|
|
);
|
|
|
|
# create StdAttachmentObject
|
|
my $StdAttachmentObject = $Kernel::OM->Get('Kernel::System::StdAttachment');
|
|
|
|
# add std. attachments to ticket
|
|
my %AllStdAttachments = $StdAttachmentObject->StdAttachmentStandardTemplateMemberList(
|
|
StandardTemplateID => $GetParam{StandardTemplateID},
|
|
);
|
|
for ( sort keys %AllStdAttachments ) {
|
|
my %AttachmentsData = $StdAttachmentObject->StdAttachmentGet( ID => $_ );
|
|
$UploadCacheObject->FormIDAddFile(
|
|
FormID => $Self->{FormID},
|
|
Disposition => 'attachment',
|
|
%AttachmentsData,
|
|
);
|
|
}
|
|
|
|
# send a list of attachments in the upload cache back to the clientside JavaScript
|
|
# which renders then the list of currently uploaded attachments
|
|
@TicketAttachments = $UploadCacheObject->FormIDGetAllFilesMeta(
|
|
FormID => $Self->{FormID},
|
|
);
|
|
|
|
for my $Attachment (@TicketAttachments) {
|
|
$Attachment->{Filesize} = $LayoutObject->HumanReadableDataSize(
|
|
Size => $Attachment->{Filesize},
|
|
);
|
|
}
|
|
}
|
|
|
|
@TemplateAJAX = (
|
|
{
|
|
Name => 'UseTemplateCreate',
|
|
Data => '0',
|
|
},
|
|
{
|
|
Name => 'RichText',
|
|
Data => $TemplateText || '',
|
|
},
|
|
{
|
|
Name => 'TicketAttachments',
|
|
Data => \@TicketAttachments,
|
|
KeepData => 1,
|
|
},
|
|
);
|
|
}
|
|
|
|
my $JSON = $LayoutObject->BuildSelectionJSON(
|
|
[
|
|
{
|
|
Name => 'Dest',
|
|
Data => $NewTos,
|
|
SelectedID => $Dest,
|
|
Translation => 0,
|
|
PossibleNone => 1,
|
|
TreeView => $TreeView,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'NewUserID',
|
|
Data => $Users,
|
|
SelectedID => $GetParam{NewUserID},
|
|
Translation => 0,
|
|
PossibleNone => 1,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'NewResponsibleID',
|
|
Data => $ResponsibleUsers,
|
|
SelectedID => $GetParam{NewResponsibleID},
|
|
Translation => 0,
|
|
PossibleNone => 1,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'NextStateID',
|
|
Data => $NextStates,
|
|
SelectedID => $GetParam{NextStateID},
|
|
Translation => 1,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'PriorityID',
|
|
Data => $Priorities,
|
|
SelectedID => $GetParam{PriorityID},
|
|
Translation => 1,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'ServiceID',
|
|
Data => $Services,
|
|
SelectedID => $GetParam{ServiceID},
|
|
PossibleNone => 1,
|
|
Translation => 0,
|
|
TreeView => $TreeView,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'SLAID',
|
|
Data => $SLAs,
|
|
SelectedID => $GetParam{SLAID},
|
|
PossibleNone => 1,
|
|
Translation => 0,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'StandardTemplateID',
|
|
Data => $StandardTemplates,
|
|
SelectedID => $GetParam{StandardTemplateID},
|
|
PossibleNone => 1,
|
|
Translation => 1,
|
|
Max => 100,
|
|
},
|
|
{
|
|
Name => 'TypeID',
|
|
Data => $Types,
|
|
SelectedID => $GetParam{TypeID},
|
|
PossibleNone => 1,
|
|
Translation => 0,
|
|
Max => 100,
|
|
},
|
|
@DynamicFieldAJAX,
|
|
@TemplateAJAX,
|
|
],
|
|
);
|
|
return $LayoutObject->Attachment(
|
|
ContentType => 'application/json; charset=' . $LayoutObject->{Charset},
|
|
Content => $JSON,
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
}
|
|
else {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => Translatable('No Subaction!'),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
}
|
|
|
|
sub _GetNextStates {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my %NextStates;
|
|
if ( $Param{QueueID} || $Param{TicketID} ) {
|
|
%NextStates = $Kernel::OM->Get('Kernel::System::Ticket')->TicketStateList(
|
|
%Param,
|
|
Action => $Self->{Action},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
return \%NextStates;
|
|
}
|
|
|
|
sub _GetUsers {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get users
|
|
my %ShownUsers;
|
|
my %AllGroupsMembers = $Kernel::OM->Get('Kernel::System::User')->UserList(
|
|
Type => 'Long',
|
|
Valid => 1,
|
|
);
|
|
|
|
# get ticket object
|
|
my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
|
|
|
|
# just show only users with selected custom queue
|
|
if ( $Param{QueueID} && !$Param{AllUsers} ) {
|
|
my @UserIDs = $TicketObject->GetSubscribedUserIDsByQueueID(%Param);
|
|
for my $KeyGroupMember ( sort keys %AllGroupsMembers ) {
|
|
my $Hit = 0;
|
|
for my $UID (@UserIDs) {
|
|
if ( $UID eq $KeyGroupMember ) {
|
|
$Hit = 1;
|
|
}
|
|
}
|
|
if ( !$Hit ) {
|
|
delete $AllGroupsMembers{$KeyGroupMember};
|
|
}
|
|
}
|
|
}
|
|
|
|
# show all system users
|
|
if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::ChangeOwnerToEveryone') ) {
|
|
%ShownUsers = %AllGroupsMembers;
|
|
}
|
|
|
|
# show all users who are owner or rw in the queue group
|
|
elsif ( $Param{QueueID} ) {
|
|
my $GID = $Kernel::OM->Get('Kernel::System::Queue')->GetQueueGroupID( QueueID => $Param{QueueID} );
|
|
my %MemberList = $Kernel::OM->Get('Kernel::System::Group')->PermissionGroupGet(
|
|
GroupID => $GID,
|
|
Type => 'owner',
|
|
);
|
|
for my $KeyMember ( sort keys %MemberList ) {
|
|
if ( $AllGroupsMembers{$KeyMember} ) {
|
|
$ShownUsers{$KeyMember} = $AllGroupsMembers{$KeyMember};
|
|
}
|
|
}
|
|
}
|
|
|
|
# workflow
|
|
my $ACL = $TicketObject->TicketAcl(
|
|
%Param,
|
|
Action => $Self->{Action},
|
|
ReturnType => 'Ticket',
|
|
ReturnSubType => 'Owner',
|
|
Data => \%ShownUsers,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
return { $TicketObject->TicketAclData() } if $ACL;
|
|
|
|
return \%ShownUsers;
|
|
}
|
|
|
|
sub _GetResponsibles {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get users
|
|
my %ShownUsers;
|
|
my %AllGroupsMembers = $Kernel::OM->Get('Kernel::System::User')->UserList(
|
|
Type => 'Long',
|
|
Valid => 1,
|
|
);
|
|
|
|
# get ticket object
|
|
my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
|
|
|
|
# just show only users with selected custom queue
|
|
if ( $Param{QueueID} && !$Param{AllUsers} ) {
|
|
my @UserIDs = $TicketObject->GetSubscribedUserIDsByQueueID(%Param);
|
|
for my $KeyGroupMember ( sort keys %AllGroupsMembers ) {
|
|
my $Hit = 0;
|
|
for my $UID (@UserIDs) {
|
|
if ( $UID eq $KeyGroupMember ) {
|
|
$Hit = 1;
|
|
}
|
|
}
|
|
if ( !$Hit ) {
|
|
delete $AllGroupsMembers{$KeyGroupMember};
|
|
}
|
|
}
|
|
}
|
|
|
|
# show all system users
|
|
if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::ChangeOwnerToEveryone') ) {
|
|
%ShownUsers = %AllGroupsMembers;
|
|
}
|
|
|
|
# show all users who are responsible or rw in the queue group
|
|
elsif ( $Param{QueueID} ) {
|
|
my $GID = $Kernel::OM->Get('Kernel::System::Queue')->GetQueueGroupID( QueueID => $Param{QueueID} );
|
|
my %MemberList = $Kernel::OM->Get('Kernel::System::Group')->PermissionGroupGet(
|
|
GroupID => $GID,
|
|
Type => 'responsible',
|
|
);
|
|
for my $KeyMember ( sort keys %MemberList ) {
|
|
if ( $AllGroupsMembers{$KeyMember} ) {
|
|
$ShownUsers{$KeyMember} = $AllGroupsMembers{$KeyMember};
|
|
}
|
|
}
|
|
}
|
|
|
|
# workflow
|
|
my $ACL = $TicketObject->TicketAcl(
|
|
%Param,
|
|
Action => $Self->{Action},
|
|
ReturnType => 'Ticket',
|
|
ReturnSubType => 'Responsible',
|
|
Data => \%ShownUsers,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
return { $TicketObject->TicketAclData() } if $ACL;
|
|
|
|
return \%ShownUsers;
|
|
}
|
|
|
|
sub _GetPriorities {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get priority
|
|
my %Priorities;
|
|
if ( $Param{QueueID} || $Param{TicketID} ) {
|
|
%Priorities = $Kernel::OM->Get('Kernel::System::Ticket')->TicketPriorityList(
|
|
%Param,
|
|
Action => $Self->{Action},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
return \%Priorities;
|
|
}
|
|
|
|
sub _GetTypes {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get type
|
|
my %Type;
|
|
if ( $Param{QueueID} || $Param{TicketID} ) {
|
|
%Type = $Kernel::OM->Get('Kernel::System::Ticket')->TicketTypeList(
|
|
%Param,
|
|
Action => $Self->{Action},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
return \%Type;
|
|
}
|
|
|
|
sub _GetServices {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get service
|
|
my %Service;
|
|
|
|
# check needed
|
|
return \%Service if !$Param{QueueID} && !$Param{TicketID};
|
|
|
|
# get options for default services for unknown customers
|
|
my $DefaultServiceUnknownCustomer
|
|
= $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Service::Default::UnknownCustomer');
|
|
|
|
# check if no CustomerUserID is selected
|
|
# if $DefaultServiceUnknownCustomer = 0 leave CustomerUserID empty, it will not get any services
|
|
# if $DefaultServiceUnknownCustomer = 1 set CustomerUserID to get default services
|
|
if ( !$Param{CustomerUserID} && $DefaultServiceUnknownCustomer ) {
|
|
$Param{CustomerUserID} = '<DEFAULT>';
|
|
}
|
|
|
|
# get service list
|
|
if ( $Param{CustomerUserID} ) {
|
|
%Service = $Kernel::OM->Get('Kernel::System::Ticket')->TicketServiceList(
|
|
%Param,
|
|
Action => $Self->{Action},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
return \%Service;
|
|
}
|
|
|
|
sub _GetSLAs {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get sla
|
|
my %SLA;
|
|
if ( $Param{ServiceID} && $Param{Services} && %{ $Param{Services} } ) {
|
|
if ( $Param{Services}->{ $Param{ServiceID} } ) {
|
|
%SLA = $Kernel::OM->Get('Kernel::System::Ticket')->TicketSLAList(
|
|
%Param,
|
|
Action => $Self->{Action},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
}
|
|
return \%SLA;
|
|
}
|
|
|
|
sub _GetTos {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# get config object
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# check own selection
|
|
my %NewTos;
|
|
if ( $ConfigObject->Get('Ticket::Frontend::NewQueueOwnSelection') ) {
|
|
%NewTos = %{ $ConfigObject->Get('Ticket::Frontend::NewQueueOwnSelection') };
|
|
}
|
|
else {
|
|
|
|
# SelectionType Queue or SystemAddress?
|
|
my %Tos;
|
|
if ( $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionType') eq 'Queue' ) {
|
|
%Tos = $Kernel::OM->Get('Kernel::System::Ticket')->MoveList(
|
|
%Param,
|
|
Type => 'create',
|
|
Action => $Self->{Action},
|
|
QueueID => $Self->{QueueID},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
else {
|
|
%Tos = $Kernel::OM->Get('Kernel::System::SystemAddress')->SystemAddressQueueList();
|
|
}
|
|
|
|
# get create permission queues
|
|
my %UserGroups = $Kernel::OM->Get('Kernel::System::Group')->PermissionUserGet(
|
|
UserID => $Self->{UserID},
|
|
Type => 'create',
|
|
);
|
|
|
|
my $SystemAddressObject = $Kernel::OM->Get('Kernel::System::SystemAddress');
|
|
my $QueueObject = $Kernel::OM->Get('Kernel::System::Queue');
|
|
|
|
# build selection string
|
|
QUEUEID:
|
|
for my $QueueID ( sort keys %Tos ) {
|
|
|
|
my %QueueData = $QueueObject->QueueGet( ID => $QueueID );
|
|
|
|
# permission check, can we create new tickets in queue
|
|
next QUEUEID if !$UserGroups{ $QueueData{GroupID} };
|
|
|
|
my $String = $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionString')
|
|
|| '<Realname> <<Email>> - Queue: <Queue>';
|
|
$String =~ s/<Queue>/$QueueData{Name}/g;
|
|
$String =~ s/<QueueComment>/$QueueData{Comment}/g;
|
|
|
|
# remove trailing spaces
|
|
if ( !$QueueData{Comment} ) {
|
|
$String =~ s{\s+\z}{};
|
|
}
|
|
|
|
if ( $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionType') ne 'Queue' ) {
|
|
my %SystemAddressData = $SystemAddressObject->SystemAddressGet(
|
|
ID => $Tos{$QueueID},
|
|
);
|
|
$String =~ s/<Realname>/$SystemAddressData{Realname}/g;
|
|
$String =~ s/<Email>/$SystemAddressData{Name}/g;
|
|
}
|
|
$NewTos{$QueueID} = $String;
|
|
}
|
|
}
|
|
|
|
# add empty selection
|
|
$NewTos{''} = '-';
|
|
return \%NewTos;
|
|
}
|
|
|
|
sub _GetTimeUnits {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $AccountedTime = '';
|
|
|
|
# Get accounted time if AccountTime config item is enabled.
|
|
if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::AccountTime') && defined $Param{ArticleID} ) {
|
|
$AccountedTime = $Kernel::OM->Get('Kernel::System::Ticket::Article')->ArticleAccountedTimeGet(
|
|
ArticleID => $Param{ArticleID},
|
|
);
|
|
}
|
|
|
|
return $AccountedTime ? $AccountedTime : '';
|
|
}
|
|
|
|
sub _GetStandardTemplates {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my %Templates;
|
|
my $QueueID = $Param{QueueID} || '';
|
|
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
my $QueueObject = $Kernel::OM->Get('Kernel::System::Queue');
|
|
|
|
if ( !$QueueID ) {
|
|
my $UserDefaultQueue = $ConfigObject->Get('Ticket::Frontend::UserDefaultQueue') || '';
|
|
|
|
if ($UserDefaultQueue) {
|
|
$QueueID = $QueueObject->QueueLookup( Queue => $UserDefaultQueue );
|
|
}
|
|
}
|
|
|
|
# check needed
|
|
return \%Templates if !$QueueID && !$Param{TicketID};
|
|
|
|
if ( !$QueueID && $Param{TicketID} ) {
|
|
|
|
# get QueueID from the ticket
|
|
my %Ticket = $Kernel::OM->Get('Kernel::System::Ticket')->TicketGet(
|
|
TicketID => $Param{TicketID},
|
|
DynamicFields => 0,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
$QueueID = $Ticket{QueueID} || '';
|
|
}
|
|
|
|
# fetch all std. templates
|
|
my %StandardTemplates = $QueueObject->QueueStandardTemplateMemberList(
|
|
QueueID => $QueueID,
|
|
TemplateTypes => 1,
|
|
);
|
|
|
|
# return empty hash if there are no templates for this screen
|
|
return \%Templates if !IsHashRefWithData( $StandardTemplates{Create} );
|
|
|
|
# return just the templates for this screen
|
|
return $StandardTemplates{Create};
|
|
}
|
|
|
|
sub _MaskPhoneNew {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
$Param{FormID} = $Self->{FormID};
|
|
|
|
# get config object
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# get list type
|
|
my $TreeView = 0;
|
|
if ( $ConfigObject->Get('Ticket::Frontend::ListType') eq 'tree' ) {
|
|
$TreeView = 1;
|
|
}
|
|
|
|
# get layout object
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# set JS data
|
|
$LayoutObject->AddJSData(
|
|
Key => 'CustomerSearch',
|
|
Value => {
|
|
ShowCustomerTickets => $ConfigObject->Get('Ticket::Frontend::ShowCustomerTickets'),
|
|
AllowMultipleFrom => $ConfigObject->Get('Ticket::Frontend::AgentTicketPhone::AllowMultipleFrom'),
|
|
},
|
|
);
|
|
|
|
# build string
|
|
$Param{OptionStrg} = $LayoutObject->BuildSelection(
|
|
Data => $Param{Users},
|
|
SelectedID => $Param{UserSelected},
|
|
Class => 'Modernize',
|
|
Translation => 0,
|
|
Name => 'NewUserID',
|
|
PossibleNone => 1,
|
|
);
|
|
|
|
my $Config = $ConfigObject->Get("Ticket::Frontend::$Self->{Action}");
|
|
|
|
# build next states string
|
|
$Param{NextStatesStrg} = $LayoutObject->BuildSelection(
|
|
Data => $Param{NextStates},
|
|
Name => 'NextStateID',
|
|
Class => 'Modernize',
|
|
Translation => 1,
|
|
SelectedValue => $Param{NextState} || $Config->{StateDefault},
|
|
);
|
|
|
|
# build to string
|
|
my %NewTo;
|
|
if ( $Param{To} ) {
|
|
for my $KeyTo ( sort keys %{ $Param{To} } ) {
|
|
$NewTo{"$KeyTo||$Param{To}->{$KeyTo}"} = $Param{To}->{$KeyTo};
|
|
}
|
|
}
|
|
if ( !$Param{ToSelected} ) {
|
|
my $UserDefaultQueue = $ConfigObject->Get('Ticket::Frontend::UserDefaultQueue') || '';
|
|
|
|
if ($UserDefaultQueue) {
|
|
my $QueueID = $Kernel::OM->Get('Kernel::System::Queue')->QueueLookup( Queue => $UserDefaultQueue );
|
|
if ($QueueID) {
|
|
$Param{ToSelected} = "$QueueID||$UserDefaultQueue";
|
|
}
|
|
}
|
|
}
|
|
if ( $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionType') eq 'Queue' ) {
|
|
$Param{ToStrg} = $LayoutObject->AgentQueueListOption(
|
|
Class => 'Validate_Required Modernize',
|
|
Data => \%NewTo,
|
|
Multiple => 0,
|
|
Size => 0,
|
|
Name => 'Dest',
|
|
TreeView => $TreeView,
|
|
SelectedID => $Param{ToSelected},
|
|
OnChangeSubmit => 0,
|
|
);
|
|
}
|
|
else {
|
|
$Param{ToStrg} = $LayoutObject->BuildSelection(
|
|
Class => 'Validate_Required Modernize',
|
|
Data => \%NewTo,
|
|
Name => 'Dest',
|
|
TreeView => $TreeView,
|
|
SelectedID => $Param{ToSelected},
|
|
Translation => 0,
|
|
);
|
|
}
|
|
|
|
# customer info string
|
|
if ( $ConfigObject->Get('Ticket::Frontend::CustomerInfoCompose') ) {
|
|
$Param{CustomerTable} = $LayoutObject->AgentCustomerViewTable(
|
|
Data => $Param{CustomerData},
|
|
Max => $ConfigObject->Get('Ticket::Frontend::CustomerInfoComposeMaxSize'),
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'CustomerTable',
|
|
Data => \%Param,
|
|
);
|
|
}
|
|
|
|
# prepare errors!
|
|
if ( $Param{Errors} ) {
|
|
for my $KeyError ( sort keys %{ $Param{Errors} } ) {
|
|
$Param{$KeyError} = '* ' . $LayoutObject->Ascii2Html( Text => $Param{Errors}->{$KeyError} );
|
|
}
|
|
}
|
|
|
|
# From external
|
|
my $ShowErrors = 1;
|
|
if (
|
|
defined $Param{FromExternalCustomer} &&
|
|
defined $Param{FromExternalCustomer}->{Email} &&
|
|
defined $Param{FromExternalCustomer}->{Customer}
|
|
)
|
|
{
|
|
$ShowErrors = 0;
|
|
$LayoutObject->AddJSData(
|
|
Key => 'FromExternalCustomerName',
|
|
Value => $Param{FromExternalCustomer}->{Customer},
|
|
);
|
|
$LayoutObject->AddJSData(
|
|
Key => 'FromExternalCustomerEmail',
|
|
Value => $Param{FromExternalCustomer}->{Email},
|
|
);
|
|
}
|
|
my $CustomerCounter = 0;
|
|
if ( $Param{MultipleCustomer} ) {
|
|
for my $Item ( @{ $Param{MultipleCustomer} } ) {
|
|
if ( !$ShowErrors ) {
|
|
|
|
# set empty values for errors
|
|
$Item->{CustomerError} = '';
|
|
$Item->{CustomerDisabled} = '';
|
|
$Item->{CustomerErrorMsg} = 'CustomerGenericServerErrorMsg';
|
|
}
|
|
$LayoutObject->Block(
|
|
Name => 'MultipleCustomer',
|
|
Data => $Item,
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => $Item->{CustomerErrorMsg},
|
|
Data => $Item,
|
|
);
|
|
if ( $Item->{CustomerError} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'CustomerErrorExplantion',
|
|
);
|
|
}
|
|
$CustomerCounter++;
|
|
}
|
|
}
|
|
|
|
if ( !$CustomerCounter ) {
|
|
$Param{CustomerHiddenContainer} = 'Hidden';
|
|
}
|
|
|
|
# set customer counter
|
|
$LayoutObject->Block(
|
|
Name => 'MultipleCustomerCounter',
|
|
Data => {
|
|
CustomerCounter => $CustomerCounter++,
|
|
},
|
|
);
|
|
|
|
if ( $Param{FromInvalid} && $Param{Errors} && !$Param{Errors}->{FromErrorType} ) {
|
|
$LayoutObject->Block( Name => 'FromServerErrorMsg' );
|
|
}
|
|
if ( $Param{Errors}->{FromErrorType} || !$ShowErrors ) {
|
|
$Param{FromInvalid} = '';
|
|
}
|
|
|
|
my $DynamicFieldNames = $Self->_GetFieldsToUpdate(
|
|
OnlyDynamicFields => 1
|
|
);
|
|
|
|
# send data to JS
|
|
$LayoutObject->AddJSData(
|
|
Key => 'DynamicFieldNames',
|
|
Value => $DynamicFieldNames,
|
|
);
|
|
|
|
# build type string
|
|
if ( $ConfigObject->Get('Ticket::Type') ) {
|
|
$Param{TypeStrg} = $LayoutObject->BuildSelection(
|
|
Class => 'Modernize Validate_Required' . ( $Param{Errors}->{TypeIDInvalid} || ' ' ),
|
|
Data => $Param{Types},
|
|
Name => 'TypeID',
|
|
SelectedID => $Param{TypeID},
|
|
PossibleNone => 1,
|
|
Sort => 'AlphanumericValue',
|
|
Translation => 0,
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'TicketType',
|
|
Data => {%Param},
|
|
);
|
|
}
|
|
|
|
# build service string
|
|
if ( $ConfigObject->Get('Ticket::Service') ) {
|
|
|
|
$Param{ServiceStrg} = $LayoutObject->BuildSelection(
|
|
Data => $Param{Services},
|
|
Name => 'ServiceID',
|
|
Class => 'Modernize '
|
|
. ( $Config->{ServiceMandatory} ? 'Validate_Required ' : '' )
|
|
. ( $Param{Errors}->{ServiceIDInvalid} || '' ),
|
|
SelectedID => $Param{ServiceID},
|
|
PossibleNone => 1,
|
|
TreeView => $TreeView,
|
|
Sort => 'TreeView',
|
|
Translation => 0,
|
|
Max => 200,
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'TicketService',
|
|
Data => {
|
|
ServiceMandatory => $Config->{ServiceMandatory} || 0,
|
|
%Param,
|
|
},
|
|
);
|
|
|
|
$Param{SLAStrg} = $LayoutObject->BuildSelection(
|
|
Data => $Param{SLAs},
|
|
Name => 'SLAID',
|
|
SelectedID => $Param{SLAID},
|
|
Class => 'Modernize '
|
|
. ( $Config->{SLAMandatory} ? 'Validate_Required ' : '' )
|
|
. ( $Param{Errors}->{SLAInvalid} || '' ),
|
|
PossibleNone => 1,
|
|
Sort => 'AlphanumericValue',
|
|
Translation => 0,
|
|
Max => 200,
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'TicketSLA',
|
|
Data => {
|
|
SLAMandatory => $Config->{SLAMandatory} || 0,
|
|
%Param
|
|
},
|
|
);
|
|
}
|
|
|
|
# check if exists create templates regardless the queue
|
|
my %StandardTemplates = $Kernel::OM->Get('Kernel::System::StandardTemplate')->StandardTemplateList(
|
|
Valid => 1,
|
|
Type => 'Create',
|
|
);
|
|
|
|
# build text template string
|
|
if ( IsHashRefWithData( \%StandardTemplates ) ) {
|
|
$Param{StandardTemplateStrg} = $LayoutObject->BuildSelection(
|
|
Data => $Param{StandardTemplates} || {},
|
|
Name => 'StandardTemplateID',
|
|
SelectedID => $Param{StandardTemplateID} || '',
|
|
Class => 'Modernize',
|
|
PossibleNone => 1,
|
|
Sort => 'AlphanumericValue',
|
|
Translation => 1,
|
|
Max => 200,
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'StandardTemplate',
|
|
Data => {%Param},
|
|
);
|
|
}
|
|
|
|
# build priority string
|
|
if ( !$Param{PriorityID} ) {
|
|
$Param{Priority} = $Config->{Priority};
|
|
}
|
|
$Param{PriorityStrg} = $LayoutObject->BuildSelection(
|
|
Data => $Param{Priorities},
|
|
Name => 'PriorityID',
|
|
SelectedID => $Param{PriorityID},
|
|
SelectedValue => $Param{Priority},
|
|
Class => 'Modernize',
|
|
Translation => 1,
|
|
);
|
|
|
|
# pending data string
|
|
$Param{PendingDateString} = $LayoutObject->BuildDateSelection(
|
|
%Param,
|
|
Format => 'DateInputFormatLong',
|
|
YearPeriodPast => 0,
|
|
YearPeriodFuture => 5,
|
|
DiffTime => $ConfigObject->Get('Ticket::Frontend::PendingDiffTime') || 0,
|
|
Class => $Param{Errors}->{DateInvalid},
|
|
Validate => 1,
|
|
ValidateDateInFuture => 1,
|
|
);
|
|
|
|
# show owner selection
|
|
if ( $ConfigObject->Get('Ticket::Frontend::NewOwnerSelection') ) {
|
|
$LayoutObject->Block(
|
|
Name => 'OwnerSelection',
|
|
Data => \%Param,
|
|
);
|
|
}
|
|
|
|
# show responsible selection
|
|
if (
|
|
$ConfigObject->Get('Ticket::Responsible')
|
|
&& $ConfigObject->Get('Ticket::Frontend::NewResponsibleSelection')
|
|
)
|
|
{
|
|
$Param{ResponsibleUsers}->{''} = '-';
|
|
$Param{ResponsibleOptionStrg} = $LayoutObject->BuildSelection(
|
|
Data => $Param{ResponsibleUsers},
|
|
SelectedID => $Param{ResponsibleUserSelected},
|
|
Name => 'NewResponsibleID',
|
|
Class => 'Modernize',
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'ResponsibleSelection',
|
|
Data => \%Param,
|
|
);
|
|
}
|
|
|
|
# Dynamic fields
|
|
# cycle trough the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
|
|
# skip fields that HTML could not be retrieved
|
|
next DYNAMICFIELD if !IsHashRefWithData(
|
|
$Param{DynamicFieldHTML}->{ $DynamicFieldConfig->{Name} }
|
|
);
|
|
|
|
# get the html strings form $Param
|
|
my $DynamicFieldHTML = $Param{DynamicFieldHTML}->{ $DynamicFieldConfig->{Name} };
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DynamicField',
|
|
Data => {
|
|
Name => $DynamicFieldConfig->{Name},
|
|
Label => $DynamicFieldHTML->{Label},
|
|
Field => $DynamicFieldHTML->{Field},
|
|
},
|
|
);
|
|
|
|
# example of dynamic fields order customization
|
|
$LayoutObject->Block(
|
|
Name => 'DynamicField_' . $DynamicFieldConfig->{Name},
|
|
Data => {
|
|
Name => $DynamicFieldConfig->{Name},
|
|
Label => $DynamicFieldHTML->{Label},
|
|
Field => $DynamicFieldHTML->{Field},
|
|
},
|
|
);
|
|
}
|
|
|
|
# show time accounting box
|
|
if ( $ConfigObject->Get('Ticket::Frontend::AccountTime') ) {
|
|
if ( $ConfigObject->Get('Ticket::Frontend::NeedAccountedTime') ) {
|
|
$LayoutObject->Block(
|
|
Name => 'TimeUnitsLabelMandatory',
|
|
Data => \%Param,
|
|
);
|
|
$Param{TimeUnitsRequired} = 'Validate_Required';
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'TimeUnitsLabel',
|
|
Data => \%Param,
|
|
);
|
|
$Param{TimeUnitsRequired} = '';
|
|
}
|
|
$LayoutObject->Block(
|
|
Name => 'TimeUnits',
|
|
Data => \%Param,
|
|
);
|
|
}
|
|
|
|
# show customer edit link
|
|
my $OptionCustomer = $LayoutObject->Permission(
|
|
Action => 'AdminCustomerUser',
|
|
Type => 'rw',
|
|
);
|
|
|
|
my $ShownOptionsBlock;
|
|
|
|
if ($OptionCustomer) {
|
|
|
|
# check if need to call Options block
|
|
if ( !$ShownOptionsBlock ) {
|
|
$LayoutObject->Block(
|
|
Name => 'TicketOptions',
|
|
Data => {
|
|
%Param,
|
|
},
|
|
);
|
|
|
|
# set flag to "true" in order to prevent calling the Options block again
|
|
$ShownOptionsBlock = 1;
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'OptionCustomer',
|
|
Data => {
|
|
%Param,
|
|
},
|
|
);
|
|
}
|
|
# ---
|
|
# ITSMIncidentProblemManagement
|
|
# ---
|
|
# make sure to show the options block so that the "Link Ticket" option is shown
|
|
# even if spellchecker and OptionCustomer is turned off
|
|
if ( $Self->{ITSMIncidentProblemManagement} && !$ShownOptionsBlock ) {
|
|
$LayoutObject->Block(
|
|
Name => 'TicketOptions',
|
|
Data => {
|
|
%Param,
|
|
},
|
|
);
|
|
|
|
# set flag to "true" in order to prevent calling the Options block again
|
|
$ShownOptionsBlock = 1;
|
|
}
|
|
# ---
|
|
|
|
# show attachments
|
|
ATTACHMENT:
|
|
for my $Attachment ( @{ $Param{Attachments} } ) {
|
|
if (
|
|
$Attachment->{ContentID}
|
|
&& $LayoutObject->{BrowserRichText}
|
|
&& ( $Attachment->{ContentType} =~ /image/i )
|
|
&& ( $Attachment->{Disposition} eq 'inline' )
|
|
)
|
|
{
|
|
next ATTACHMENT;
|
|
}
|
|
|
|
push @{ $Param{AttachmentList} }, $Attachment;
|
|
}
|
|
|
|
# add rich text editor
|
|
if ( $LayoutObject->{BrowserRichText} ) {
|
|
|
|
# use height/width defined for this screen
|
|
$Param{RichTextHeight} = $Config->{RichTextHeight} || 0;
|
|
$Param{RichTextWidth} = $Config->{RichTextWidth} || 0;
|
|
|
|
# set up rich text editor
|
|
$LayoutObject->SetRichTextParameters(
|
|
Data => \%Param,
|
|
);
|
|
}
|
|
|
|
# Permissions have been checked before in Run()
|
|
if ( $Param{FromChatID} ) {
|
|
my @ChatMessages = $Kernel::OM->Get('Kernel::System::Chat')->ChatMessageList(
|
|
ChatID => $Param{FromChatID},
|
|
);
|
|
|
|
for my $Message (@ChatMessages) {
|
|
$Message->{MessageText} = $LayoutObject->Ascii2Html(
|
|
Text => $Message->{MessageText},
|
|
LinkFeature => 1,
|
|
);
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'ChatArticlePreview',
|
|
Data => {
|
|
ChatMessages => \@ChatMessages,
|
|
},
|
|
);
|
|
}
|
|
|
|
# get output back
|
|
return $LayoutObject->Output(
|
|
TemplateFile => 'AgentTicketPhone',
|
|
Data => \%Param,
|
|
);
|
|
}
|
|
|
|
sub _GetFieldsToUpdate {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my @UpdatableFields;
|
|
|
|
# set the fields that can be updatable via AJAXUpdate
|
|
if ( !$Param{OnlyDynamicFields} ) {
|
|
@UpdatableFields = qw(
|
|
TypeID
|
|
Dest
|
|
ServiceID
|
|
SLAID
|
|
NewUserID
|
|
NewResponsibleID
|
|
NextStateID
|
|
PriorityID
|
|
StandardTemplateID
|
|
);
|
|
}
|
|
|
|
# cycle trough the activated Dynamic Fields for this screen
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
|
|
my $IsACLReducible = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->HasBehavior(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
Behavior => 'IsACLReducible',
|
|
);
|
|
next DYNAMICFIELD if !$IsACLReducible;
|
|
|
|
push @UpdatableFields, 'DynamicField_' . $DynamicFieldConfig->{Name};
|
|
}
|
|
|
|
return \@UpdatableFields;
|
|
}
|
|
|
|
1;
|