1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9package Kernel::Modules::AgentTicketProcess;
10
11use strict;
12use warnings;
13
14use Kernel::System::VariableCheck qw(:all);
15use Kernel::Language qw(Translatable);
16
17our $ObjectManagerDisabled = 1;
18
19sub new {
20    my ( $Type, %Param ) = @_;
21
22    # allocate new hash for object
23    my $Self = {%Param};
24    bless $Self, $Type;
25
26    # global config hash for id dissolution
27    $Self->{NameToID} = {
28        Title          => 'Title',
29        State          => 'StateID',
30        StateID        => 'StateID',
31        Priority       => 'PriorityID',
32        PriorityID     => 'PriorityID',
33        Lock           => 'LockID',
34        LockID         => 'LockID',
35        Queue          => 'QueueID',
36        QueueID        => 'QueueID',
37        Customer       => 'CustomerID',
38        CustomerID     => 'CustomerID',
39        CustomerNo     => 'CustomerID',
40        CustomerUserID => 'CustomerUserID',
41        Owner          => 'OwnerID',
42        OwnerID        => 'OwnerID',
43        Type           => 'TypeID',
44        TypeID         => 'TypeID',
45        SLA            => 'SLAID',
46        SLAID          => 'SLAID',
47        Service        => 'ServiceID',
48        ServiceID      => 'ServiceID',
49        Responsible    => 'ResponsibleID',
50        ResponsibleID  => 'ResponsibleID',
51        PendingTime    => 'PendingTime',
52        Article        => 'Article',
53    };
54
55    return $Self;
56}
57
58sub Run {
59    my ( $Self, %Param ) = @_;
60
61    # get param object
62    my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
63
64    my $TicketID               = $ParamObject->GetParam( Param => 'TicketID' );
65    my $ActivityDialogEntityID = $ParamObject->GetParam( Param => 'ActivityDialogEntityID' );
66    my $ActivityDialogHashRef;
67
68    # get needed objects
69    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');
70    my $LayoutObject         = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
71    my $TicketObject         = $Kernel::OM->Get('Kernel::System::Ticket');
72
73    $Self->{FirstActivityDialog} = $ParamObject->GetParam( Param => 'FirstActivityDialog' );
74    $Self->{LinkTicketID}        = $ParamObject->GetParam( Param => 'LinkTicketID' ) || '';
75    $Self->{ArticleID}           = $ParamObject->GetParam( Param => 'ArticleID' ) || '';
76
77    # get the ticket information on link actions
78    if ( $Self->{LinkTicketID} ) {
79        my %TicketData = $TicketObject->TicketGet(
80            TicketID => $Self->{LinkTicketID},
81            UserID   => $Self->{UserID},
82            Extended => 1,
83        );
84        $Self->{LinkTicketData} = \%TicketData;
85
86        # set LinkTicketID param for showing on main form
87        $Param{LinkTicketID} = $Self->{LinkTicketID};
88    }
89
90    # get the article information on link actions
91    if ( $Self->{ArticleID} ) {
92        my $ArticleBackendObject = $Kernel::OM->Get('Kernel::System::Ticket::Article')->BackendForArticle(
93            TicketID  => $Self->{LinkTicketID},
94            ArticleID => $Self->{ArticleID},
95        );
96
97        my %Article = $ArticleBackendObject->ArticleGet(
98            TicketID  => $Self->{LinkTicketID},
99            ArticleID => $Self->{ArticleID},
100        );
101
102        $Self->{LinkArticleData} = \%Article;
103
104        # set ArticleID param for showing on main form
105        $Param{ArticleID} = $Self->{ArticleID};
106    }
107
108    if ($TicketID) {
109
110        # check if there is a configured required permission
111        # for the ActivityDialog (if there is one)
112        my $ActivityDialogPermission = 'rw';
113        if ($ActivityDialogEntityID) {
114            $ActivityDialogHashRef = $ActivityDialogObject->ActivityDialogGet(
115                ActivityDialogEntityID => $ActivityDialogEntityID,
116                Interface              => 'AgentInterface',
117            );
118
119            if ( !IsHashRefWithData($ActivityDialogHashRef) ) {
120                return $LayoutObject->ErrorScreen(
121                    Message => $LayoutObject->{LanguageObject}->Translate(
122                        'Couldn\'t get ActivityDialogEntityID "%s"!',
123                        $ActivityDialogEntityID,
124                    ),
125                    Comment => Translatable('Please contact the administrator.'),
126                );
127            }
128
129            if ( $ActivityDialogHashRef->{Permission} ) {
130                $ActivityDialogPermission = $ActivityDialogHashRef->{Permission};
131            }
132        }
133
134        # check permissions
135        my $Access = $TicketObject->TicketPermission(
136            Type     => $ActivityDialogPermission,
137            TicketID => $Self->{TicketID},
138            UserID   => $Self->{UserID}
139        );
140
141        # error screen, don't show ticket
142        if ( !$Access ) {
143            return $LayoutObject->NoPermission(
144                Message =>
145                    $LayoutObject->{LanguageObject}->Translate( 'You need %s permissions!', $ActivityDialogPermission ),
146                WithHeader => 'yes',
147            );
148        }
149
150        # get ACL restrictions
151        my %PossibleActions = ( 1 => $Self->{Action} );
152
153        my $ACL = $TicketObject->TicketAcl(
154            Data          => \%PossibleActions,
155            Action        => $Self->{Action},
156            TicketID      => $Self->{TicketID},
157            ReturnType    => 'Action',
158            ReturnSubType => '-',
159            UserID        => $Self->{UserID},
160        );
161        my %AclAction = $TicketObject->TicketAclActionData();
162
163        # check if ACL restrictions exist
164        if ( $ACL || IsHashRefWithData( \%AclAction ) ) {
165
166            my %AclActionLookup = reverse %AclAction;
167
168            # show error screen if ACL prohibits this action
169            if ( !$AclActionLookup{ $Self->{Action} } ) {
170                return $LayoutObject->NoPermission( WithHeader => 'yes' );
171            }
172        }
173
174        if ( IsHashRefWithData($ActivityDialogHashRef) ) {
175
176            # check if it's already locked by somebody else
177            if ( $ActivityDialogHashRef->{RequiredLock} ) {
178
179                if ( $TicketObject->TicketLockGet( TicketID => $TicketID ) ) {
180                    my $AccessOk = $TicketObject->OwnerCheck(
181                        TicketID => $TicketID,
182                        OwnerID  => $Self->{UserID},
183                    );
184                    if ( !$AccessOk ) {
185                        my $Output = $LayoutObject->Header(
186                            Type => 'Small',
187                        );
188                        $Output .= $LayoutObject->Warning(
189                            Message => Translatable('Sorry, you need to be the ticket owner to perform this action.'),
190                            Comment => Translatable('Please change the owner first.'),
191                        );
192                        $Output .= $LayoutObject->Footer(
193                            Type => 'Small',
194                        );
195                        return $Output;
196                    }
197                }
198                else {
199
200                    my %Ticket = $TicketObject->TicketGet(
201                        TicketID => $TicketID,
202                    );
203
204                    my $Lock = $TicketObject->TicketLockSet(
205                        TicketID => $TicketID,
206                        Lock     => 'lock',
207                        UserID   => $Self->{UserID}
208                    );
209
210                    # Set new owner if ticket owner is different then logged user.
211                    if ( $Lock && ( $Ticket{OwnerID} != $Self->{UserID} ) ) {
212
213                        # Remember previous owner, which will be used to restore ticket owner on undo action.
214                        $Param{PreviousOwner} = $Ticket{OwnerID};
215
216                        my $Success = $TicketObject->TicketOwnerSet(
217                            TicketID  => $TicketID,
218                            UserID    => $Self->{UserID},
219                            NewUserID => $Self->{UserID},
220                        );
221
222                        # Reload the parent window to show the updated lock state.
223                        $Param{ParentReload} = 1;
224
225                        # Show lock state link.
226                        $Param{RenderLocked} = 1;
227                    }
228
229                    my $TicketNumber = $TicketObject->TicketNumberLookup(
230                        TicketID => $TicketID,
231                        UserID   => $Self->{UserID},
232                    );
233
234                    # notify the agent that the ticket was locked
235                    push @{ $Param{Notify} }, {
236                        Priority => 'Notice',
237                        Data     => "$TicketNumber: " . $LayoutObject->{LanguageObject}->Translate("Ticket locked."),
238                    };
239                }
240            }
241
242            my $PossibleActivityDialogs = { 1 => $ActivityDialogEntityID };
243
244            # get ACL restrictions
245            my $ACL = $TicketObject->TicketAcl(
246                Data                   => $PossibleActivityDialogs,
247                ActivityDialogEntityID => $ActivityDialogEntityID,
248                TicketID               => $TicketID,
249                ReturnType             => 'ActivityDialog',
250                ReturnSubType          => '-',
251                Action                 => $Self->{Action},
252                UserID                 => $Self->{UserID},
253            );
254
255            if ($ACL) {
256                %{$PossibleActivityDialogs} = $TicketObject->TicketAclData();
257            }
258
259            # check if ACL restrictions exist
260            if ( !IsHashRefWithData($PossibleActivityDialogs) )
261            {
262                return $LayoutObject->NoPermission( WithHeader => 'yes' );
263            }
264        }
265    }
266
267    # list only Active processes by default
268    my @ProcessStates = ('Active');
269
270    # set IsMainWindow, IsAjaxRequest, IsProcessEnroll for proper error responses, screen display
271    # and process list
272    $Self->{IsMainWindow}    = $ParamObject->GetParam( Param => 'IsMainWindow' )    || '';
273    $Self->{IsAjaxRequest}   = $ParamObject->GetParam( Param => 'IsAjaxRequest' )   || '';
274    $Self->{IsProcessEnroll} = $ParamObject->GetParam( Param => 'IsProcessEnroll' ) || '';
275
276    # fetch also FadeAway processes to continue working with existing tickets, but not to start new
277    #    ones
278    if ( !$Self->{IsMainWindow} && $Self->{Subaction} ) {
279        push @ProcessStates, 'FadeAway';
280    }
281
282    # create process object
283    $Kernel::OM->ObjectParamAdd(
284        'Kernel::System::ProcessManagement::Process' => {
285            ActivityObject         => $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity'),
286            ActivityDialogObject   => $ActivityDialogObject,
287            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
288            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
289        }
290    );
291    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');
292
293    # get processes
294    my $ProcessList = $ProcessObject->ProcessList(
295        ProcessState => \@ProcessStates,
296        Interface    => ['AgentInterface'],
297    );
298
299    # also get the list of processes initiated by customers, as an activity dialog might be
300    # configured for the agent interface
301    my $FollowupProcessList = $ProcessObject->ProcessList(
302        ProcessState => \@ProcessStates,
303        Interface    => [ 'AgentInterface', 'CustomerInterface' ],
304    );
305
306    my $ProcessEntityID = $ParamObject->GetParam( Param => 'ProcessEntityID' );
307
308    if ( !IsHashRefWithData($ProcessList) && !IsHashRefWithData($FollowupProcessList) ) {
309        return $LayoutObject->ErrorScreen(
310            Message => Translatable('No Process configured!'),
311            Comment => Translatable('Please contact the administrator.'),
312        );
313    }
314
315    # prepare process list for ACLs, use only entities instead of names, convert from
316    #   P1 => Name to P1 => P1. As ACLs should work only against entities
317    my %ProcessListACL = map { $_ => $_ } sort keys %{$ProcessList};
318
319    # validate the ProcessList with stored ACLs
320    my $ACL = $TicketObject->TicketAcl(
321        ReturnType    => 'Process',
322        ReturnSubType => '-',
323        Data          => \%ProcessListACL,
324        Action        => $Self->{Action},
325        UserID        => $Self->{UserID},
326        TicketID      => $TicketID,
327    );
328
329    if ( IsHashRefWithData($ProcessList) && $ACL ) {
330
331        # get ACL results
332        my %ACLData = $TicketObject->TicketAclData();
333
334        # recover process names
335        my %ReducedProcessList = map { $_ => $ProcessList->{$_} } sort keys %ACLData;
336
337        # replace original process list with the reduced one
338        $ProcessList = \%ReducedProcessList;
339    }
340
341    # get form id
342    $Self->{FormID} = $ParamObject->GetParam( Param => 'FormID' );
343
344    # create form id
345    if ( !$Self->{FormID} ) {
346        $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate();
347    }
348
349    # if we have no subaction display the process list to start a new one
350    if ( !$Self->{Subaction} ) {
351
352        # to display the process list is mandatory to have processes that agent can start
353        if ( !IsHashRefWithData($ProcessList) ) {
354            return $LayoutObject->ErrorScreen(
355                Message => Translatable('No Process configured!'),
356                Comment => Translatable('Please contact the administrator.'),
357            );
358        }
359
360        # get process id (if any, a process should be pre-selected)
361        $Param{ProcessID} = $ParamObject->GetParam( Param => 'ID' );
362        if ( $Param{ProcessID} ) {
363            $Param{PreSelectProcess} = 1;
364        }
365
366        return $Self->_DisplayProcessList(
367            %Param,
368            ProcessList     => $ProcessList,
369            ProcessEntityID => $ProcessEntityID || $Param{ProcessID},
370            TicketID        => $TicketID,
371        );
372    }
373
374    # check if the selected process from the list is valid, prevent tamper with process selection
375    #    list (not existing, invalid an fade away processes must not be able to start a new process
376    #    ticket)
377    elsif (
378        $Self->{Subaction} eq 'DisplayActivityDialogAJAX'
379        && !$ProcessList->{$ProcessEntityID}
380        && $Self->{IsMainWindow}
381        )
382    {
383
384        # translate the error message (as it will be injected in the HTML)
385        my $ErrorMessage = $LayoutObject->{LanguageObject}->Translate("The selected process is invalid!");
386
387        # return a predefined HTML structure as the AJAX call is expecting and HTML response
388        return $LayoutObject->Attachment(
389            ContentType => 'text/html; charset=' . $LayoutObject->{Charset},
390            Content     => '<div class="ServerError" data-message="' . $ErrorMessage . '"></div>',
391            Type        => 'inline',
392            NoCache     => 1,
393        );
394    }
395
396    # if invalid process is detected on a ActivityDilog pop-up screen show an error message
397    elsif (
398        $Self->{Subaction} eq 'DisplayActivityDialog'
399        && !$FollowupProcessList->{$ProcessEntityID}
400        && !$Self->{IsMainWindow}
401        )
402    {
403        $LayoutObject->FatalError(
404            Message => $LayoutObject->{LanguageObject}->Translate( 'Process %s is invalid!', $ProcessEntityID ),
405            Comment => Translatable('Please contact the administrator.'),
406        );
407    }
408
409    # Get the necessary parameters
410    # collects a mixture of present values bottom to top:
411    # SysConfig DefaultValues, ActivityDialog DefaultValues, TicketValues, SubmittedValues
412    # including ActivityDialogEntityID and ProcessEntityID
413    # is used for:
414    # - Parameter checking before storing
415    # - will be used for ACL checking later on
416    my $GetParam = $Self->_GetParam(
417        ProcessEntityID => $ProcessEntityID,
418    );
419
420    if ( $Self->{Subaction} eq 'StoreActivityDialog' && $ProcessEntityID ) {
421        $LayoutObject->ChallengeTokenCheck();
422
423        return $Self->_StoreActivityDialog(
424            %Param,
425            ProcessName     => $ProcessList->{$ProcessEntityID},
426            ProcessEntityID => $ProcessEntityID,
427            GetParam        => $GetParam,
428        );
429    }
430    if ( $Self->{Subaction} eq 'DisplayActivityDialog' && $ProcessEntityID ) {
431
432        return $Self->_OutputActivityDialog(
433            %Param,
434            ProcessEntityID => $ProcessEntityID,
435            GetParam        => $GetParam,
436        );
437    }
438    if ( $Self->{Subaction} eq 'DisplayActivityDialogAJAX' && $ProcessEntityID ) {
439
440        my $ActivityDialogHTML = $Self->_OutputActivityDialog(
441            %Param,
442            ProcessEntityID => $ProcessEntityID,
443            GetParam        => $GetParam,
444        );
445        return $LayoutObject->Attachment(
446            ContentType => 'text/html; charset=' . $LayoutObject->{Charset},
447            Content     => $ActivityDialogHTML,
448            Type        => 'inline',
449            NoCache     => 1,
450        );
451
452    }
453    elsif ( $Self->{Subaction} eq 'AJAXUpdate' ) {
454
455        return $Self->_RenderAjax(
456            %Param,
457            ProcessEntityID => $ProcessEntityID,
458            GetParam        => $GetParam,
459        );
460    }
461    return $LayoutObject->ErrorScreen(
462        Message => Translatable('Subaction is invalid!'),
463        Comment => Translatable('Please contact the administrator.'),
464    );
465}
466
467sub _RenderAjax {
468    my ( $Self, %Param ) = @_;
469
470    # get layout object
471    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
472
473    # FatalError is safe because a JSON structure is expecting, then it will result into a
474    # communications error
475
476    for my $Needed (qw(ProcessEntityID)) {
477        if ( !$Param{$Needed} ) {
478            $LayoutObject->FatalError(
479                Message => $LayoutObject->{LanguageObject}
480                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderAjax' ),
481            );
482        }
483    }
484    my $ActivityDialogEntityID = $Param{GetParam}{ActivityDialogEntityID};
485    if ( !$ActivityDialogEntityID ) {
486        $LayoutObject->FatalError(
487            Message => $LayoutObject->{LanguageObject}
488                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogEntityID', '_RenderAjax' ),
489        );
490    }
491    my $ActivityDialog = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog')->ActivityDialogGet(
492        ActivityDialogEntityID => $ActivityDialogEntityID,
493        Interface              => 'AgentInterface',
494    );
495
496    if ( !IsHashRefWithData($ActivityDialog) ) {
497        $LayoutObject->FatalError(
498            Message => $LayoutObject->{LanguageObject}->Translate(
499                'No ActivityDialog configured for %s in _RenderAjax!',
500                $ActivityDialogEntityID,
501            ),
502        );
503    }
504
505    # get list type
506    my $TreeView = 0;
507    if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::ListType') eq 'tree' ) {
508        $TreeView = 1;
509    }
510
511    my %FieldsProcessed;
512    my @JSONCollector;
513
514    my $Services;
515
516    # All submitted DynamicFields
517    # get dynamic field values form http request
518    my %DynamicFieldValues;
519
520    my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
521        Valid      => 1,
522        ObjectType => 'Ticket',
523    );
524
525    # get needed object
526    my $ParamObject               = $Kernel::OM->Get('Kernel::System::Web::Request');
527    my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');
528
529    # cycle trough the activated Dynamic Fields for this screen
530    DYNAMICFIELD:
531    for my $DynamicFieldConfig ( @{$DynamicField} ) {
532        next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
533
534        # extract the dynamic field value from the web request
535        $DynamicFieldValues{ $DynamicFieldConfig->{Name} } = $DynamicFieldBackendObject->EditFieldValueGet(
536            DynamicFieldConfig => $DynamicFieldConfig,
537            ParamObject        => $ParamObject,
538            LayoutObject       => $LayoutObject,
539        );
540    }
541
542    # convert dynamic field values into a structure for ACLs
543    my %DynamicFieldCheckParam;
544    DYNAMICFIELD:
545    for my $DynamicFieldItem ( sort keys %DynamicFieldValues ) {
546        next DYNAMICFIELD if !$DynamicFieldItem;
547        next DYNAMICFIELD if !defined $DynamicFieldValues{$DynamicFieldItem};
548        next DYNAMICFIELD if !length $DynamicFieldValues{$DynamicFieldItem};
549
550        $DynamicFieldCheckParam{ 'DynamicField_' . $DynamicFieldItem } = $DynamicFieldValues{$DynamicFieldItem};
551    }
552    $Param{GetParam}->{DynamicField} = \%DynamicFieldCheckParam;
553
554    # Get the activity dialog's Submit Param's or Config Params
555    DIALOGFIELD:
556    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
557
558        # Skip if we're working on a field that was already done with or without ID
559        if (
560            $Self->{NameToID}{$CurrentField}
561            && $FieldsProcessed{ $Self->{NameToID}{$CurrentField} }
562            )
563        {
564            next DIALOGFIELD;
565        }
566
567        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
568            my $DynamicFieldName = $1;
569
570            my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{$DynamicField} )[0];
571
572            next DIALOGFIELD if !IsHashRefWithData($DynamicFieldConfig);
573
574            my $IsACLReducible = $DynamicFieldBackendObject->HasBehavior(
575                DynamicFieldConfig => $DynamicFieldConfig,
576                Behavior           => 'IsACLReducible',
577            );
578            next DIALOGFIELD if !$IsACLReducible;
579
580            my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
581                DynamicFieldConfig => $DynamicFieldConfig,
582            );
583
584            # convert possible values key => value to key => key for ACLs using a Hash slice
585            my %AclData = %{$PossibleValues};
586            @AclData{ keys %AclData } = keys %AclData;
587
588            # get ticket object
589            my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
590
591            # set possible values filter from ACLs
592            my $ACL = $TicketObject->TicketAcl(
593                %{ $Param{GetParam} },
594                ReturnType    => 'Ticket',
595                ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
596                Data          => \%AclData,
597                Action        => $Self->{Action},
598                UserID        => $Self->{UserID},
599            );
600
601            if ($ACL) {
602                my %Filter = $TicketObject->TicketAclData();
603
604                # convert Filer key => key back to key => value using map
605                %{$PossibleValues} = map { $_ => $PossibleValues->{$_} } keys %Filter;
606            }
607
608            my $DataValues = $DynamicFieldBackendObject->BuildSelectionDataGet(
609                DynamicFieldConfig => $DynamicFieldConfig,
610                PossibleValues     => $PossibleValues,
611                Value              => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
612            ) || $PossibleValues;
613
614            # add dynamic field to the JSONCollector
615            push(
616                @JSONCollector,
617                {
618                    Name        => 'DynamicField_' . $DynamicFieldConfig->{Name},
619                    Data        => $DataValues,
620                    SelectedID  => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
621                    Translation => $DynamicFieldConfig->{Config}->{TranslatableValues} || 0,
622                    Max         => 100,
623                }
624            );
625        }
626        elsif ( $Self->{NameToID}{$CurrentField} eq 'OwnerID' ) {
627            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
628
629            my $Data = $Self->_GetOwners(
630                %{ $Param{GetParam} },
631            );
632
633            # add Owner to the JSONCollector
634            push(
635                @JSONCollector,
636                {
637                    Name         => $Self->{NameToID}{$CurrentField},
638                    Data         => $Data,
639                    SelectedID   => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
640                    PossibleNone => 1,
641                    Translation  => 0,
642                    Max          => 100,
643                },
644            );
645            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
646        }
647        elsif ( $Self->{NameToID}{$CurrentField} eq 'ResponsibleID' ) {
648            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
649
650            my $Data = $Self->_GetResponsibles(
651                %{ $Param{GetParam} },
652            );
653
654            # add Responsible to the JSONCollector
655            push(
656                @JSONCollector,
657                {
658                    Name         => $Self->{NameToID}{$CurrentField},
659                    Data         => $Data,
660                    SelectedID   => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
661                    PossibleNone => 1,
662                    Translation  => 0,
663                    Max          => 100,
664                },
665            );
666            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
667        }
668        elsif ( $Self->{NameToID}{$CurrentField} eq 'QueueID' ) {
669            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
670
671            my $Data = $Self->_GetQueues(
672                %{ $Param{GetParam} },
673            );
674
675            # add Queue to the JSONCollector
676            push(
677                @JSONCollector,
678                {
679                    Name         => $Self->{NameToID}{$CurrentField},
680                    Data         => $Data,
681                    SelectedID   => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
682                    PossibleNone => 1,
683                    Translation  => 0,
684                    TreeView     => $TreeView,
685                    Max          => 100,
686                },
687            );
688            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
689        }
690
691        elsif ( $Self->{NameToID}{$CurrentField} eq 'StateID' ) {
692            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
693
694            my $Data = $Self->_GetStates(
695                %{ $Param{GetParam} },
696            );
697
698            # add State to the JSONCollector
699            push(
700                @JSONCollector,
701                {
702                    Name        => 'StateID',
703                    Data        => $Data,
704                    SelectedID  => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
705                    Translation => 1,
706                    Max         => 100,
707                },
708            );
709            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
710        }
711        elsif ( $Self->{NameToID}{$CurrentField} eq 'PriorityID' ) {
712            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
713
714            my $Data = $Self->_GetPriorities(
715                %{ $Param{GetParam} },
716            );
717
718            # add Priority to the JSONCollector
719            push(
720                @JSONCollector,
721                {
722                    Name        => $Self->{NameToID}{$CurrentField},
723                    Data        => $Data,
724                    SelectedID  => $Param{GetParam}{ $Self->{NameToID}{$CurrentField} },
725                    Translation => 1,
726                    Max         => 100,
727                },
728            );
729            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
730        }
731        elsif ( $Self->{NameToID}{$CurrentField} eq 'ServiceID' ) {
732            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
733
734            my $Data = $Self->_GetServices(
735                %{ $Param{GetParam} },
736            );
737            $Services = $Data;
738
739            # add Service to the JSONCollector (Use ServiceID from web request)
740            push(
741                @JSONCollector,
742                {
743                    Name         => $Self->{NameToID}{$CurrentField},
744                    Data         => $Data,
745                    SelectedID   => $ParamObject->GetParam( Param => 'ServiceID' ) || '',
746                    PossibleNone => 1,
747                    Translation  => 0,
748                    TreeView     => $TreeView,
749                    Max          => 100,
750                },
751            );
752            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
753        }
754        elsif ( $Self->{NameToID}{$CurrentField} eq 'SLAID' ) {
755            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
756
757            # if SLA is render before service (by it order in the fields) it needs to create
758            # the service list
759            if ( !IsHashRefWithData($Services) ) {
760                $Services = $Self->_GetServices(
761                    %{ $Param{GetParam} },
762                );
763            }
764
765            my $Data = $Self->_GetSLAs(
766                %{ $Param{GetParam} },
767                Services  => $Services,
768                ServiceID => $ParamObject->GetParam( Param => 'ServiceID' ) || '',
769            );
770
771            # add SLA to the JSONCollector (Use SelectedID from web request)
772            push(
773                @JSONCollector,
774                {
775                    Name         => $Self->{NameToID}{$CurrentField},
776                    Data         => $Data,
777                    SelectedID   => $ParamObject->GetParam( Param => 'SLAID' ) || '',
778                    PossibleNone => 1,
779                    Translation  => 0,
780                    Max          => 100,
781                },
782            );
783            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
784        }
785        elsif ( $Self->{NameToID}{$CurrentField} eq 'TypeID' ) {
786            next DIALOGFIELD if $FieldsProcessed{ $Self->{NameToID}{$CurrentField} };
787
788            my $Data = $Self->_GetTypes(
789                %{ $Param{GetParam} },
790            );
791
792            # Add Type to the JSONCollector (Use SelectedID from web request).
793            push(
794                @JSONCollector,
795                {
796                    Name         => $Self->{NameToID}{$CurrentField},
797                    Data         => $Data,
798                    SelectedID   => $ParamObject->GetParam( Param => 'TypeID' ) || '',
799                    PossibleNone => 1,
800                    Translation  => 0,
801                    Max          => 100,
802                },
803            );
804            $FieldsProcessed{ $Self->{NameToID}{$CurrentField} } = 1;
805        }
806    }
807
808    my $JSON = $LayoutObject->BuildSelectionJSON( [@JSONCollector] );
809
810    return $LayoutObject->Attachment(
811        ContentType => 'application/json; charset=' . $LayoutObject->{Charset},
812        Content     => $JSON,
813        Type        => 'inline',
814        NoCache     => 1,
815    );
816}
817
818# =cut
819#
820# _GetParam()
821#
822# returns the current data state of the submitted information
823#
824# This contains the following data for the different callers:
825#
826#     Initial call with selected Process:
827#         ProcessEntityID
828#         ActivityDialogEntityID
829#         DefaultValues for the configured Fields in that ActivityDialog
830#         DefaultValues for the 4 required Fields Queue State Lock Priority
831#
832#     First Store call submitting an Activity Dialog:
833#         ProcessEntityID
834#         ActivityDialogEntityID
835#         SubmittedValues for the current ActivityDialog
836#         ActivityDialog DefaultValues for invisible fields of that ActivityDialog
837#         DefaultValues for the 4 required Fields Queue State Lock Priority
838#             if not configured in the ActivityDialog
839#
840#     ActivityDialog fillout request on existing Ticket:
841#         ProcessEntityID
842#         ActivityDialogEntityID
843#         TicketValues
844#
845#     ActivityDialog store request or AjaxUpdate request on existing Tickets:
846#         ProcessEntityID
847#         ActivityDialogEntityID
848#         TicketValues for all not-Submitted Values
849#         Submitted Values
850#
851#     my $GetParam = _GetParam(
852#         ProcessEntityID => $ProcessEntityID,
853#     );
854#
855# =cut
856
857sub _GetParam {
858    my ( $Self, %Param ) = @_;
859
860    #my $IsAJAXUpdate = $Param{AJAX} || '';
861
862    # get layout object
863    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
864
865    for my $Needed (qw(ProcessEntityID)) {
866        if ( !$Param{$Needed} ) {
867            $LayoutObject->FatalError(
868                Message => $LayoutObject->{LanguageObject}
869                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_GetParam' ),
870            );
871        }
872    }
873
874    # get param object
875    my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
876
877    my %GetParam;
878    my %Ticket;
879    my $ProcessEntityID        = $Param{ProcessEntityID};
880    my $TicketID               = $ParamObject->GetParam( Param => 'TicketID' );
881    my $ActivityDialogEntityID = $ParamObject->GetParam(
882        Param => 'ActivityDialogEntityID',
883    );
884    my $ActivityEntityID;
885    my %ValuesGotten;
886    my $Value;
887
888    # get activity dialog object
889    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');
890
891    # create process object
892    $Kernel::OM->ObjectParamAdd(
893        'Kernel::System::ProcessManagement::Process' => {
894            ActivityObject         => $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity'),
895            ActivityDialogObject   => $ActivityDialogObject,
896            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
897            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
898        }
899    );
900    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');
901
902    # If we got no ActivityDialogEntityID and no TicketID
903    # we have to get the Processes' Startpoint
904    if ( !$ActivityDialogEntityID && ( !$TicketID || $Self->{IsProcessEnroll} ) ) {
905        my $ActivityActivityDialog = $ProcessObject->ProcessStartpointGet(
906            ProcessEntityID => $ProcessEntityID,
907        );
908        if (
909            !$ActivityActivityDialog->{ActivityDialog}
910            || !$ActivityActivityDialog->{Activity}
911            )
912        {
913            my $Message = $LayoutObject->{LanguageObject}->Translate(
914                'Got no Start ActivityEntityID or Start ActivityDialogEntityID for Process: %s in _GetParam!',
915                $ProcessEntityID,
916            );
917
918            # does not show header and footer again
919            if ( $Self->{IsMainWindow} ) {
920                return $LayoutObject->Error(
921                    Message => $Message,
922                );
923            }
924
925            $LayoutObject->FatalError(
926                Message => $Message,
927            );
928        }
929        $ActivityDialogEntityID = $ActivityActivityDialog->{ActivityDialog};
930        $ActivityEntityID       = $ActivityActivityDialog->{Activity};
931    }
932
933    my $ActivityDialog = $ActivityDialogObject->ActivityDialogGet(
934        ActivityDialogEntityID => $ActivityDialogEntityID,
935        Interface              => 'AgentInterface',
936    );
937
938    if ( !IsHashRefWithData($ActivityDialog) ) {
939        return $LayoutObject->ErrorScreen(
940            Message => $LayoutObject->{LanguageObject}->Translate(
941                'Couldn\'t get ActivityDialogEntityID "%s"!',
942                $ActivityDialogEntityID,
943            ),
944            Comment => Translatable('Please contact the administrator.'),
945        );
946    }
947
948    # get config object
949    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
950
951    # if there is a ticket then is not an AJAX request
952    if ($TicketID) {
953        %Ticket = $Kernel::OM->Get('Kernel::System::Ticket')->TicketGet(
954            TicketID      => $TicketID,
955            UserID        => $Self->{UserID},
956            DynamicFields => 1,
957        );
958
959        %GetParam = %Ticket;
960        if ( !IsHashRefWithData( \%GetParam ) ) {
961            $LayoutObject->FatalError(
962                Message => $LayoutObject->{LanguageObject}->Translate(
963                    'Couldn\'t get Ticket for TicketID: %s in _GetParam!',
964                    $TicketID,
965                ),
966            );
967        }
968
969        if ( !$Self->{IsProcessEnroll} ) {
970            $ActivityEntityID = $Ticket{
971                'DynamicField_'
972                    . $ConfigObject->Get("Process::DynamicFieldProcessManagementActivityID")
973            };
974            if ( !$ActivityEntityID ) {
975                $LayoutObject->FatalError(
976                    Message => Translatable(
977                        'Couldn\'t determine ActivityEntityID. DynamicField or Config isn\'t set properly!'
978                    ),
979                );
980            }
981        }
982
983    }
984    $GetParam{ActivityDialogEntityID} = $ActivityDialogEntityID;
985    $GetParam{ActivityEntityID}       = $ActivityEntityID;
986    $GetParam{ProcessEntityID}        = $ProcessEntityID;
987
988    # Get the activitydialogs's Submit Param's or Config Params
989    DIALOGFIELD:
990    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
991
992        # Skip if we're working on a field that was already done with or without ID
993        if ( $Self->{NameToID}{$CurrentField} && $ValuesGotten{ $Self->{NameToID}{$CurrentField} } )
994        {
995            next DIALOGFIELD;
996        }
997
998        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
999            my $DynamicFieldName = $1;
1000
1001            my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
1002                Valid      => 1,
1003                ObjectType => 'Ticket',
1004            );
1005
1006            # Get the Config of the current DynamicField (the first element of the grep result array)
1007            my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{$DynamicField} )[0];
1008
1009            if ( !IsHashRefWithData($DynamicFieldConfig) ) {
1010                my $Message =
1011                    "DynamicFieldConfig missing for field: $DynamicFieldName, or is not a Ticket Dynamic Field!";
1012
1013                # log error but does not stop the execution as it could be an old Article
1014                # DynamicField, see bug#11666
1015                $Kernel::OM->Get('Kernel::System::Log')->Log(
1016                    Priority => 'error',
1017                    Message  => $Message,
1018                );
1019
1020                next DIALOGFIELD;
1021            }
1022
1023            # Get DynamicField Values
1024            $Value = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->EditFieldValueGet(
1025                DynamicFieldConfig => $DynamicFieldConfig,
1026                ParamObject        => $ParamObject,
1027                LayoutObject       => $LayoutObject,
1028            );
1029
1030            # If we got a submitted param, take it and next out
1031            if (
1032                defined $Value
1033                && (
1034                    $Value eq ''
1035                    || IsStringWithData($Value)
1036                    || IsArrayRefWithData($Value)
1037                    || IsHashRefWithData($Value)
1038                )
1039                )
1040            {
1041                $GetParam{$CurrentField} = $Value;
1042                next DIALOGFIELD;
1043            }
1044
1045            # If we didn't have a Param Value try the ticket Value
1046            # next out if it was successful
1047            if (
1048                defined $Ticket{$CurrentField}
1049                && (
1050                    $Ticket{$CurrentField} eq ''
1051                    || IsStringWithData( $Ticket{$CurrentField} )
1052                    || IsArrayRefWithData( $Ticket{$CurrentField} )
1053                    || IsHashRefWithData( $Ticket{$CurrentField} )
1054                )
1055                )
1056            {
1057                $GetParam{$CurrentField} = $Ticket{$CurrentField};
1058                next DIALOGFIELD;
1059            }
1060
1061            # If we had neither submitted nor ticket param get the ActivityDialog's default Value
1062            # next out if it was successful
1063            $Value = $ActivityDialog->{Fields}{$CurrentField}{DefaultValue};
1064            if ( defined $Value && length $Value ) {
1065                $GetParam{$CurrentField} = $Value;
1066                next DIALOGFIELD;
1067            }
1068
1069            # If we had no submitted, ticket or ActivityDialog default value
1070            # use the DynamicField's default value and next out
1071            $Value = $DynamicFieldConfig->{Config}{DefaultValue};
1072            if ( defined $Value && length $Value ) {
1073                $GetParam{$CurrentField} = $Value;
1074                next DIALOGFIELD;
1075            }
1076
1077            # if all that failed then the field should not have a defined value otherwise
1078            # if a value (even empty) is sent, fields like Date or DateTime will mark the field as
1079            # used with the field display value, this could lead to unwanted field sets,
1080            # see bug#9159
1081            next DIALOGFIELD;
1082        }
1083
1084        # get article fields
1085        if ( $CurrentField eq 'Article' ) {
1086
1087            $GetParam{Subject} = $ParamObject->GetParam( Param => 'Subject' );
1088            $GetParam{Body}    = $ParamObject->GetParam( Param => 'Body' );
1089            @{ $GetParam{InformUserID} } = $ParamObject->GetArray(
1090                Param => 'InformUserID',
1091            );
1092
1093            $ValuesGotten{Article} = 1 if ( $GetParam{Subject} && $GetParam{Body} );
1094
1095            $GetParam{TimeUnits} = $ParamObject->GetParam( Param => 'TimeUnits' );
1096        }
1097
1098        if ( $CurrentField eq 'CustomerID' ) {
1099            $GetParam{Customer} = $ParamObject->GetParam(
1100                Param => 'SelectedCustomerUser',
1101            ) || '';
1102            $GetParam{CustomerUserID} = $ParamObject->GetParam(
1103                Param => 'SelectedCustomerUser',
1104            ) || '';
1105        }
1106
1107        if ( $CurrentField eq 'PendingTime' ) {
1108            my $Prefix = 'PendingTime';
1109
1110            # Ok, we need to try to find the target state now
1111            my %StateData;
1112
1113            # get state object
1114            my $StateObject = $Kernel::OM->Get('Kernel::System::State');
1115
1116            # Was something submitted from the GUI?
1117            my $TargetStateID = $ParamObject->GetParam( Param => 'StateID' );
1118            if ($TargetStateID) {
1119                %StateData = $StateObject->StateGet(
1120                    ID => $TargetStateID,
1121                );
1122            }
1123
1124            # Fallback 1: default value of dialog field State
1125            if ( !%StateData && $ActivityDialog->{Fields}{State}{DefaultValue} ) {
1126                %StateData = $StateObject->StateGet(
1127                    Name => $ActivityDialog->{Fields}{State}{DefaultValue},
1128                );
1129            }
1130
1131            # Fallback 2: default value of dialog field StateID
1132            if ( !%StateData && $ActivityDialog->{Fields}{StateID}{DefaultValue} ) {
1133                %StateData = $StateObject->StateGet(
1134                    ID => $ActivityDialog->{Fields}{StateID}{DefaultValue},
1135                );
1136            }
1137
1138            # Fallback 3: existing ticket state
1139            if ( !%StateData && %Ticket ) {
1140                %StateData = $StateObject->StateGet(
1141                    ID => $Ticket{StateID},
1142                );
1143            }
1144
1145            # get pending time values
1146            # depends on StateType containing '^pending'
1147            if (
1148                IsHashRefWithData( \%StateData )
1149                && $StateData{TypeName}
1150                && $StateData{TypeName} =~ /^pending/i
1151                )
1152            {
1153
1154                # map the GetParam's Date Values to our DateParamHash
1155                my %DateParam = (
1156                    Prefix => $Prefix,
1157                    map {
1158                        ( $Prefix . $_ )
1159                            => $ParamObject->GetParam( Param => ( $Prefix . $_ ) )
1160                        }
1161                        qw(Year Month Day Hour Minute)
1162                );
1163
1164                # if all values are present
1165                if (
1166                    defined $DateParam{ $Prefix . 'Year' }
1167                    && defined $DateParam{ $Prefix . 'Month' }
1168                    && defined $DateParam{ $Prefix . 'Day' }
1169                    && defined $DateParam{ $Prefix . 'Hour' }
1170                    && defined $DateParam{ $Prefix . 'Minute' }
1171                    )
1172                {
1173
1174                    # recalculate time according to the user's timezone
1175                    %DateParam = $LayoutObject->TransformDateSelection(
1176                        %DateParam,
1177                    );
1178
1179                    # reformat for storing (e.g. take out Prefix)
1180                    %{ $GetParam{$CurrentField} }
1181                        = map { $_ => $DateParam{ $Prefix . $_ } } qw(Year Month Day Hour Minute);
1182                    $ValuesGotten{PendingTime} = 1;
1183                }
1184            }
1185        }
1186
1187        # Non DynamicFields
1188        # 1. try to get the required param
1189        my $Value = $ParamObject->GetParam( Param => $Self->{NameToID}{$CurrentField} );
1190
1191        if ($Value) {
1192
1193            # if we have an ID field make sure the value without ID won't be in the
1194            # %GetParam Hash any more
1195            if ( $Self->{NameToID}{$CurrentField} =~ m{(.*)ID$}xms ) {
1196                $GetParam{$1} = undef;
1197            }
1198            $GetParam{ $Self->{NameToID}{$CurrentField} }     = $Value;
1199            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
1200            next DIALOGFIELD;
1201        }
1202
1203        # If we got ticket params, the GetParam Hash was already filled before the loop
1204        # and we can next out
1205        if ( $GetParam{ $Self->{NameToID}{$CurrentField} } ) {
1206            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
1207            next DIALOGFIELD;
1208        }
1209
1210        if ( $CurrentField eq 'Queue' && !$GetParam{ $Self->{NameToID}{$CurrentField} } ) {
1211            my $UserDefaultQueue = $ConfigObject->Get('Ticket::Frontend::UserDefaultQueue') || '';
1212            if ($UserDefaultQueue) {
1213                my $QueueID = $Kernel::OM->Get('Kernel::System::Queue')->QueueLookup( Queue => $UserDefaultQueue );
1214                if ($QueueID) {
1215                    $GetParam{$CurrentField}                          = $UserDefaultQueue;
1216                    $GetParam{ $Self->{NameToID}{$CurrentField} }     = $QueueID;
1217                    $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
1218                    next DIALOGFIELD;
1219                }
1220            }
1221        }
1222
1223        # if no Submitted nore Ticket Param get ActivityDialog Config's Param
1224        if ( $CurrentField ne 'CustomerID' ) {
1225            $Value = $ActivityDialog->{Fields}{$CurrentField}{DefaultValue};
1226        }
1227        if ($Value) {
1228            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
1229            $GetParam{$CurrentField} = $Value;
1230            next DIALOGFIELD;
1231        }
1232    }
1233    REQUIREDFIELDLOOP:
1234    for my $CurrentField (qw(Queue State Lock Priority)) {
1235        $Value = undef;
1236        if ( !$ValuesGotten{ $Self->{NameToID}{$CurrentField} } ) {
1237            $Value = $ConfigObject->Get("Process::Default$CurrentField");
1238            if ( !$Value ) {
1239
1240                my $Message = $LayoutObject->{LanguageObject}->Translate(
1241                    'Process::Default%s Config Value missing!',
1242                    $CurrentField,
1243                );
1244
1245                # does not show header and footer again
1246                if ( $Self->{IsMainWindow} ) {
1247                    return $LayoutObject->Error(
1248                        Message => $Message,
1249                    );
1250                }
1251
1252                $LayoutObject->FatalError(
1253                    Message => $Message,
1254                );
1255            }
1256            $GetParam{$CurrentField} = $Value;
1257            $ValuesGotten{ $Self->{NameToID}{$CurrentField} } = 1;
1258        }
1259    }
1260
1261    my $Dest = $ParamObject->GetParam( Param => 'Dest' ) || '';
1262    if ($Dest) {
1263
1264        my @QueueParts = split( /\|\|/, $Dest );
1265
1266        $GetParam{QueueID} = $QueueParts[0];
1267        $GetParam{Queue}   = $QueueParts[1];
1268
1269        $ValuesGotten{QueueID} = 1;
1270    }
1271
1272    # get also the IDs for the Required files (if they are not present)
1273    if ( $GetParam{Queue} && !$GetParam{QueueID} ) {
1274        $GetParam{QueueID} = $Kernel::OM->Get('Kernel::System::Queue')->QueueLookup( Queue => $GetParam{Queue} );
1275    }
1276    if ( $GetParam{State} && !$GetParam{StateID} ) {
1277        $GetParam{StateID} = $Kernel::OM->Get('Kernel::System::State')->StateLookup( State => $GetParam{State} );
1278    }
1279    if ( $GetParam{Lock} && !$GetParam{LockID} ) {
1280        $GetParam{LockID} = $Kernel::OM->Get('Kernel::System::Lock')->LockLookup( Lock => $GetParam{Lock} );
1281    }
1282    if ( $GetParam{Priority} && !$GetParam{PriorityID} ) {
1283        $GetParam{PriorityID} = $Kernel::OM->Get('Kernel::System::Priority')->PriorityLookup(
1284            Priority => $GetParam{Priority},
1285        );
1286    }
1287
1288    # and finally we'll have the special parameters:
1289    $GetParam{ResponsibleAll} = $ParamObject->GetParam( Param => 'ResponsibleAll' );
1290    $GetParam{OwnerAll}       = $ParamObject->GetParam( Param => 'OwnerAll' );
1291    $GetParam{ElementChanged} = $ParamObject->GetParam( Param => 'ElementChanged' );
1292
1293    return \%GetParam;
1294}
1295
1296sub _OutputActivityDialog {
1297    my ( $Self, %Param ) = @_;
1298    my $TicketID               = $Param{GetParam}{TicketID};
1299    my $ActivityDialogEntityID = $Param{GetParam}{ActivityDialogEntityID};
1300
1301    # get layout object
1302    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
1303
1304    # Check needed parameters:
1305    # ProcessEntityID only
1306    # TicketID ActivityDialogEntityID
1307    if ( !$Param{ProcessEntityID} || ( !$TicketID && !$ActivityDialogEntityID ) ) {
1308        my $Message = Translatable('Got no ProcessEntityID or TicketID and ActivityDialogEntityID!');
1309
1310        # does not show header and footer again
1311        if ( $Self->{IsMainWindow} ) {
1312            return $LayoutObject->Error(
1313                Message => $Message,
1314            );
1315        }
1316
1317        $LayoutObject->FatalError(
1318            Message => $Message,
1319        );
1320    }
1321
1322    my $ActivityActivityDialog;
1323    my %Ticket;
1324    my %Error         = ();
1325    my %ErrorMessages = ();
1326
1327    # If we had Errors, we got an Errorhash
1328    %Error         = %{ $Param{Error} }         if ( IsHashRefWithData( $Param{Error} ) );
1329    %ErrorMessages = %{ $Param{ErrorMessages} } if ( IsHashRefWithData( $Param{ErrorMessages} ) );
1330
1331    # get needed objects
1332    my $ActivityObject       = $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity');
1333    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');
1334
1335    # create process object
1336    $Kernel::OM->ObjectParamAdd(
1337        'Kernel::System::ProcessManagement::Process' => {
1338            ActivityObject         => $ActivityObject,
1339            ActivityDialogObject   => $ActivityDialogObject,
1340            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
1341            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
1342        }
1343    );
1344    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');
1345
1346    # get needed object
1347    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
1348    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
1349
1350    if ( !$TicketID || $Self->{IsProcessEnroll} ) {
1351        $ActivityActivityDialog = $ProcessObject->ProcessStartpointGet(
1352            ProcessEntityID => $Param{ProcessEntityID},
1353        );
1354
1355        if ( !IsHashRefWithData($ActivityActivityDialog) ) {
1356            my $Message = $LayoutObject->{LanguageObject}->Translate(
1357                'Can\'t get StartActivityDialog and StartActivityDialog for the ProcessEntityID "%s"!',
1358                $Param{ProcessEntityID},
1359            );
1360
1361            # does not show header and footer again
1362            if ( $Self->{IsMainWindow} ) {
1363                return $LayoutObject->Error(
1364                    Message => $Message,
1365                );
1366            }
1367
1368            $LayoutObject->FatalError(
1369                Message => $Message,
1370            );
1371        }
1372    }
1373    else {
1374
1375        # no AJAX update in this part
1376        %Ticket = $TicketObject->TicketGet(
1377            TicketID      => $TicketID,
1378            UserID        => $Self->{UserID},
1379            DynamicFields => 1,
1380        );
1381
1382        if ( !IsHashRefWithData( \%Ticket ) ) {
1383            $LayoutObject->FatalError(
1384                Message => $LayoutObject->{LanguageObject}->Translate( 'Can\'t get Ticket "%s"!', $Param{TicketID} ),
1385            );
1386        }
1387
1388        my $DynamicFieldProcessID = 'DynamicField_'
1389            . $ConfigObject->Get('Process::DynamicFieldProcessManagementProcessID');
1390        my $DynamicFieldActivityID = 'DynamicField_'
1391            . $ConfigObject->Get('Process::DynamicFieldProcessManagementActivityID');
1392
1393        if ( !$Ticket{$DynamicFieldProcessID} || !$Ticket{$DynamicFieldActivityID} ) {
1394            $LayoutObject->FatalError(
1395                Message => $LayoutObject->{LanguageObject}->Translate(
1396                    'Can\'t get ProcessEntityID or ActivityEntityID for Ticket "%s"!',
1397                    $Param{TicketID},
1398                ),
1399            );
1400        }
1401
1402        $ActivityActivityDialog = {
1403            Activity       => $Ticket{$DynamicFieldActivityID},
1404            ActivityDialog => $ActivityDialogEntityID,
1405        };
1406    }
1407
1408    if ( !%Ticket && $Self->{IsProcessEnroll} ) {
1409        %Ticket = $TicketObject->TicketGet(
1410            TicketID      => $TicketID,
1411            UserID        => $Self->{UserID},
1412            DynamicFields => 1,
1413        );
1414    }
1415
1416    my $Activity = $ActivityObject->ActivityGet(
1417        Interface        => 'AgentInterface',
1418        ActivityEntityID => $ActivityActivityDialog->{Activity}
1419    );
1420    if ( !$Activity ) {
1421        my $Message = $LayoutObject->{LanguageObject}->Translate(
1422            'Can\'t get Activity configuration for ActivityEntityID "%s"!',
1423            $ActivityActivityDialog->{Activity},
1424        );
1425
1426        # does not show header and footer again
1427        if ( $Self->{IsMainWindow} ) {
1428            return $LayoutObject->Error(
1429                Message => $Message,
1430            );
1431        }
1432
1433        $LayoutObject->FatalError(
1434            Message => $Message,
1435        );
1436    }
1437
1438    my $ActivityDialog = $ActivityDialogObject->ActivityDialogGet(
1439        ActivityDialogEntityID => $ActivityActivityDialog->{ActivityDialog},
1440        Interface              => 'AgentInterface',
1441    );
1442    if ( !IsHashRefWithData($ActivityDialog) ) {
1443        my $Message = $LayoutObject->{LanguageObject}->Translate(
1444            'Can\'t get ActivityDialog configuration for ActivityDialogEntityID "%s"!',
1445            $ActivityActivityDialog->{ActivityDialog},
1446        );
1447
1448        # does not show header and footer again
1449        if ( $Self->{IsMainWindow} ) {
1450            return $LayoutObject->Error(
1451                Message => $Message,
1452            );
1453        }
1454
1455        $LayoutObject->FatalError(
1456            Message => $Message,
1457        );
1458    }
1459
1460    # grep out Overwrites if defined on the Activity
1461    my @OverwriteActivityDialogNumber = grep {
1462        ref $Activity->{ActivityDialog}{$_} eq 'HASH'
1463            && $Activity->{ActivityDialog}{$_}{ActivityDialogEntityID}
1464            && $Activity->{ActivityDialog}{$_}{ActivityDialogEntityID} eq
1465            $ActivityActivityDialog->{ActivityDialog}
1466            && IsHashRefWithData( $Activity->{ActivityDialog}{$_}{Overwrite} )
1467    } keys %{ $Activity->{ActivityDialog} };
1468
1469    # let the Overwrites Overwrite the ActivityDialog's Hash values
1470    if ( $OverwriteActivityDialogNumber[0] ) {
1471        %{$ActivityDialog} = (
1472            %{$ActivityDialog},
1473            %{ $Activity->{ActivityDialog}{ $OverwriteActivityDialogNumber[0] }{Overwrite} }
1474        );
1475    }
1476
1477    # Add PageHeader, Navbar, Formheader (Process/ActivityDialogHeader)
1478    my $Output;
1479    my $MainBoxClass;
1480
1481    if ( !$Self->{IsMainWindow} && !$Self->{IsProcessEnroll} ) {
1482        $Output = $LayoutObject->Header(
1483            Type  => 'Small',
1484            Value => $Ticket{Number},
1485        );
1486
1487        # display given notify messages if this is not an AJAX request
1488        if ( IsArrayRefWithData( $Param{Notify} ) ) {
1489
1490            for my $NotifyData ( @{ $Param{Notify} } ) {
1491                $Output .= $LayoutObject->Notify( %{$NotifyData} );
1492            }
1493        }
1494
1495        $LayoutObject->Block(
1496            Name => 'Header',
1497            Data => {
1498                Name =>
1499                    $LayoutObject->{LanguageObject}->Translate( $ActivityDialog->{Name} )
1500                    || '',
1501            }
1502        );
1503    }
1504    elsif (
1505        ( $Self->{IsMainWindow} || $Self->{IsProcessEnroll} )
1506        && IsHashRefWithData( \%Error )
1507        )
1508    {
1509
1510        # add rich text editor
1511        if ( $LayoutObject->{BrowserRichText} ) {
1512
1513            # use height/width defined for this screen
1514            $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
1515            $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;
1516
1517            # set up rich text editor
1518            $LayoutObject->SetRichTextParameters(
1519                Data => \%Param,
1520            );
1521        }
1522
1523        # display complete header and navigation bar in AJAX dialogs when there is a server error
1524        #    unless we are in a process enrollment (only when IsMainWindow is active)
1525        my $Type = $Self->{IsMainWindow} ? '' : 'Small';
1526        $Output = $LayoutObject->Header(
1527            Type => $Type,
1528        );
1529        if ( $Self->{IsMainWindow} ) {
1530            $Output .= $LayoutObject->NavigationBar();
1531        }
1532
1533        # display original header texts (the process list maybe is not necessary)
1534        $Output .= $LayoutObject->Output(
1535            TemplateFile => 'AgentTicketProcess' . $Type,
1536            Data         => {
1537                %Param,
1538                FormID          => $Self->{FormID},
1539                IsProcessEnroll => $Self->{IsProcessEnroll},
1540            },
1541        );
1542
1543        # set the MainBox class to add correct borders to the screen
1544        $MainBoxClass = 'MainBox';
1545    }
1546
1547    # display process information
1548    if ( $Self->{IsMainWindow} ) {
1549
1550        # get process data
1551        my $Process = $ProcessObject->ProcessGet(
1552            ProcessEntityID => $Param{ProcessEntityID},
1553        );
1554
1555        # output main process information
1556        $LayoutObject->Block(
1557            Name => 'ProcessInfoSidebar',
1558            Data => {
1559                Process        => $Process->{Name}        || '',
1560                Activity       => $Activity->{Name}       || '',
1561                ActivityDialog => $ActivityDialog->{Name} || '',
1562            },
1563        );
1564
1565        # output activity dialog short description (if any)
1566        if (
1567            defined $ActivityDialog->{DescriptionShort}
1568            && $ActivityDialog->{DescriptionShort} ne ''
1569            )
1570        {
1571            $LayoutObject->Block(
1572                Name => 'ProcessInfoSidebarActivityDialogDesc',
1573                Data => {
1574                    ActivityDialogDescription => $ActivityDialog->{DescriptionShort} || '',
1575                },
1576            );
1577        }
1578
1579        # output long description information if exists
1580        if (
1581            defined $ActivityDialog->{DescriptionLong}
1582            && length $ActivityDialog->{DescriptionLong}
1583            )
1584        {
1585            $LayoutObject->Block(
1586                Name => 'LongDescriptionSidebar',
1587                Data => {
1588                    Description => $ActivityDialog->{DescriptionLong},
1589                },
1590            );
1591        }
1592    }
1593
1594    # show descriptions
1595    if ( $ActivityDialog->{DescriptionShort} ) {
1596        $LayoutObject->Block(
1597            Name => 'DescriptionShort',
1598            Data => {
1599                DescriptionShort
1600                    => $LayoutObject->{LanguageObject}->Translate(
1601                    $ActivityDialog->{DescriptionShort},
1602                    ),
1603            },
1604        );
1605    }
1606    if ( $ActivityDialog->{DescriptionLong} ) {
1607        $LayoutObject->Block(
1608            Name => 'DescriptionLong',
1609            Data => {
1610                DescriptionLong
1611                    => $LayoutObject->{LanguageObject}->Translate(
1612                    $ActivityDialog->{DescriptionLong},
1613                    ),
1614            },
1615        );
1616    }
1617
1618    # show close & cancel link if necessary
1619    if ( !$Self->{IsMainWindow} && !$Self->{IsProcessEnroll} ) {
1620        if ( $Param{RenderLocked} ) {
1621            $LayoutObject->Block(
1622                Name => 'PropertiesLock',
1623                Data => {
1624                    %Param,
1625                    TicketID => $TicketID,
1626                },
1627            );
1628        }
1629        else {
1630            $LayoutObject->Block(
1631                Name => 'CancelLink',
1632            );
1633        }
1634
1635    }
1636
1637    $Output .= $LayoutObject->Output(
1638        TemplateFile => 'ProcessManagement/ActivityDialogHeader',
1639        Data         => {
1640            FormName               => 'ActivityDialogDialog' . $ActivityActivityDialog->{ActivityDialog},
1641            FormID                 => $Self->{FormID},
1642            Subaction              => 'StoreActivityDialog',
1643            TicketID               => $Ticket{TicketID} || '',
1644            LinkTicketID           => $Self->{LinkTicketID},
1645            ActivityDialogEntityID => $ActivityActivityDialog->{ActivityDialog},
1646            ProcessEntityID        => $Param{ProcessEntityID}
1647                || $Ticket{
1648                'DynamicField_'
1649                    . $ConfigObject->Get(
1650                    'Process::DynamicFieldProcessManagementProcessID'
1651                    )
1652                },
1653            IsMainWindow    => $Self->{IsMainWindow},
1654            IsProcessEnroll => $Self->{IsProcessEnroll},
1655            MainBoxClass    => $MainBoxClass || '',
1656        },
1657    );
1658
1659    my %RenderedFields = ();
1660
1661    # get the list of fields where the AJAX loader icon should appear on AJAX updates triggered
1662    # by ActivityDialog fields
1663    my $AJAXUpdatableFields = $Self->_GetAJAXUpdatableFields(
1664        ActivityDialogFields => $ActivityDialog->{Fields},
1665    );
1666
1667    # Loop through ActivityDialogFields and render their output
1668    DIALOGFIELD:
1669    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
1670        if ( !IsHashRefWithData( $ActivityDialog->{Fields}{$CurrentField} ) ) {
1671            my $Message = $LayoutObject->{LanguageObject}->Translate(
1672                'Can\'t get data for Field "%s" of ActivityDialog "%s"!',
1673                $CurrentField,
1674                $ActivityActivityDialog->{ActivityDialog},
1675            );
1676
1677            # does not show header and footer again
1678            if ( $Self->{IsMainWindow} ) {
1679                return $LayoutObject->Error(
1680                    Message => $Message,
1681                );
1682            }
1683
1684            $LayoutObject->FatalError(
1685                Message => $Message,
1686            );
1687        }
1688
1689        my %FieldData = %{ $ActivityDialog->{Fields}{$CurrentField} };
1690
1691        # We render just visible ActivityDialogFields
1692        next DIALOGFIELD if !$FieldData{Display};
1693
1694        # render DynamicFields
1695        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
1696            my $DynamicFieldName = $1;
1697            my $Response         = $Self->_RenderDynamicField(
1698                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1699                FieldName           => $DynamicFieldName,
1700                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1701                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1702                Ticket              => \%Ticket || {},
1703                Error               => \%Error || {},
1704                ErrorMessages       => \%ErrorMessages || {},
1705                FormID              => $Self->{FormID},
1706                GetParam            => $Param{GetParam},
1707                AJAXUpdatableFields => $AJAXUpdatableFields,
1708            );
1709
1710            if ( !$Response->{Success} ) {
1711
1712                # does not show header and footer again
1713                if ( $Self->{IsMainWindow} ) {
1714                    return $LayoutObject->Error(
1715                        Message => $Response->{Message},
1716                    );
1717                }
1718
1719                $LayoutObject->FatalError(
1720                    Message => $Response->{Message},
1721                );
1722            }
1723
1724            $Output .= $Response->{HTML};
1725
1726            $RenderedFields{$CurrentField} = 1;
1727
1728        }
1729
1730        # render State
1731        elsif ( $Self->{NameToID}->{$CurrentField} eq 'StateID' )
1732        {
1733
1734            # We don't render Fields twice,
1735            # if there was already a Config without ID, skip this field
1736            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1737
1738            my $Response = $Self->_RenderState(
1739                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1740                FieldName           => $CurrentField,
1741                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1742                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1743                Ticket              => \%Ticket || {},
1744                Error               => \%Error || {},
1745                FormID              => $Self->{FormID},
1746                GetParam            => $Param{GetParam},
1747                AJAXUpdatableFields => $AJAXUpdatableFields,
1748            );
1749
1750            if ( !$Response->{Success} ) {
1751
1752                # does not show header and footer again
1753                if ( $Self->{IsMainWindow} ) {
1754                    return $LayoutObject->Error(
1755                        Message => $Response->{Message},
1756                    );
1757                }
1758
1759                $LayoutObject->FatalError(
1760                    Message => $Response->{Message},
1761                );
1762            }
1763
1764            $Output .= $Response->{HTML};
1765
1766            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
1767        }
1768
1769        # render Queue
1770        elsif ( $Self->{NameToID}->{$CurrentField} eq 'QueueID' )
1771        {
1772            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1773
1774            my $Response = $Self->_RenderQueue(
1775                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1776                FieldName           => $CurrentField,
1777                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1778                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1779                Ticket              => \%Ticket || {},
1780                Error               => \%Error || {},
1781                FormID              => $Self->{FormID},
1782                GetParam            => $Param{GetParam},
1783                AJAXUpdatableFields => $AJAXUpdatableFields,
1784            );
1785
1786            if ( !$Response->{Success} ) {
1787
1788                # does not show header and footer again
1789                if ( $Self->{IsMainWindow} ) {
1790                    return $LayoutObject->Error(
1791                        Message => $Response->{Message},
1792                    );
1793                }
1794
1795                $LayoutObject->FatalError(
1796                    Message => $Response->{Message},
1797                );
1798            }
1799
1800            $Output .= $Response->{HTML};
1801
1802            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
1803        }
1804
1805        # render Priority
1806        elsif ( $Self->{NameToID}->{$CurrentField} eq 'PriorityID' )
1807        {
1808            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1809
1810            my $Response = $Self->_RenderPriority(
1811                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1812                FieldName           => $CurrentField,
1813                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1814                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1815                Ticket              => \%Ticket || {},
1816                Error               => \%Error || {},
1817                FormID              => $Self->{FormID},
1818                GetParam            => $Param{GetParam},
1819                AJAXUpdatableFields => $AJAXUpdatableFields,
1820            );
1821
1822            if ( !$Response->{Success} ) {
1823
1824                # does not show header and footer again
1825                if ( $Self->{IsMainWindow} ) {
1826                    return $LayoutObject->Error(
1827                        Message => $Response->{Message},
1828                    );
1829                }
1830
1831                $LayoutObject->FatalError(
1832                    Message => $Response->{Message},
1833                );
1834            }
1835
1836            $Output .= $Response->{HTML};
1837
1838            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
1839        }
1840
1841        # render Lock
1842        elsif ( $Self->{NameToID}->{$CurrentField} eq 'LockID' ) {
1843            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1844
1845            my $Response = $Self->_RenderLock(
1846                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1847                FieldName           => $CurrentField,
1848                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1849                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1850                Ticket              => \%Ticket || {},
1851                Error               => \%Error || {},
1852                FormID              => $Self->{FormID},
1853                GetParam            => $Param{GetParam},
1854                AJAXUpdatableFields => $AJAXUpdatableFields,
1855            );
1856
1857            if ( !$Response->{Success} ) {
1858
1859                # does not show header and footer again
1860                if ( $Self->{IsMainWindow} ) {
1861                    return $LayoutObject->Error(
1862                        Message => $Response->{Message},
1863                    );
1864                }
1865
1866                $LayoutObject->FatalError(
1867                    Message => $Response->{Message},
1868                );
1869            }
1870
1871            $Output .= $Response->{HTML};
1872
1873            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
1874        }
1875
1876        # render Service
1877        elsif ( $Self->{NameToID}->{$CurrentField} eq 'ServiceID' ) {
1878            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1879
1880            my $Response = $Self->_RenderService(
1881                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1882                FieldName           => $CurrentField,
1883                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1884                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1885                Ticket              => \%Ticket || {},
1886                Error               => \%Error || {},
1887                FormID              => $Self->{FormID},
1888                GetParam            => $Param{GetParam},
1889                AJAXUpdatableFields => $AJAXUpdatableFields,
1890            );
1891
1892            if ( !$Response->{Success} ) {
1893
1894                # does not show header and footer again
1895                if ( $Self->{IsMainWindow} ) {
1896                    return $LayoutObject->Error(
1897                        Message => $Response->{Message},
1898                    );
1899                }
1900
1901                $LayoutObject->FatalError(
1902                    Message => $Response->{Message},
1903                );
1904            }
1905
1906            $Output .= $Response->{HTML};
1907
1908            $RenderedFields{$CurrentField} = 1;
1909        }
1910
1911        # render SLA
1912        elsif ( $Self->{NameToID}->{$CurrentField} eq 'SLAID' ) {
1913            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1914
1915            my $Response = $Self->_RenderSLA(
1916                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1917                FieldName           => $CurrentField,
1918                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1919                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1920                Ticket              => \%Ticket || {},
1921                Error               => \%Error || {},
1922                FormID              => $Self->{FormID},
1923                GetParam            => $Param{GetParam},
1924                AJAXUpdatableFields => $AJAXUpdatableFields,
1925            );
1926
1927            if ( !$Response->{Success} ) {
1928
1929                # does not show header and footer again
1930                if ( $Self->{IsMainWindow} ) {
1931                    return $LayoutObject->Error(
1932                        Message => $Response->{Message},
1933                    );
1934                }
1935
1936                $LayoutObject->FatalError(
1937                    Message => $Response->{Message},
1938                );
1939            }
1940
1941            $Output .= $Response->{HTML};
1942
1943            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
1944        }
1945
1946        # render Owner
1947        elsif ( $Self->{NameToID}->{$CurrentField} eq 'OwnerID' ) {
1948            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1949
1950            my $Response = $Self->_RenderOwner(
1951                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1952                FieldName           => $CurrentField,
1953                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1954                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1955                Ticket              => \%Ticket || {},
1956                Error               => \%Error || {},
1957                FormID              => $Self->{FormID},
1958                GetParam            => $Param{GetParam},
1959                AJAXUpdatableFields => $AJAXUpdatableFields,
1960            );
1961
1962            if ( !$Response->{Success} ) {
1963
1964                # does not show header and footer again
1965                if ( $Self->{IsMainWindow} ) {
1966                    return $LayoutObject->Error(
1967                        Message => $Response->{Message},
1968                    );
1969                }
1970
1971                $LayoutObject->FatalError(
1972                    Message => $Response->{Message},
1973                );
1974            }
1975
1976            $Output .= $Response->{HTML};
1977
1978            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
1979        }
1980
1981        # render responsible
1982        elsif ( $Self->{NameToID}->{$CurrentField} eq 'ResponsibleID' ) {
1983            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
1984
1985            my $Response = $Self->_RenderResponsible(
1986                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
1987                FieldName           => $CurrentField,
1988                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
1989                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
1990                Ticket              => \%Ticket || {},
1991                Error               => \%Error || {},
1992                FormID              => $Self->{FormID},
1993                GetParam            => $Param{GetParam},
1994                AJAXUpdatableFields => $AJAXUpdatableFields,
1995            );
1996
1997            if ( !$Response->{Success} ) {
1998
1999                # does not show header and footer again
2000                if ( $Self->{IsMainWindow} ) {
2001                    return $LayoutObject->Error(
2002                        Message => $Response->{Message},
2003                    );
2004                }
2005
2006                $LayoutObject->FatalError(
2007                    Message => $Response->{Message},
2008                );
2009            }
2010
2011            $Output .= $Response->{HTML};
2012
2013            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
2014        }
2015
2016        # render CustomerID
2017        elsif ( $Self->{NameToID}->{$CurrentField} eq 'CustomerID' ) {
2018            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
2019
2020            my $Response = $Self->_RenderCustomer(
2021                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
2022                FieldName           => $CurrentField,
2023                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
2024                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
2025                Ticket              => \%Ticket || {},
2026                Error               => \%Error || {},
2027                FormID              => $Self->{FormID},
2028                GetParam            => $Param{GetParam},
2029                AJAXUpdatableFields => $AJAXUpdatableFields,
2030            );
2031
2032            if ( !$Response->{Success} ) {
2033
2034                # does not show header and footer again
2035                if ( $Self->{IsMainWindow} ) {
2036                    return $LayoutObject->Error(
2037                        Message => $Response->{Message},
2038                    );
2039                }
2040
2041                $LayoutObject->FatalError(
2042                    Message => $Response->{Message},
2043                );
2044            }
2045
2046            $Output .= $Response->{HTML};
2047
2048            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
2049        }
2050
2051        elsif ( $CurrentField eq 'PendingTime' ) {
2052
2053            # PendingTime is just useful if we have State or StateID
2054            if ( !grep {m{^(StateID|State)$}xms} @{ $ActivityDialog->{FieldOrder} } ) {
2055                my $Message = $LayoutObject->{LanguageObject}->Translate(
2056                    'PendingTime can just be used if State or StateID is configured for the same ActivityDialog. ActivityDialog: %s!',
2057                    $ActivityActivityDialog->{ActivityDialog},
2058                );
2059
2060                # does not show header and footer again
2061                if ( $Self->{IsMainWindow} ) {
2062                    return $LayoutObject->Error(
2063                        Message => $Message,
2064                    );
2065                }
2066
2067                $LayoutObject->FatalError(
2068                    Message => $Message,
2069                );
2070            }
2071
2072            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
2073
2074            my $Response = $Self->_RenderPendingTime(
2075                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
2076                FieldName           => $CurrentField,
2077                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
2078                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
2079                Ticket              => \%Ticket || {},
2080                Error               => \%Error || {},
2081                FormID              => $Self->{FormID},
2082                GetParam            => $Param{GetParam},
2083            );
2084
2085            if ( !$Response->{Success} ) {
2086
2087                # does not show header and footer again
2088                if ( $Self->{IsMainWindow} ) {
2089                    return $LayoutObject->Error(
2090                        Message => $Response->{Message},
2091                    );
2092                }
2093
2094                $LayoutObject->FatalError(
2095                    Message => $Response->{Message},
2096                );
2097            }
2098
2099            $Output .= $Response->{HTML};
2100
2101            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
2102        }
2103
2104        # render Title
2105        elsif ( $Self->{NameToID}->{$CurrentField} eq 'Title' ) {
2106            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
2107
2108            my $Response = $Self->_RenderTitle(
2109                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
2110                FieldName           => $CurrentField,
2111                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
2112                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
2113                Ticket              => \%Ticket || {},
2114                Error               => \%Error || {},
2115                FormID              => $Self->{FormID},
2116                GetParam            => $Param{GetParam},
2117            );
2118
2119            if ( !$Response->{Success} ) {
2120
2121                # does not show header and footer again
2122                if ( $Self->{IsMainWindow} ) {
2123                    return $LayoutObject->Error(
2124                        Message => $Response->{Message},
2125                    );
2126                }
2127
2128                $LayoutObject->FatalError(
2129                    Message => $Response->{Message},
2130                );
2131            }
2132
2133            $Output .= $Response->{HTML};
2134
2135            $RenderedFields{$CurrentField} = 1;
2136        }
2137
2138        # render Article
2139        elsif ( $Self->{NameToID}->{$CurrentField} eq 'Article' ) {
2140            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
2141
2142            my $Response = $Self->_RenderArticle(
2143                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
2144                FieldName           => $CurrentField,
2145                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
2146                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
2147                Ticket              => \%Ticket || {},
2148                Error               => \%Error || {},
2149                FormID              => $Self->{FormID},
2150                GetParam            => $Param{GetParam},
2151                InformAgents        => $ActivityDialog->{Fields}->{Article}->{Config}->{InformAgents},
2152            );
2153
2154            if ( !$Response->{Success} ) {
2155
2156                # does not show header and footer again
2157                if ( $Self->{IsMainWindow} ) {
2158                    return $LayoutObject->Error(
2159                        Message => $Response->{Message},
2160                    );
2161                }
2162
2163                $LayoutObject->FatalError(
2164                    Message => $Response->{Message},
2165                );
2166            }
2167
2168            $Output .= $Response->{HTML};
2169
2170            $RenderedFields{$CurrentField} = 1;
2171        }
2172
2173        # render Type
2174        elsif ( $Self->{NameToID}->{$CurrentField} eq 'TypeID' ) {
2175
2176            # We don't render Fields twice,
2177            # if there was already a Config without ID, skip this field
2178            next DIALOGFIELD if $RenderedFields{ $Self->{NameToID}->{$CurrentField} };
2179
2180            my $Response = $Self->_RenderType(
2181                ActivityDialogField => $ActivityDialog->{Fields}{$CurrentField},
2182                FieldName           => $CurrentField,
2183                DescriptionShort    => $ActivityDialog->{Fields}{$CurrentField}{DescriptionShort},
2184                DescriptionLong     => $ActivityDialog->{Fields}{$CurrentField}{DescriptionLong},
2185                Ticket              => \%Ticket || {},
2186                Error               => \%Error || {},
2187                FormID              => $Self->{FormID},
2188                GetParam            => $Param{GetParam},
2189                AJAXUpdatableFields => $AJAXUpdatableFields,
2190            );
2191
2192            if ( !$Response->{Success} ) {
2193
2194                # does not show header and footer again
2195                if ( $Self->{IsMainWindow} ) {
2196                    return $LayoutObject->Error(
2197                        Message => $Response->{Message},
2198                    );
2199                }
2200
2201                $LayoutObject->FatalError(
2202                    Message => $Response->{Message},
2203                );
2204            }
2205
2206            $Output .= $Response->{HTML};
2207
2208            $RenderedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
2209        }
2210    }
2211
2212    my $FooterCSSClass = 'Footer';
2213
2214    if ( $Self->{IsAjaxRequest} ) {
2215
2216        # Due to the initial loading of
2217        # the first ActivityDialog after Process selection
2218        # we have to bind the AjaxUpdate Function on
2219        # the selects, so we get the complete JSOnDocumentComplete code
2220        # and deliver it in the FooterJS block.
2221        # This Javascript Part is executed in
2222        # AgentTicketProcess.tt
2223        $LayoutObject->Block(
2224            Name => 'FooterJS',
2225        );
2226
2227        $FooterCSSClass = 'Centered';
2228    }
2229
2230    # set submit button data
2231    my $ButtonText  = 'Submit';
2232    my $ButtonTitle = 'Save';
2233    my $ButtonID    = 'Submit' . $ActivityActivityDialog->{ActivityDialog};
2234    if ( $ActivityDialog->{SubmitButtonText} ) {
2235        $ButtonText  = $ActivityDialog->{SubmitButtonText};
2236        $ButtonTitle = $ActivityDialog->{SubmitButtonText};
2237    }
2238
2239    $LayoutObject->Block(
2240        Name => 'Footer',
2241        Data => {
2242            FooterCSSClass => $FooterCSSClass,
2243            ButtonText     => $ButtonText,
2244            ButtonTitle    => $ButtonTitle,
2245            ButtonID       => $ButtonID
2246
2247        },
2248    );
2249
2250    if ( $ActivityDialog->{SubmitAdviceText} ) {
2251        $LayoutObject->Block(
2252            Name => 'SubmitAdviceText',
2253            Data => {
2254                AdviceText => $ActivityDialog->{SubmitAdviceText},
2255            },
2256        );
2257    }
2258
2259    # reload parent window
2260    if ( $Param{ParentReload} ) {
2261        $LayoutObject->AddJSData(
2262            Key   => 'ParentReload',
2263            Value => 1,
2264        );
2265    }
2266
2267    # Add the FormFooter
2268    $Output .= $LayoutObject->Output(
2269        TemplateFile => 'ProcessManagement/ActivityDialogFooter',
2270        Data         => {},
2271    );
2272
2273    # display regular footer only in non-ajax case
2274    if ( !$Self->{IsAjaxRequest} ) {
2275        $Output .= $LayoutObject->Footer( Type => $Self->{IsMainWindow} ? '' : 'Small' );
2276    }
2277
2278    return $Output;
2279}
2280
2281sub _RenderPendingTime {
2282    my ( $Self, %Param ) = @_;
2283
2284    # get layout object
2285    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
2286
2287    for my $Needed (qw(FormID)) {
2288        if ( !$Param{$Needed} ) {
2289            return {
2290                Success => 0,
2291                Message => $LayoutObject->{LanguageObject}
2292                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderPendingTime' ),
2293            };
2294        }
2295    }
2296    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
2297        return {
2298            Success => 0,
2299            Message => $LayoutObject->{LanguageObject}
2300                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderPendingTime' ),
2301        };
2302    }
2303
2304    my %Data = (
2305        Label => (
2306            $LayoutObject->{LanguageObject}->Translate('Pending Date')
2307                . ' ('
2308                . $LayoutObject->{LanguageObject}->Translate('for pending* states') . ')'
2309        ),
2310        FieldID => 'ResponsibleID',
2311        FormID  => $Param{FormID},
2312    );
2313
2314    my $Error = '';
2315    if ( IsHashRefWithData( $Param{Error} ) ) {
2316        if ( $Param{Error}->{'PendingtTimeDay'} ) {
2317            $Data{PendingtTimeDayError} = $LayoutObject->{LanguageObject}->Translate("Date invalid!");
2318            $Error = $Param{Error}->{'PendingtTimeDay'};
2319        }
2320        if ( $Param{Error}->{'PendingtTimeHour'} ) {
2321            $Data{PendingtTimeHourError} = $LayoutObject->{LanguageObject}->Translate("Date invalid!");
2322            $Error = $Param{Error}->{'PendingtTimeDay'};
2323        }
2324    }
2325
2326    my $Calendar = '';
2327
2328    # get ticket object
2329    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
2330
2331    # get used calendar if we have ticket data
2332    if ( IsHashRefWithData( $Param{Ticket} ) ) {
2333        $Calendar = $TicketObject->TicketCalendarGet(
2334            %{ $Param{Ticket} },
2335        );
2336    }
2337
2338    $Data{Content} = $LayoutObject->BuildDateSelection(
2339        Prefix => 'PendingTime',
2340        PendingTimeRequired =>
2341            (
2342            $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2
2343            ) ? 1 : 0,
2344        Format           => 'DateInputFormatLong',
2345        YearPeriodPast   => 0,
2346        YearPeriodFuture => 5,
2347        DiffTime         => $Param{ActivityDialogField}->{DefaultValue}
2348            || $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::PendingDiffTime')
2349            || 86400,
2350        Class                => $Error,
2351        Validate             => 1,
2352        ValidateDateInFuture => 1,
2353        Calendar             => $Calendar,
2354    );
2355
2356    $LayoutObject->Block(
2357        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:PendingTime',
2358        Data => \%Data,
2359    );
2360    if ( $Param{DescriptionShort} ) {
2361        $LayoutObject->Block(
2362            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:PendingTime:DescriptionShort',
2363            Data => {
2364                DescriptionShort => $Param{DescriptionShort},
2365            },
2366        );
2367    }
2368
2369    if ( $Param{DescriptionLong} ) {
2370        $LayoutObject->Block(
2371            Name => 'rw:PendingTime:DescriptionLong',
2372            Data => {
2373                DescriptionLong => $Param{DescriptionLong},
2374            },
2375        );
2376    }
2377
2378    return {
2379        Success => 1,
2380        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/PendingTime' ),
2381    };
2382}
2383
2384sub _RenderDynamicField {
2385    my ( $Self, %Param ) = @_;
2386
2387    # get layout object
2388    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
2389
2390    for my $Needed (qw(FormID FieldName)) {
2391        if ( !$Param{$Needed} ) {
2392            return {
2393                Success => 0,
2394                Message => $LayoutObject->{LanguageObject}
2395                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderDynamicField' ),
2396            };
2397        }
2398    }
2399
2400    my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
2401        Valid      => 1,
2402        ObjectType => 'Ticket',
2403    );
2404
2405    my $DynamicFieldConfig = ( grep { $_->{Name} eq $Param{FieldName} } @{$DynamicField} )[0];
2406
2407    if ( !IsHashRefWithData($DynamicFieldConfig) ) {
2408
2409        my $Message = "DynamicFieldConfig missing for field: $Param{FieldName}, or is not a Ticket Dynamic Field!";
2410
2411        # log error but does not stop the execution as it could be an old Article
2412        # DynamicField, see bug#11666
2413        $Kernel::OM->Get('Kernel::System::Log')->Log(
2414            Priority => 'error',
2415            Message  => $Message,
2416        );
2417
2418        return {
2419            Success => 1,
2420            HTML    => '',
2421        };
2422    }
2423
2424    my $PossibleValuesFilter;
2425
2426    # get dynamic field backend object
2427    my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');
2428
2429    my $IsACLReducible = $DynamicFieldBackendObject->HasBehavior(
2430        DynamicFieldConfig => $DynamicFieldConfig,
2431        Behavior           => 'IsACLReducible',
2432    );
2433
2434    # get ticket object
2435    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
2436
2437    if ($IsACLReducible) {
2438
2439        # get PossibleValues
2440        my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet(
2441            DynamicFieldConfig => $DynamicFieldConfig,
2442        );
2443
2444        # All Ticket DynamicFields
2445        # used for ACL checking
2446        my %DynamicFieldCheckParam = map { $_ => $Param{GetParam}{$_} }
2447            grep {m{^DynamicField_}xms} ( keys %{ $Param{GetParam} } );
2448
2449        # check if field has PossibleValues property in its configuration
2450        if ( IsHashRefWithData($PossibleValues) ) {
2451
2452            # convert possible values key => value to key => key for ACLs using a Hash slice
2453            my %AclData = %{$PossibleValues};
2454            @AclData{ keys %AclData } = keys %AclData;
2455
2456            # set possible values filter from ACLs
2457            my $ACL = $TicketObject->TicketAcl(
2458                %{ $Param{GetParam} },
2459                DynamicField  => \%DynamicFieldCheckParam,
2460                Action        => $Self->{Action},
2461                ReturnType    => 'Ticket',
2462                ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
2463                Data          => \%AclData,
2464                UserID        => $Self->{UserID},
2465            );
2466            if ($ACL) {
2467                my %Filter = $TicketObject->TicketAclData();
2468
2469                # convert Filer key => key back to key => value using map
2470                %{$PossibleValuesFilter} = map { $_ => $PossibleValues->{$_} } keys %Filter;
2471            }
2472        }
2473    }
2474
2475    my $ServerError;
2476    if ( IsHashRefWithData( $Param{Error} ) ) {
2477        if (
2478            defined $Param{Error}->{ $Param{FieldName} }
2479            && $Param{Error}->{ $Param{FieldName} } ne ''
2480            )
2481        {
2482            $ServerError = 1;
2483        }
2484    }
2485
2486    # get stored dynamic field value (split)
2487    if ( $Self->{LinkTicketID} ) {
2488
2489        my $Value = $DynamicFieldBackendObject->ValueGet(
2490            DynamicFieldConfig => $DynamicFieldConfig,
2491            ObjectID           => $Self->{LinkTicketID},
2492        );
2493
2494        $Param{GetParam}->{ 'DynamicField_' . $Param{FieldName} } = $Value;
2495    }
2496    my $ErrorMessage = '';
2497    if ( IsHashRefWithData( $Param{ErrorMessages} ) ) {
2498        if (
2499            defined $Param{ErrorMessages}->{ $Param{FieldName} }
2500            && $Param{ErrorMessages}->{ $Param{FieldName} } ne ''
2501            )
2502        {
2503            $ErrorMessage = $Param{ErrorMessages}->{ $Param{FieldName} };
2504        }
2505    }
2506
2507    my $DynamicFieldHTML = $DynamicFieldBackendObject->EditFieldRender(
2508        DynamicFieldConfig   => $DynamicFieldConfig,
2509        PossibleValuesFilter => $PossibleValuesFilter,
2510        Value                => $Param{GetParam}{ 'DynamicField_' . $Param{FieldName} },
2511        LayoutObject         => $LayoutObject,
2512        ParamObject          => $Kernel::OM->Get('Kernel::System::Web::Request'),
2513        AJAXUpdate           => 1,
2514        Mandatory            => $Param{ActivityDialogField}->{Display} == 2,
2515        UpdatableFields      => $Param{AJAXUpdatableFields},
2516        ServerError          => $ServerError,
2517        ErrorMessage         => $ErrorMessage,
2518    );
2519
2520    my %Data = (
2521        Name    => $DynamicFieldConfig->{Name},
2522        Label   => $DynamicFieldHTML->{Label},
2523        Content => $DynamicFieldHTML->{Field},
2524    );
2525
2526    $LayoutObject->Block(
2527        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:DynamicField',
2528        Data => \%Data,
2529    );
2530    if ( $Param{DescriptionShort} ) {
2531        $LayoutObject->Block(
2532            Name => $Param{ActivityDialogField}->{LayoutBlock}
2533                || 'rw:DynamicField:DescriptionShort',
2534            Data => {
2535                DescriptionShort => $Param{DescriptionShort},
2536            },
2537        );
2538    }
2539
2540    if ( $Param{DescriptionLong} ) {
2541        $LayoutObject->Block(
2542            Name => 'rw:DynamicField:DescriptionLong',
2543            Data => {
2544                DescriptionLong => $Param{DescriptionLong},
2545            },
2546        );
2547    }
2548
2549    return {
2550        Success => 1,
2551        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/DynamicField' ),
2552    };
2553}
2554
2555sub _RenderTitle {
2556    my ( $Self, %Param ) = @_;
2557
2558    # get layout object
2559    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
2560
2561    for my $Needed (qw(FormID)) {
2562        if ( !$Param{$Needed} ) {
2563            return {
2564                Success => 0,
2565                Message => $LayoutObject->{LanguageObject}
2566                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderTitle' ),
2567            };
2568        }
2569    }
2570    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
2571        return {
2572            Success => 0,
2573            Message => $LayoutObject->{LanguageObject}
2574                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderTitle' ),
2575        };
2576    }
2577
2578    my $Title = $Param{Ticket}->{Title} // '';
2579
2580    if ( !$Title && $Self->{LinkArticleData} ) {
2581        my %Ticket = $Kernel::OM->Get('Kernel::System::Ticket')->TicketGet(
2582            TicketID => $Self->{LinkArticleData}->{TicketID},
2583            UserID   => $Self->{UserID},
2584        );
2585        $Title = $Ticket{Title};
2586    }
2587
2588    $Param{GetParam}->{Title} //= $Title;
2589
2590    my %Data = (
2591        Label            => $LayoutObject->{LanguageObject}->Translate("Title"),
2592        FieldID          => 'Title',
2593        FormID           => $Param{FormID},
2594        Value            => $Param{GetParam}->{Title},
2595        Name             => 'Title',
2596        MandatoryClass   => '',
2597        ValidateRequired => '',
2598    );
2599
2600    # If field is required put in the necessary variables for
2601    # ValidateRequired class input field, Mandatory class for the label
2602    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
2603        $Data{ValidateRequired} = 'Validate_Required';
2604        $Data{MandatoryClass}   = 'Mandatory';
2605    }
2606
2607    # output server errors
2608    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'Title'} ) {
2609        $Data{ServerError} = 'ServerError';
2610    }
2611
2612    $LayoutObject->Block(
2613        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Title',
2614        Data => \%Data,
2615    );
2616
2617    # set mandatory label marker
2618    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
2619        $LayoutObject->Block(
2620            Name => 'LabelSpan',
2621            Data => {},
2622        );
2623    }
2624
2625    if ( $Param{DescriptionShort} ) {
2626        $LayoutObject->Block(
2627            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Title:DescriptionShort',
2628            Data => {
2629                DescriptionShort => $Param{DescriptionShort},
2630            },
2631        );
2632    }
2633
2634    if ( $Param{DescriptionLong} ) {
2635        $LayoutObject->Block(
2636            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Title:DescriptionLong',
2637            Data => {
2638                DescriptionLong => $Param{DescriptionLong},
2639            },
2640        );
2641    }
2642
2643    return {
2644        Success => 1,
2645        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Title' ),
2646    };
2647
2648}
2649
2650sub _RenderArticle {
2651    my ( $Self, %Param ) = @_;
2652
2653    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
2654    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
2655
2656    for my $Needed (qw(FormID Ticket)) {
2657        if ( !$Param{$Needed} ) {
2658            return {
2659                Success => 0,
2660                Message => $LayoutObject->{LanguageObject}
2661                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderArticle' ),
2662            };
2663        }
2664    }
2665    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
2666        return {
2667            Success => 0,
2668            Message => $LayoutObject->{LanguageObject}
2669                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderArticle' ),
2670        };
2671    }
2672
2673    if ( IsHashRefWithData( $Self->{LinkArticleData} ) ) {
2674        my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
2675        my $TicketNumber = $TicketObject->TicketNumberLookup(
2676            TicketID => $Self->{LinkArticleData}->{TicketID},
2677        );
2678
2679        # prepare subject
2680        $Param{GetParam}->{Subject} = $TicketObject->TicketSubjectClean(
2681            TicketNumber => $TicketNumber,
2682            Subject      => $Self->{LinkArticleData}->{Subject} || '',
2683        );
2684
2685        # body preparation for plain text processing
2686        $Param{GetParam}->{Body} = $LayoutObject->ArticleQuote(
2687            TicketID           => $Self->{LinkArticleData}->{TicketID},
2688            ArticleID          => $Self->{LinkArticleData}->{ArticleID},
2689            FormID             => $Self->{FormID},
2690            UploadCacheObject  => $Kernel::OM->Get('Kernel::System::Web::UploadCache'),
2691            AttachmentsInclude => 1,
2692        );
2693
2694        my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
2695            String => $Param{GetParam}->{Body},
2696
2697            # Strip out external content if BlockLoadingRemoteContent is enabled.
2698            NoExtSrcLoad => $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent'),
2699
2700            # Disallow potentially unsafe content.
2701            NoApplet     => 1,
2702            NoObject     => 1,
2703            NoEmbed      => 1,
2704            NoSVG        => 1,
2705            NoJavaScript => 1,
2706        );
2707        $Param{GetParam}->{Body} = $SafetyCheckResult{String};
2708    }
2709
2710    # get all attachments meta data
2711    my @Attachments = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDGetAllFilesMeta(
2712        FormID => $Self->{FormID},
2713    );
2714
2715    # show attachments
2716    ATTACHMENT:
2717    for my $Attachment (@Attachments) {
2718        if (
2719            $Attachment->{ContentID}
2720            && $LayoutObject->{BrowserRichText}
2721            && ( $Attachment->{ContentType} =~ /image/i )
2722            && ( $Attachment->{Disposition} eq 'inline' )
2723            )
2724        {
2725            next ATTACHMENT;
2726        }
2727
2728        push @{ $Param{AttachmentList} }, $Attachment;
2729    }
2730
2731    my %Data = (
2732        Name             => 'Article',
2733        MandatoryClass   => '',
2734        ValidateRequired => '',
2735        Subject          => $Param{GetParam}->{Subject},
2736        Body             => $Param{GetParam}->{Body},
2737        LabelSubject     => $Param{ActivityDialogField}->{Config}->{LabelSubject}
2738            || $LayoutObject->{LanguageObject}->Translate("Subject"),
2739        LabelBody => $Param{ActivityDialogField}->{Config}->{LabelBody}
2740            || $LayoutObject->{LanguageObject}->Translate("Text"),
2741        AttachmentList => $Param{AttachmentList},
2742    );
2743
2744    # If field is required put in the necessary variables for
2745    # ValidateRequired class input field, Mandatory class for the label
2746    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
2747        $Data{ValidateRequired} = 'Validate_Required';
2748        $Data{MandatoryClass}   = 'Mandatory';
2749    }
2750
2751    # output server errors
2752    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ArticleSubject'} ) {
2753        $Data{SubjectServerError} = 'ServerError';
2754    }
2755    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ArticleBody'} ) {
2756        $Data{BodyServerError} = 'ServerError';
2757    }
2758
2759    $LayoutObject->Block(
2760        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Article',
2761        Data => \%Data,
2762    );
2763
2764    # set mandatory label marker
2765    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
2766        $LayoutObject->Block(
2767            Name => 'LabelSpanSubject',
2768            Data => {},
2769        );
2770        $LayoutObject->Block(
2771            Name => 'LabelSpanBody',
2772            Data => {},
2773        );
2774    }
2775
2776    # add rich text editor
2777    if ( $LayoutObject->{BrowserRichText} ) {
2778
2779        # use height/width defined for this screen
2780        $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
2781        $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;
2782
2783        # set up rich text editor
2784        $LayoutObject->SetRichTextParameters(
2785            Data => \%Param,
2786        );
2787    }
2788
2789    if ( $Param{DescriptionShort} ) {
2790        $LayoutObject->Block(
2791            Name => 'rw:Article:DescriptionShort',
2792            Data => {
2793                DescriptionShort => $Param{DescriptionShort},
2794            },
2795        );
2796    }
2797
2798    if ( $Param{DescriptionLong} ) {
2799        $LayoutObject->Block(
2800            Name => 'rw:Article:DescriptionLong',
2801            Data => {
2802                DescriptionLong => $Param{DescriptionLong},
2803            },
2804        );
2805    }
2806
2807    if ( $Param{InformAgents} ) {
2808
2809        my %ShownUsers;
2810        my %AllGroupsMembers = $Kernel::OM->Get('Kernel::System::User')->UserList(
2811            Type  => 'Long',
2812            Valid => 1,
2813        );
2814        my $GID = $Kernel::OM->Get('Kernel::System::Queue')->GetQueueGroupID( QueueID => $Param{Ticket}->{QueueID} );
2815        my %MemberList = $Kernel::OM->Get('Kernel::System::Group')->PermissionGroupGet(
2816            GroupID => $GID,
2817            Type    => 'ro',
2818        );
2819        for my $UserID ( sort keys %MemberList ) {
2820            $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
2821        }
2822        $Param{OptionStrg} = $LayoutObject->BuildSelection(
2823            Data       => \%ShownUsers,
2824            SelectedID => '',
2825            Name       => 'InformUserID',
2826            Multiple   => 1,
2827            Size       => 3,
2828            Class      => 'Modernize',
2829        );
2830        $LayoutObject->Block(
2831            Name => 'rw:Article:InformAgent',
2832            Data => \%Param,
2833        );
2834    }
2835
2836    # output server errors
2837    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'TimeUnits'} ) {
2838        $Param{TimeUnitsInvalid} = 'ServerError';
2839    }
2840
2841    # show time units
2842    if (
2843        $ConfigObject->Get('Ticket::Frontend::AccountTime')
2844        && $Param{ActivityDialogField}->{Config}->{TimeUnits}
2845        )
2846    {
2847
2848        if ( $ConfigObject->Get('Ticket::Frontend::NeedAccountedTime') ) {
2849
2850            $LayoutObject->Block(
2851                Name => 'TimeUnitsLabelMandatory',
2852                Data => \%Param,
2853            );
2854            $Param{TimeUnitsRequired} = 'Validate_Required';
2855        }
2856        elsif ( $Param{ActivityDialogField}->{Config}->{TimeUnits} == 1 ) {
2857
2858            $LayoutObject->Block(
2859                Name => 'TimeUnitsLabel',
2860                Data => \%Param,
2861            );
2862            $Param{TimeUnitsRequired} = '';
2863        }
2864        else {
2865
2866            $LayoutObject->Block(
2867                Name => 'TimeUnitsLabelMandatory',
2868                Data => \%Param,
2869            );
2870            $Param{TimeUnitsRequired} = 'Validate_Required';
2871        }
2872
2873        # Get TimeUnits value.
2874        $Param{TimeUnits} = $Param{GetParam}{TimeUnits};
2875
2876        if ( !defined $Param{TimeUnits} && $Self->{ArticleID} ) {
2877            $Param{TimeUnits} = $Self->_GetTimeUnits(
2878                ArticleID => $Self->{ArticleID},
2879            );
2880        }
2881
2882        $LayoutObject->Block(
2883            Name => 'TimeUnits',
2884            Data => \%Param,
2885        );
2886    }
2887
2888    return {
2889        Success => 1,
2890        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Article' ),
2891    };
2892}
2893
2894sub _GetTimeUnits {
2895    my ( $Self, %Param ) = @_;
2896
2897    my $AccountedTime = '';
2898
2899    # Get accounted time if AccountTime config item is enabled.
2900    if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::AccountTime') && defined $Param{ArticleID} ) {
2901        $AccountedTime = $Kernel::OM->Get('Kernel::System::Ticket::Article')->ArticleAccountedTimeGet(
2902            ArticleID => $Param{ArticleID},
2903        );
2904    }
2905
2906    return $AccountedTime ? $AccountedTime : '';
2907}
2908
2909sub _RenderCustomer {
2910    my ( $Self, %Param ) = @_;
2911
2912    # get layout object
2913    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
2914
2915    for my $Needed (qw(FormID)) {
2916        if ( !$Param{$Needed} ) {
2917            return {
2918                Success => 0,
2919                Message => $LayoutObject->{LanguageObject}
2920                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderCustomer' ),
2921            };
2922        }
2923    }
2924    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
2925        return {
2926            Success => 0,
2927            Message => $LayoutObject->{LanguageObject}
2928                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderCustomer' ),
2929        };
2930    }
2931
2932    my %CustomerUserData = ();
2933
2934    my $SubmittedCustomerUserID = $Param{GetParam}{CustomerUserID};
2935
2936    my %Data = (
2937        LabelCustomerUser => $LayoutObject->{LanguageObject}->Translate("Customer user"),
2938        LabelCustomerID   => $LayoutObject->{LanguageObject}->Translate("CustomerID"),
2939        FormID            => $Param{FormID},
2940        MandatoryClass    => '',
2941        ValidateRequired  => '',
2942    );
2943
2944    # If field is required put in the necessary variables for
2945    # ValidateRequired class input field, Mandatory class for the label
2946    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
2947        $Data{ValidateRequired} = 'Validate_Required';
2948        $Data{MandatoryClass}   = 'Mandatory';
2949    }
2950
2951    # output server errors
2952    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{CustomerUserID} ) {
2953        $Data{CustomerUserIDServerError} = 'ServerError';
2954    }
2955    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{CustomerID} ) {
2956        $Data{CustomerIDServerError} = 'ServerError';
2957    }
2958
2959    if ( $Self->{LinkTicketData} ) {
2960        %CustomerUserData = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserDataGet(
2961            User => $Self->{LinkTicketData}->{CustomerUserID},
2962        );
2963    }
2964
2965    if (
2966        ( IsHashRefWithData( $Param{Ticket} ) && $Param{Ticket}->{CustomerUserID} )
2967        || $SubmittedCustomerUserID
2968        )
2969    {
2970        %CustomerUserData = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserDataGet(
2971            User => $SubmittedCustomerUserID
2972                || $Param{Ticket}{CustomerUserID},
2973        );
2974    }
2975
2976    # Customer user from article is preselected for new split ticket. See bug#12956.
2977    if (
2978        IsHashRefWithData( $Self->{LinkArticleData} )
2979        && $Self->{LinkArticleData}->{From}
2980        && $Self->{LinkArticleData}->{SenderType} eq 'customer'
2981        )
2982    {
2983
2984        my @ArticleFromAddress = Mail::Address->parse( $Self->{LinkArticleData}->{From} );
2985
2986        my $CustomerUserObject = $Kernel::OM->Get('Kernel::System::CustomerUser');
2987        my %List               = $CustomerUserObject->CustomerSearch(
2988            PostMasterSearch => $ArticleFromAddress[0]->address(),
2989            Valid            => 1,
2990        );
2991
2992        my @CustomerUser = sort keys %List;
2993        %CustomerUserData = $CustomerUserObject->CustomerUserDataGet(
2994            User => $CustomerUser[0],
2995        );
2996    }
2997
2998    # show customer field as "FirstName Lastname" <MailAddress>
2999    if ( IsHashRefWithData( \%CustomerUserData ) ) {
3000        $Data{CustomerUserID}       = "\"$CustomerUserData{UserFullname}" . "\" <$CustomerUserData{UserEmail}>";
3001        $Data{CustomerID}           = $CustomerUserData{UserCustomerID} || '';
3002        $Data{SelectedCustomerUser} = $CustomerUserData{UserID} || '';
3003    }
3004
3005    # When there is no Customer in the DB, it could be unknown Customer, set it from the ticket.
3006    # See bug#12797 ( https://bugs.otrs.org/show_bug.cgi?id=12797 ).
3007    else {
3008        $Data{CustomerUserID} = $Param{Ticket}{CustomerUserID} || '';
3009        $Data{CustomerID}     = $Param{Ticket}{CustomerID}     || '';
3010    }
3011
3012    # send data to JS
3013    $LayoutObject->AddJSData(
3014        Key   => 'CustomerFieldsToUpdate',
3015        Value => $Param{AJAXUpdatableFields},
3016    );
3017
3018    if ( $Param{DescriptionShort} ) {
3019        $Data{DescriptionShort} = $Param{DescriptionShort};
3020    }
3021
3022    $LayoutObject->Block(
3023        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Customer',
3024        Data => \%Data,
3025    );
3026
3027    # set mandatory label marker
3028    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
3029        $LayoutObject->Block(
3030            Name => 'LabelSpanCustomerUser',
3031            Data => {},
3032        );
3033    }
3034
3035    if ( $Param{DescriptionLong} ) {
3036        $LayoutObject->Block(
3037            Name => 'rw:Customer:DescriptionLong',
3038            Data => {
3039                DescriptionLong => $Param{DescriptionLong},
3040            },
3041        );
3042    }
3043
3044    return {
3045        Success => 1,
3046        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Customer' ),
3047    };
3048}
3049
3050sub _RenderResponsible {
3051    my ( $Self, %Param ) = @_;
3052
3053    # get layout object
3054    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
3055
3056    for my $Needed (qw(FormID)) {
3057        if ( !$Param{$Needed} ) {
3058            return {
3059                Success => 0,
3060                Message => $LayoutObject->{LanguageObject}
3061                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderResponsible' ),
3062            };
3063        }
3064    }
3065    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
3066        return {
3067            Success => 0,
3068            Message => $LayoutObject->{LanguageObject}
3069                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderResponsible' ),
3070        };
3071    }
3072
3073    if ( $Self->{LinkTicketData} ) {
3074        $Param{GetParam}->{ResponsibleAll} = 1;
3075    }
3076
3077    my $Responsibles = $Self->_GetResponsibles( %{ $Param{GetParam} } );
3078
3079    my %Data = (
3080        Label            => $LayoutObject->{LanguageObject}->Translate("Responsible"),
3081        FieldID          => 'ResponsibleID',
3082        FormID           => $Param{FormID},
3083        ResponsibleAll   => $Param{GetParam}{ResponsibleAll},
3084        MandatoryClass   => '',
3085        ValidateRequired => '',
3086    );
3087
3088    # if field is required put in the necessary variables for
3089    #    ValidateRequired class input field, Mandatory class for the label
3090    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
3091        $Data{ValidateRequired} = 'Validate_Required';
3092        $Data{MandatoryClass}   = 'Mandatory';
3093    }
3094
3095    my $SelectedValue;
3096
3097    # get user object
3098    my $UserObject = $Kernel::OM->Get('Kernel::System::User');
3099
3100    if ( $Param{ActivityDialogField}->{DefaultValue} ) {
3101
3102        if ( $Param{FieldName} eq 'Responsible' ) {
3103
3104            # Fetch DefaultValue from Config
3105            if ( !$SelectedValue ) {
3106                $SelectedValue = $UserObject->UserLookup(
3107                    UserLogin => $Param{ActivityDialogField}->{DefaultValue} || '',
3108                );
3109                if ($SelectedValue) {
3110                    $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
3111                }
3112            }
3113        }
3114        else {
3115            if ( !$SelectedValue ) {
3116                $SelectedValue = $UserObject->UserLookup(
3117                    UserID => $Param{ActivityDialogField}->{DefaultValue} || '',
3118                );
3119            }
3120        }
3121    }
3122
3123    my $ResponsibleIDParam = $Param{GetParam}{ResponsibleID};
3124    if ( $ResponsibleIDParam && !$SelectedValue ) {
3125        $SelectedValue = $UserObject->UserLookup( UserID => $ResponsibleIDParam );
3126    }
3127
3128    # if there is no user from GetParam or default and the field is mandatory get it from the ticket
3129    #    (if any)
3130    if (
3131        !$SelectedValue
3132        && $Param{ActivityDialogField}->{Display} == 2
3133        && IsHashRefWithData( $Param{Ticket} )
3134        )
3135    {
3136        $SelectedValue = $Param{Ticket}->{Responsible};
3137    }
3138
3139    # if we have a user already and the field is not mandatory and it is the same as in ticket, then
3140    #    set it to none (as it doesn't need to be changed afterall)
3141    elsif (
3142        $SelectedValue
3143        && $Param{ActivityDialogField}->{Display} != 2
3144        && IsHashRefWithData( $Param{Ticket} )
3145        && $SelectedValue eq $Param{Ticket}->{Responsible}
3146        )
3147    {
3148        $SelectedValue = '';
3149    }
3150
3151    # set server errors
3152    my $ServerError = '';
3153    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ResponsibleID'} ) {
3154        $ServerError = 'ServerError';
3155    }
3156
3157    # look up $SelectedID
3158    my $SelectedID;
3159    if ($SelectedValue) {
3160        $SelectedID = $UserObject->UserLookup(
3161            UserLogin => $SelectedValue,
3162        );
3163    }
3164
3165    if ( $Self->{LinkTicketData} ) {
3166        $SelectedID = $Self->{LinkTicketData}->{ResponsibleID};
3167    }
3168
3169    # build Responsible string
3170    $Data{Content} = $LayoutObject->BuildSelection(
3171        Data         => $Responsibles,
3172        Name         => 'ResponsibleID',
3173        Translation  => 1,
3174        SelectedID   => $SelectedID,
3175        Class        => "Modernize $ServerError",
3176        PossibleNone => 1,
3177    );
3178
3179    # send data to JS
3180    $LayoutObject->AddJSData(
3181        Key   => 'ResponsibleFieldsToUpdate',
3182        Value => $Param{AJAXUpdatableFields}
3183    );
3184
3185    $LayoutObject->Block(
3186        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Responsible',
3187        Data => \%Data,
3188    );
3189
3190    # set mandatory label marker
3191    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
3192        $LayoutObject->Block(
3193            Name => 'LabelSpan',
3194            Data => {},
3195        );
3196    }
3197
3198    if ( $Param{DescriptionShort} ) {
3199        $LayoutObject->Block(
3200            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Responsible:DescriptionShort',
3201            Data => {
3202                DescriptionShort => $Param{DescriptionShort},
3203            },
3204        );
3205    }
3206
3207    if ( $Param{DescriptionLong} ) {
3208        $LayoutObject->Block(
3209            Name => 'rw:Responsible:DescriptionLong',
3210            Data => {
3211                DescriptionLong => $Param{DescriptionLong},
3212            },
3213        );
3214    }
3215
3216    return {
3217        Success => 1,
3218        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Responsible' ),
3219    };
3220
3221}
3222
3223sub _RenderOwner {
3224    my ( $Self, %Param ) = @_;
3225
3226    # get layout object
3227    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
3228
3229    for my $Needed (qw(FormID)) {
3230        if ( !$Param{$Needed} ) {
3231            return {
3232                Success => 0,
3233                Message => $LayoutObject->{LanguageObject}
3234                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderOwner' ),
3235            };
3236        }
3237    }
3238    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
3239        return {
3240            Success => 0,
3241            Message => $LayoutObject->{LanguageObject}
3242                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderOwner' ),
3243        };
3244    }
3245
3246    if ( $Self->{LinkTicketData} ) {
3247        $Param{GetParam}->{OwnerAll} = 1;
3248    }
3249
3250    my $Owners = $Self->_GetOwners( %{ $Param{GetParam} } );
3251
3252    my %Data = (
3253        Label            => $LayoutObject->{LanguageObject}->Translate("Owner"),
3254        FieldID          => 'OwnerID',
3255        FormID           => $Param{FormID},
3256        OwnerAll         => $Param{GetParam}{OwnerAll},
3257        MandatoryClass   => '',
3258        ValidateRequired => '',
3259    );
3260
3261    # if field is required put in the necessary variables for
3262    #    ValidateRequired class input field, Mandatory class for the label
3263    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
3264        $Data{ValidateRequired} = 'Validate_Required';
3265        $Data{MandatoryClass}   = 'Mandatory';
3266    }
3267
3268    my $SelectedValue;
3269
3270    # get user object
3271    my $UserObject = $Kernel::OM->Get('Kernel::System::User');
3272
3273    if ( $Param{ActivityDialogField}->{DefaultValue} ) {
3274
3275        if ( $Param{FieldName} eq 'Owner' ) {
3276
3277            if ( !$SelectedValue ) {
3278
3279                # Fetch DefaultValue from Config
3280                $SelectedValue = $UserObject->UserLookup(
3281                    UserLogin => $Param{ActivityDialogField}->{DefaultValue} || '',
3282                );
3283                if ($SelectedValue) {
3284                    $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
3285                }
3286            }
3287        }
3288        else {
3289            if ( !$SelectedValue ) {
3290                $SelectedValue = $UserObject->UserLookup(
3291                    UserID => $Param{ActivityDialogField}->{DefaultValue} || '',
3292                );
3293            }
3294        }
3295    }
3296
3297    my $OwnerIDParam = $Param{GetParam}{OwnerID};
3298    if ( $OwnerIDParam && !$SelectedValue ) {
3299        $SelectedValue = $UserObject->UserLookup(
3300            UserID => $OwnerIDParam,
3301        );
3302    }
3303
3304    # if there is no user from GetParam or default and the field is mandatory get it from the ticket
3305    #    (if any)
3306    if (
3307        !$SelectedValue
3308        && $Param{ActivityDialogField}->{Display} == 2
3309        && IsHashRefWithData( $Param{Ticket} )
3310        )
3311    {
3312        $SelectedValue = $Param{Ticket}->{Owner};
3313    }
3314
3315    # if we have a user already and the field is not mandatory and it is the same as in ticket, then
3316    #    set it to none (as it doesn't need to be changed afterall)
3317    elsif (
3318        $SelectedValue
3319        && $Param{ActivityDialogField}->{Display} != 2
3320        && IsHashRefWithData( $Param{Ticket} )
3321        && $SelectedValue eq $Param{Ticket}->{Owner}
3322        )
3323    {
3324        $SelectedValue = '';
3325    }
3326
3327    # set server errors
3328    my $ServerError = '';
3329    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'OwnerID'} ) {
3330        $ServerError = 'ServerError';
3331    }
3332
3333    if ( $Self->{LinkTicketData} ) {
3334        $SelectedValue = $Self->{LinkTicketData}->{OwnerID};
3335    }
3336
3337    # look up $SelectedID
3338    my $SelectedID;
3339    if ($SelectedValue) {
3340        $SelectedID = $UserObject->UserLookup(
3341            UserLogin => $SelectedValue,
3342        );
3343    }
3344
3345    # build Owner string
3346    $Data{Content} = $LayoutObject->BuildSelection(
3347        Data         => $Owners,
3348        Name         => 'OwnerID',
3349        Translation  => 1,
3350        SelectedID   => $SelectedID || '',
3351        Class        => "Modernize $ServerError",
3352        PossibleNone => 1,
3353    );
3354
3355    # send data to JS
3356    $LayoutObject->AddJSData(
3357        Key   => 'OwnerFieldsToUpdate',
3358        Value => $Param{AJAXUpdatableFields}
3359    );
3360
3361    $LayoutObject->Block(
3362        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Owner',
3363        Data => \%Data,
3364    );
3365
3366    # set mandatory label marker
3367    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
3368        $LayoutObject->Block(
3369            Name => 'LabelSpan',
3370            Data => {},
3371        );
3372    }
3373
3374    if ( $Param{DescriptionShort} ) {
3375        $LayoutObject->Block(
3376            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Owner:DescriptionShort',
3377            Data => {
3378                DescriptionShort => $Param{DescriptionShort},
3379            },
3380        );
3381    }
3382
3383    if ( $Param{DescriptionLong} ) {
3384        $LayoutObject->Block(
3385            Name => 'rw:Owner:DescriptionLong',
3386            Data => {
3387                DescriptionLong => $Param{DescriptionLong},
3388            },
3389        );
3390    }
3391
3392    return {
3393        Success => 1,
3394        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Owner' ),
3395    };
3396}
3397
3398sub _RenderSLA {
3399    my ( $Self, %Param ) = @_;
3400
3401    # get layout object
3402    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
3403
3404    for my $Needed (qw(FormID)) {
3405        if ( !$Param{$Needed} ) {
3406            return {
3407                Success => 0,
3408                Message => $LayoutObject->{LanguageObject}
3409                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderSLA' ),
3410            };
3411        }
3412    }
3413    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
3414        return {
3415            Success => 0,
3416            Message => $LayoutObject->{LanguageObject}
3417                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderSLA' ),
3418        };
3419    }
3420
3421    if ( $Self->{LinkTicketData} ) {
3422        $Param{GetParam}->{QueueID}        = $Self->{LinkTicketData}->{QueueID};
3423        $Param{GetParam}->{TicketID}       = $Self->{LinkTicketData}->{TicketID};
3424        $Param{GetParam}->{CustomerUserID} = $Self->{LinkTicketData}->{CustomerUserID};
3425    }
3426
3427    # create a local copy of the GetParam
3428    my %GetServicesParam = %{ $Param{GetParam} };
3429
3430    # use ticket information as a fall back if customer was already set, otherwise when the
3431    # activity dialog displays the service list will be initially empty, see bug#10059
3432    if ( IsHashRefWithData( $Param{Ticket} ) ) {
3433        $GetServicesParam{CustomerUserID} ||= $Param{Ticket}->{CustomerUserID} ||= '';
3434    }
3435
3436    my $Services = $Self->_GetServices(
3437        %GetServicesParam,
3438    );
3439
3440    if ( $Self->{LinkTicketData} ) {
3441        $Param{GetParam}->{Services}  = $Services;
3442        $Param{GetParam}->{ServiceID} = $Self->{LinkTicketData}->{ServiceID};
3443    }
3444
3445    my $SLAs = $Self->_GetSLAs(
3446        %{ $Param{GetParam} },
3447        Services => $Services,
3448    );
3449
3450    my %Data = (
3451        Label            => $LayoutObject->{LanguageObject}->Translate("SLA"),
3452        FieldID          => 'SLAID',
3453        FormID           => $Param{FormID},
3454        MandatoryClass   => '',
3455        ValidateRequired => '',
3456    );
3457
3458    # If field is required put in the necessary variables for
3459    # ValidateRequired class input field, Mandatory class for the label
3460    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
3461        $Data{ValidateRequired} = 'Validate_Required';
3462        $Data{MandatoryClass}   = 'Mandatory';
3463    }
3464
3465    my $SelectedValue;
3466
3467    # get SLA object
3468    my $SLAObject = $Kernel::OM->Get('Kernel::System::SLA');
3469
3470    my $SLAIDParam = $Param{GetParam}{SLAID};
3471    if ($SLAIDParam) {
3472        $SelectedValue = $SLAObject->SLALookup( SLAID => $SLAIDParam );
3473    }
3474
3475    if ( $Param{FieldName} eq 'SLA' ) {
3476
3477        if ( !$SelectedValue ) {
3478
3479            # Fetch DefaultValue from Config
3480            if (
3481                defined $Param{ActivityDialogField}->{DefaultValue}
3482                && $Param{ActivityDialogField}->{DefaultValue} ne ''
3483                )
3484            {
3485                $SelectedValue = $SLAObject->SLALookup(
3486                    SLA => $Param{ActivityDialogField}->{DefaultValue},
3487                );
3488            }
3489
3490            if ($SelectedValue) {
3491                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
3492            }
3493        }
3494    }
3495    else {
3496        if ( !$SelectedValue ) {
3497            if (
3498                defined $Param{ActivityDialogField}->{DefaultValue}
3499                && $Param{ActivityDialogField}->{DefaultValue} ne ''
3500                )
3501            {
3502                $SelectedValue = $SLAObject->SLALookup(
3503                    SLA => $Param{ActivityDialogField}->{DefaultValue},
3504                );
3505            }
3506        }
3507    }
3508
3509    # Get TicketValue
3510    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
3511        $SelectedValue = $Param{Ticket}->{SLA};
3512    }
3513
3514    # set server errors
3515    my $ServerError = '';
3516    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'SLAID'} ) {
3517        $ServerError = 'ServerError';
3518    }
3519
3520    if ( $Self->{LinkTicketData} ) {
3521        $SelectedValue = $Self->{LinkTicketData}->{SLA};
3522    }
3523
3524    # build SLA string
3525    $Data{Content} = $LayoutObject->BuildSelection(
3526        Data          => $SLAs,
3527        Name          => 'SLAID',
3528        SelectedValue => $SelectedValue,
3529        PossibleNone  => 1,
3530        Sort          => 'AlphanumericValue',
3531        Translation   => 0,
3532        Class         => "Modernize $ServerError",
3533        Max           => 200,
3534    );
3535
3536    # send data to JS
3537    $LayoutObject->AddJSData(
3538        Key   => 'SLAFieldsToUpdate',
3539        Value => $Param{AJAXUpdatableFields}
3540    );
3541
3542    $LayoutObject->Block(
3543        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:SLA',
3544        Data => \%Data,
3545    );
3546
3547    # set mandatory label marker
3548    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
3549        $LayoutObject->Block(
3550            Name => 'LabelSpan',
3551            Data => {},
3552        );
3553    }
3554
3555    if ( $Param{DescriptionShort} ) {
3556        $LayoutObject->Block(
3557            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:SLA:DescriptionShort',
3558            Data => {
3559                DescriptionShort => $Param{DescriptionShort},
3560            },
3561        );
3562    }
3563
3564    if ( $Param{DescriptionLong} ) {
3565        $LayoutObject->Block(
3566            Name => 'rw:SLA:DescriptionLong',
3567            Data => {
3568                DescriptionLong => $Param{DescriptionLong},
3569            },
3570        );
3571    }
3572
3573    return {
3574        Success => 1,
3575        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/SLA' ),
3576    };
3577}
3578
3579sub _RenderService {
3580    my ( $Self, %Param ) = @_;
3581
3582    # get layout object
3583    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
3584
3585    for my $Needed (qw(FormID)) {
3586        if ( !$Param{$Needed} ) {
3587            return {
3588                Success => 0,
3589                Message => $LayoutObject->{LanguageObject}
3590                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderService' ),
3591            };
3592        }
3593    }
3594    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
3595        return {
3596            Success => 0,
3597            Message => $LayoutObject->{LanguageObject}
3598                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderService' ),
3599        };
3600    }
3601
3602    if ( $Self->{LinkTicketData} ) {
3603        $Param{GetParam}->{QueueID}        = $Self->{LinkTicketData}->{QueueID};
3604        $Param{GetParam}->{TicketID}       = $Self->{LinkTicketData}->{TicketID};
3605        $Param{GetParam}->{CustomerUserID} = $Self->{LinkTicketData}->{CustomerUserID};
3606    }
3607
3608    # create a local copy of the GetParam
3609    my %GetServicesParam = %{ $Param{GetParam} };
3610
3611    # use ticket information as a fall back if customer was already set, otherwise when the
3612    # activity dialog displays the service list will be initially empty, see bug#10059
3613    if ( IsHashRefWithData( $Param{Ticket} ) ) {
3614        $GetServicesParam{CustomerUserID} ||= $Param{Ticket}->{CustomerUserID} ||= '';
3615    }
3616
3617    my $Services = $Self->_GetServices(
3618        %GetServicesParam,
3619    );
3620
3621    my %Data = (
3622        Label            => $LayoutObject->{LanguageObject}->Translate("Service"),
3623        FieldID          => 'ServiceID',
3624        FormID           => $Param{FormID},
3625        MandatoryClass   => '',
3626        ValidateRequired => '',
3627    );
3628
3629    # If field is required put in the necessary variables for
3630    # ValidateRequired class input field, Mandatory class for the label
3631    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
3632        $Data{ValidateRequired} = 'Validate_Required';
3633        $Data{MandatoryClass}   = 'Mandatory';
3634    }
3635
3636    my $SelectedValue;
3637
3638    # get service object
3639    my $ServiceObject = $Kernel::OM->Get('Kernel::System::Service');
3640
3641    my $ServiceIDParam = $Param{GetParam}{ServiceID};
3642    if ($ServiceIDParam) {
3643        $SelectedValue = $ServiceObject->ServiceLookup(
3644            ServiceID => $ServiceIDParam,
3645        );
3646    }
3647
3648    if ( $Param{FieldName} eq 'Service' ) {
3649
3650        if ( !$SelectedValue ) {
3651
3652            # Fetch DefaultValue from Config
3653            if (
3654                defined $Param{ActivityDialogField}->{DefaultValue}
3655                && $Param{ActivityDialogField}->{DefaultValue} ne ''
3656                )
3657            {
3658                $SelectedValue = $ServiceObject->ServiceLookup(
3659                    Name => $Param{ActivityDialogField}->{DefaultValue},
3660                );
3661            }
3662            if ($SelectedValue) {
3663                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
3664            }
3665        }
3666    }
3667    else {
3668        if ( !$SelectedValue ) {
3669            if (
3670                defined $Param{ActivityDialogField}->{DefaultValue}
3671                && $Param{ActivityDialogField}->{DefaultValue} ne ''
3672                )
3673            {
3674                $SelectedValue = $ServiceObject->ServiceLookup(
3675                    Service => $Param{ActivityDialogField}->{DefaultValue},
3676                );
3677            }
3678        }
3679    }
3680
3681    # Get TicketValue
3682    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
3683        $SelectedValue = $Param{Ticket}->{Service};
3684    }
3685
3686    # set server errors
3687    my $ServerError = '';
3688    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'ServiceID'} ) {
3689        $ServerError = 'ServerError';
3690    }
3691
3692    # get list type
3693    my $TreeView = 0;
3694    if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::ListType') eq 'tree' ) {
3695        $TreeView = 1;
3696    }
3697
3698    if ( $Self->{LinkTicketData} ) {
3699        $SelectedValue = $Self->{LinkTicketData}->{Service};
3700    }
3701
3702    # build Service string
3703    $Data{Content} = $LayoutObject->BuildSelection(
3704        Data          => $Services,
3705        Name          => 'ServiceID',
3706        Class         => "Modernize $ServerError",
3707        SelectedValue => $SelectedValue,
3708        PossibleNone  => 1,
3709        TreeView      => $TreeView,
3710        Sort          => 'TreeView',
3711        Translation   => 0,
3712        Max           => 200,
3713    );
3714
3715    # send data to JS
3716    $LayoutObject->AddJSData(
3717        Key   => 'ServiceFieldsToUpdate',
3718        Value => $Param{AJAXUpdatableFields}
3719    );
3720
3721    $LayoutObject->Block(
3722        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Service',
3723        Data => \%Data,
3724    );
3725
3726    # set mandatory label marker
3727    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
3728        $LayoutObject->Block(
3729            Name => 'LabelSpan',
3730            Data => {},
3731        );
3732    }
3733
3734    if ( $Param{DescriptionShort} ) {
3735        $LayoutObject->Block(
3736            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Service:DescriptionShort',
3737            Data => {
3738                DescriptionShort => $Param{DescriptionShort},
3739            },
3740        );
3741    }
3742
3743    if ( $Param{DescriptionLong} ) {
3744        $LayoutObject->Block(
3745            Name => 'rw:Service:DescriptionLong',
3746            Data => {
3747                DescriptionLong => $Param{DescriptionLong},
3748            },
3749        );
3750    }
3751
3752    return {
3753        Success => 1,
3754        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Service' ),
3755    };
3756
3757}
3758
3759sub _RenderLock {
3760
3761    # for lock states there's no ACL checking yet implemented so no checking...
3762
3763    my ( $Self, %Param ) = @_;
3764
3765    # get layout object
3766    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
3767
3768    for my $Needed (qw(FormID)) {
3769        if ( !$Param{$Needed} ) {
3770            return {
3771                Success => 0,
3772                Message => $LayoutObject->{LanguageObject}
3773                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderLock' ),
3774            };
3775        }
3776    }
3777    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
3778        return {
3779            Success => 0,
3780            Message => $LayoutObject->{LanguageObject}
3781                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderLock' ),
3782        };
3783    }
3784
3785    my $Locks = $Self->_GetLocks(
3786        %{ $Param{GetParam} },
3787    );
3788
3789    my %Data = (
3790        Label            => $LayoutObject->{LanguageObject}->Translate("Lock state"),
3791        FieldID          => 'LockID',
3792        FormID           => $Param{FormID},
3793        MandatoryClass   => '',
3794        ValidateRequired => '',
3795    );
3796
3797    # If field is required put in the necessary variables for
3798    # ValidateRequired class input field, Mandatory class for the label
3799    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
3800        $Data{ValidateRequired} = 'Validate_Required';
3801        $Data{MandatoryClass}   = 'Mandatory';
3802    }
3803
3804    my $SelectedValue;
3805
3806    # get lock object
3807    my $LockObject = $Kernel::OM->Get('Kernel::System::Lock');
3808
3809    my $LockIDParam = $Param{GetParam}{LockID};
3810    $SelectedValue = $LockObject->LockLookup( LockID => $LockIDParam )
3811        if ($LockIDParam);
3812
3813    if ( $Param{FieldName} eq 'Lock' ) {
3814
3815        if ( !$SelectedValue ) {
3816
3817            # Fetch DefaultValue from Config
3818            $SelectedValue = $LockObject->LockLookup(
3819                Lock => $Param{ActivityDialogField}->{DefaultValue} || '',
3820            );
3821            if ($SelectedValue) {
3822                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
3823            }
3824        }
3825    }
3826    else {
3827        $SelectedValue = $LockObject->LockLookup(
3828            LockID => $Param{ActivityDialogField}->{DefaultValue} || ''
3829            )
3830            if !$SelectedValue;
3831    }
3832
3833    # Get TicketValue
3834    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
3835        $SelectedValue = $Param{Ticket}->{Lock};
3836    }
3837
3838    # set server errors
3839    my $ServerError = '';
3840    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'LockID'} ) {
3841        $ServerError = 'ServerError';
3842    }
3843
3844    if ( $Self->{LinkTicketData} ) {
3845        $SelectedValue = $Self->{LinkTicketData}->{Lock};
3846    }
3847
3848    # build lock string
3849    $Data{Content} = $LayoutObject->BuildSelection(
3850        Data          => $Locks,
3851        Name          => 'LockID',
3852        Translation   => 1,
3853        SelectedValue => $SelectedValue,
3854        Class         => "Modernize $ServerError",
3855    );
3856
3857    # send data to JS
3858    $LayoutObject->AddJSData(
3859        Key   => 'LockFieldsToUpdate',
3860        Value => $Param{AJAXUpdatableFields}
3861    );
3862
3863    $LayoutObject->Block(
3864        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Lock',
3865        Data => \%Data,
3866    );
3867
3868    # set mandatory label marker
3869    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
3870        $LayoutObject->Block(
3871            Name => 'LabelSpan',
3872            Data => {},
3873        );
3874    }
3875
3876    if ( $Param{DescriptionShort} ) {
3877        $LayoutObject->Block(
3878            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Lock:DescriptionShort',
3879            Data => {
3880                DescriptionShort => $Param{DescriptionShort},
3881            },
3882        );
3883    }
3884
3885    if ( $Param{DescriptionLong} ) {
3886        $LayoutObject->Block(
3887            Name => 'rw:Lock:DescriptionLong',
3888            Data => {
3889                DescriptionLong => $Param{DescriptionLong},
3890            },
3891        );
3892    }
3893
3894    return {
3895        Success => 1,
3896        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Lock' ),
3897    };
3898}
3899
3900sub _RenderPriority {
3901    my ( $Self, %Param ) = @_;
3902
3903    # get layout object
3904    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
3905
3906    for my $Needed (qw(FormID)) {
3907        if ( !$Param{$Needed} ) {
3908            return {
3909                Success => 0,
3910                Message => $LayoutObject->{LanguageObject}
3911                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderPriority' ),
3912            };
3913        }
3914    }
3915    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
3916        return {
3917            Success => 0,
3918            Message => $LayoutObject->{LanguageObject}
3919                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderPriority' ),
3920        };
3921    }
3922
3923    my $Priorities = $Self->_GetPriorities(
3924        %{ $Param{GetParam} },
3925    );
3926
3927    my %Data = (
3928        Label            => $LayoutObject->{LanguageObject}->Translate("Priority"),
3929        FieldID          => 'PriorityID',
3930        FormID           => $Param{FormID},
3931        MandatoryClass   => '',
3932        ValidateRequired => '',
3933    );
3934
3935    # If field is required put in the necessary variables for
3936    # ValidateRequired class input field, Mandatory class for the label
3937    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
3938        $Data{ValidateRequired} = 'Validate_Required';
3939        $Data{MandatoryClass}   = 'Mandatory';
3940    }
3941
3942    my $SelectedValue;
3943
3944    # get priority object
3945    my $PriorityObject = $Kernel::OM->Get('Kernel::System::Priority');
3946
3947    my $PriorityIDParam = $Param{GetParam}{PriorityID};
3948    if ($PriorityIDParam) {
3949        $SelectedValue = $PriorityObject->PriorityLookup(
3950            PriorityID => $PriorityIDParam,
3951        );
3952    }
3953
3954    if ( $Param{FieldName} eq 'Priority' ) {
3955
3956        if ( !$SelectedValue ) {
3957
3958            # Fetch DefaultValue from Config
3959            $SelectedValue = $PriorityObject->PriorityLookup(
3960                Priority => $Param{ActivityDialogField}->{DefaultValue} || '',
3961            );
3962            if ($SelectedValue) {
3963                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
3964            }
3965        }
3966    }
3967    else {
3968        if ( !$SelectedValue ) {
3969            $SelectedValue = $PriorityObject->PriorityLookup(
3970                PriorityID => $Param{ActivityDialogField}->{DefaultValue} || '',
3971            );
3972        }
3973    }
3974
3975    # Get TicketValue
3976    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
3977        $SelectedValue = $Param{Ticket}->{Priority};
3978    }
3979
3980    # set server errors
3981    my $ServerError = '';
3982    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'PriorityID'} ) {
3983        $ServerError = 'ServerError';
3984    }
3985
3986    if ( $Self->{LinkTicketData} ) {
3987        $SelectedValue = $Self->{LinkTicketData}->{Priority};
3988    }
3989
3990    # build next Priorities string
3991    $Data{Content} = $LayoutObject->BuildSelection(
3992        Data          => $Priorities,
3993        Name          => 'PriorityID',
3994        Translation   => 1,
3995        SelectedValue => $SelectedValue,
3996        Class         => "Modernize $ServerError",
3997    );
3998
3999    # send data to JS
4000    $LayoutObject->AddJSData(
4001        Key   => 'PriorityFieldsToUpdate',
4002        Value => $Param{AJAXUpdatableFields}
4003    );
4004
4005    $LayoutObject->Block(
4006        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Priority',
4007        Data => \%Data,
4008    );
4009
4010    # set mandatory label marker
4011    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
4012        $LayoutObject->Block(
4013            Name => 'LabelSpan',
4014            Data => {},
4015        );
4016    }
4017
4018    if ( $Param{DescriptionShort} ) {
4019        $LayoutObject->Block(
4020            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Priority:DescriptionShort',
4021            Data => {
4022                DescriptionShort => $Param{DescriptionShort},
4023            },
4024        );
4025    }
4026
4027    if ( $Param{DescriptionLong} ) {
4028        $LayoutObject->Block(
4029            Name => 'rw:Priority:DescriptionLong',
4030            Data => {
4031                DescriptionLong => $Param{DescriptionLong},
4032            },
4033        );
4034    }
4035
4036    return {
4037        Success => 1,
4038        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Priority' ),
4039    };
4040}
4041
4042sub _RenderQueue {
4043    my ( $Self, %Param ) = @_;
4044
4045    # get layout object
4046    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
4047
4048    for my $Needed (qw(FormID)) {
4049        if ( !$Param{$Needed} ) {
4050            return {
4051                Success => 0,
4052                Message => $LayoutObject->{LanguageObject}
4053                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderQueue' ),
4054            };
4055        }
4056    }
4057    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
4058        return {
4059            Success => 0,
4060            Message => $LayoutObject->{LanguageObject}
4061                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderQueue' ),
4062        };
4063    }
4064
4065    my $Queues = $Self->_GetQueues(
4066        %{ $Param{GetParam} },
4067    );
4068
4069    my %Data = (
4070        Label            => $LayoutObject->{LanguageObject}->Translate("To queue"),
4071        FieldID          => 'QueueID',
4072        FormID           => $Param{FormID},
4073        MandatoryClass   => '',
4074        ValidateRequired => '',
4075    );
4076
4077    # If field is required put in the necessary variables for
4078    # ValidateRequired class input field, Mandatory class for the label
4079    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
4080        $Data{ValidateRequired} = 'Validate_Required';
4081        $Data{MandatoryClass}   = 'Mandatory';
4082    }
4083    my $SelectedValue;
4084
4085    # get queue object
4086    my $QueueObject = $Kernel::OM->Get('Kernel::System::Queue');
4087
4088    # if we got QueueID as Param from the GUI
4089    my $QueueIDParam = $Param{GetParam}{QueueID};
4090    if ($QueueIDParam) {
4091        $SelectedValue = $QueueObject->QueueLookup(
4092            QueueID => $QueueIDParam,
4093        );
4094    }
4095
4096    if ( $Param{FieldName} eq 'Queue' ) {
4097
4098        if ( !$SelectedValue ) {
4099
4100            # Fetch DefaultValue from Config
4101            $SelectedValue = $QueueObject->QueueLookup(
4102                Queue => $Param{ActivityDialogField}->{DefaultValue} || '',
4103            );
4104            if ($SelectedValue) {
4105                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
4106            }
4107        }
4108    }
4109    else {
4110        if ( !$SelectedValue ) {
4111            $SelectedValue = $QueueObject->QueueLookup(
4112                QueueID => $Param{ActivityDialogField}->{DefaultValue} || '',
4113            );
4114        }
4115    }
4116
4117    # Get TicketValue
4118    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
4119        $SelectedValue = $Param{Ticket}->{Queue};
4120    }
4121
4122    # set server errors
4123    my $ServerError = '';
4124    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'QueueID'} ) {
4125        $ServerError = 'ServerError';
4126    }
4127
4128    # get list type
4129    my $TreeView = 0;
4130    if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::ListType') eq 'tree' ) {
4131        $TreeView = 1;
4132    }
4133
4134    if ( $Self->{LinkTicketData} ) {
4135        $SelectedValue = $Self->{LinkTicketData}->{Queue};
4136    }
4137
4138    # build next queues string
4139    $Data{Content} = $LayoutObject->BuildSelection(
4140        Data          => $Queues,
4141        Name          => 'QueueID',
4142        Translation   => 0,
4143        SelectedValue => $SelectedValue,
4144        Class         => "Modernize $ServerError",
4145        TreeView      => $TreeView,
4146        Sort          => 'TreeView',
4147        PossibleNone  => 1,
4148    );
4149
4150    # send data to JS
4151    $LayoutObject->AddJSData(
4152        Key   => 'QueueFieldsToUpdate',
4153        Value => $Param{AJAXUpdatableFields}
4154    );
4155
4156    $LayoutObject->Block(
4157        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Queue',
4158        Data => \%Data,
4159    );
4160
4161    # set mandatory label marker
4162    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
4163        $LayoutObject->Block(
4164            Name => 'LabelSpan',
4165            Data => {},
4166        );
4167    }
4168
4169    if ( $Param{DescriptionShort} ) {
4170        $LayoutObject->Block(
4171            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Queue:DescriptionShort',
4172            Data => {
4173                DescriptionShort => $Param{DescriptionShort},
4174            },
4175        );
4176    }
4177
4178    if ( $Param{DescriptionLong} ) {
4179        $LayoutObject->Block(
4180            Name => 'rw:Queue:DescriptionLong',
4181            Data => {
4182                DescriptionLong => $Param{DescriptionLong},
4183            },
4184        );
4185    }
4186
4187    return {
4188        Success => 1,
4189        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Queue' ),
4190    };
4191}
4192
4193sub _RenderState {
4194    my ( $Self, %Param ) = @_;
4195
4196    # get layout object
4197    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
4198
4199    for my $Needed (qw(FormID)) {
4200        if ( !$Param{$Needed} ) {
4201            return {
4202                Success => 0,
4203                Message => $LayoutObject->{LanguageObject}
4204                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderState' ),
4205            };
4206        }
4207    }
4208    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
4209        return {
4210            Success => 0,
4211            Message => $LayoutObject->{LanguageObject}
4212                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderState' ),
4213        };
4214    }
4215
4216    my $States = $Self->_GetStates( %{ $Param{GetParam} } );
4217
4218    my %Data = (
4219        Label            => $LayoutObject->{LanguageObject}->Translate("Next ticket state"),
4220        FieldID          => 'StateID',
4221        FormID           => $Param{FormID},
4222        MandatoryClass   => '',
4223        ValidateRequired => '',
4224    );
4225
4226    # If field is required put in the necessary variables for
4227    # ValidateRequired class input field, Mandatory class for the label
4228    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
4229        $Data{ValidateRequired} = 'Validate_Required';
4230        $Data{MandatoryClass}   = 'Mandatory';
4231    }
4232    my $SelectedValue;
4233
4234    # get state object
4235    my $StateObject = $Kernel::OM->Get('Kernel::System::State');
4236
4237    my $StateIDParam = $Param{GetParam}{StateID};
4238    if ($StateIDParam) {
4239        $SelectedValue = $StateObject->StateLookup( StateID => $StateIDParam );
4240    }
4241
4242    if ( $Param{FieldName} eq 'State' ) {
4243
4244        if ( !$SelectedValue ) {
4245
4246            # Fetch DefaultValue from Config
4247            $SelectedValue = $StateObject->StateLookup(
4248                State => $Param{ActivityDialogField}->{DefaultValue} || '',
4249            );
4250            if ($SelectedValue) {
4251                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
4252            }
4253        }
4254    }
4255    else {
4256        if ( !$SelectedValue ) {
4257            $SelectedValue = $StateObject->StateLookup(
4258                StateID => $Param{ActivityDialogField}->{DefaultValue} || '',
4259            );
4260        }
4261    }
4262
4263    # Get TicketValue
4264    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
4265        $SelectedValue = $Param{Ticket}->{State};
4266    }
4267
4268    # set server errors
4269    my $ServerError = '';
4270    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'StateID'} ) {
4271        $ServerError = 'ServerError';
4272    }
4273
4274    # build next states string
4275    $Data{Content} = $LayoutObject->BuildSelection(
4276        Data          => $States,
4277        Name          => 'StateID',
4278        Translation   => 1,
4279        SelectedValue => $SelectedValue,
4280        Class         => "Modernize $ServerError",
4281    );
4282
4283    # send data to JS
4284    $LayoutObject->AddJSData(
4285        Key   => 'StateFieldsToUpdate',
4286        Value => $Param{AJAXUpdatableFields}
4287    );
4288
4289    $LayoutObject->Block(
4290        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:State',
4291        Data => \%Data,
4292    );
4293
4294    # set mandatory label marker
4295    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
4296        $LayoutObject->Block(
4297            Name => 'LabelSpan',
4298            Data => {},
4299        );
4300    }
4301
4302    if ( $Param{DescriptionShort} ) {
4303        $LayoutObject->Block(
4304            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:State:DescriptionShort',
4305            Data => {
4306                DescriptionShort => $Param{DescriptionShort},
4307            },
4308        );
4309    }
4310
4311    if ( $Param{DescriptionLong} ) {
4312        $LayoutObject->Block(
4313            Name => 'rw:State:DescriptionLong',
4314            Data => {
4315                DescriptionLong => $Param{DescriptionLong},
4316            },
4317        );
4318    }
4319
4320    return {
4321        Success => 1,
4322        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/State' ),
4323    };
4324}
4325
4326sub _RenderType {
4327    my ( $Self, %Param ) = @_;
4328
4329    # get layout object
4330    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
4331
4332    for my $Needed (qw(FormID)) {
4333        if ( !$Param{$Needed} ) {
4334            return {
4335                Success => 0,
4336                Message => $LayoutObject->{LanguageObject}
4337                    ->Translate( 'Parameter %s is missing in %s.', $Needed, '_RenderType' ),
4338            };
4339        }
4340    }
4341    if ( !IsHashRefWithData( $Param{ActivityDialogField} ) ) {
4342        return {
4343            Success => 0,
4344            Message => $LayoutObject->{LanguageObject}
4345                ->Translate( 'Parameter %s is missing in %s.', 'ActivityDialogField', '_RenderType' ),
4346        };
4347    }
4348
4349    my $Types = $Self->_GetTypes(
4350        %{ $Param{GetParam} },
4351    );
4352
4353    my %Data = (
4354        Label            => $LayoutObject->{LanguageObject}->Translate("Type"),
4355        FieldID          => 'TypeID',
4356        FormID           => $Param{FormID},
4357        MandatoryClass   => '',
4358        ValidateRequired => '',
4359    );
4360
4361    # If field is required put in the necessary variables for
4362    # ValidateRequired class input field, Mandatory class for the label
4363    if ( $Param{ActivityDialogField}->{Display} && $Param{ActivityDialogField}->{Display} == 2 ) {
4364        $Data{ValidateRequired} = 'Validate_Required';
4365        $Data{MandatoryClass}   = 'Mandatory';
4366    }
4367
4368    my $SelectedValue;
4369
4370    # get type object
4371    my $TypeObject = $Kernel::OM->Get('Kernel::System::Type');
4372
4373    my $TypeIDParam = $Param{GetParam}{TypeID};
4374    if ($TypeIDParam) {
4375        $SelectedValue = $TypeObject->TypeLookup(
4376            TypeID => $TypeIDParam,
4377        );
4378    }
4379
4380    if ( $Param{FieldName} eq 'Type' ) {
4381
4382        if ( !$SelectedValue ) {
4383
4384            # Fetch DefaultValue from Config
4385            if (
4386                defined $Param{ActivityDialogField}->{DefaultValue}
4387                && $Param{ActivityDialogField}->{DefaultValue} ne ''
4388                )
4389            {
4390                $SelectedValue = $TypeObject->TypeLookup(
4391                    Type => $Param{ActivityDialogField}->{DefaultValue},
4392                );
4393            }
4394            if ($SelectedValue) {
4395                $SelectedValue = $Param{ActivityDialogField}->{DefaultValue};
4396            }
4397        }
4398    }
4399    else {
4400        if ( !$SelectedValue ) {
4401            if (
4402                defined $Param{ActivityDialogField}->{DefaultValue}
4403                && $Param{ActivityDialogField}->{DefaultValue} ne ''
4404                )
4405            {
4406                $SelectedValue = $TypeObject->TypeLookup(
4407                    Type => $Param{ActivityDialogField}->{DefaultValue},
4408                );
4409            }
4410        }
4411    }
4412
4413    # Get TicketValue
4414    if ( IsHashRefWithData( $Param{Ticket} ) && !$SelectedValue ) {
4415        $SelectedValue = $Param{Ticket}->{Type};
4416    }
4417
4418    # set server errors
4419    my $ServerError = '';
4420    if ( IsHashRefWithData( $Param{Error} ) && $Param{Error}->{'TypeID'} ) {
4421        $ServerError = 'ServerError';
4422    }
4423
4424    if ( $Self->{LinkTicketData} ) {
4425        $SelectedValue = $Self->{LinkTicketData}->{Type};
4426    }
4427
4428    # build Service string
4429    $Data{Content} = $LayoutObject->BuildSelection(
4430        Data          => $Types,
4431        Name          => 'TypeID',
4432        Class         => "Modernize $ServerError",
4433        SelectedValue => $SelectedValue,
4434        PossibleNone  => 1,
4435        Sort          => 'AlphanumericValue',
4436        Translation   => 0,
4437        Max           => 200,
4438    );
4439
4440    # send data to JS
4441    $LayoutObject->AddJSData(
4442        Key   => 'TypeFieldsToUpdate',
4443        Value => $Param{AJAXUpdatableFields}
4444    );
4445
4446    $LayoutObject->Block(
4447        Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Type',
4448        Data => \%Data,
4449    );
4450
4451    # set mandatory label marker
4452    if ( $Data{MandatoryClass} && $Data{MandatoryClass} ne '' ) {
4453        $LayoutObject->Block(
4454            Name => 'LabelSpan',
4455            Data => {},
4456        );
4457    }
4458
4459    if ( $Param{DescriptionShort} ) {
4460        $LayoutObject->Block(
4461            Name => $Param{ActivityDialogField}->{LayoutBlock} || 'rw:Type:DescriptionShort',
4462            Data => {
4463                DescriptionShort => $Param{DescriptionShort},
4464            },
4465        );
4466    }
4467
4468    if ( $Param{DescriptionLong} ) {
4469        $LayoutObject->Block(
4470            Name => 'rw:Type:DescriptionLong',
4471            Data => {
4472                DescriptionLong => $Param{DescriptionLong},
4473            },
4474        );
4475    }
4476
4477    return {
4478        Success => 1,
4479        HTML    => $LayoutObject->Output( TemplateFile => 'ProcessManagement/Type' ),
4480    };
4481}
4482
4483sub _StoreActivityDialog {
4484    my ( $Self, %Param ) = @_;
4485
4486    my $TicketID = $Param{GetParam}->{TicketID};
4487    my $ProcessStartpoint;
4488    my %Ticket;
4489    my $ProcessEntityID;
4490    my $ActivityEntityID;
4491    my %Error;
4492    my %ErrorMessages;
4493
4494    my %TicketParam;
4495
4496    # get layout object
4497    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
4498
4499    my $ActivityDialogEntityID = $Param{GetParam}->{ActivityDialogEntityID};
4500    if ( !$ActivityDialogEntityID ) {
4501        $LayoutObject->FatalError(
4502            Message => Translatable('ActivityDialogEntityID missing!'),
4503        );
4504    }
4505
4506    # get activity dialog object
4507    my $ActivityDialogObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::ActivityDialog');
4508    my $ActivityDialog       = $ActivityDialogObject->ActivityDialogGet(
4509        ActivityDialogEntityID => $ActivityDialogEntityID,
4510        Interface              => 'AgentInterface',
4511    );
4512
4513    if ( !IsHashRefWithData($ActivityDialog) ) {
4514        $LayoutObject->FatalError(
4515            Message => $LayoutObject->{LanguageObject}->Translate(
4516                'Couldn\'t get Config for ActivityDialogEntityID "%s"!',
4517                $ActivityDialogEntityID,
4518            ),
4519        );
4520    }
4521
4522    # get param object
4523    my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
4524
4525    # get upload cache object
4526    my $UploadCacheObject = $Kernel::OM->Get('Kernel::System::Web::UploadCache');
4527
4528    my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
4529        Valid      => 1,
4530        ObjectType => 'Ticket',
4531    );
4532
4533    # get dynamic field backend object
4534    my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');
4535
4536    # check each Field of an Activity Dialog and fill the error hash if something goes horribly wrong
4537    my %CheckedFields;
4538    DIALOGFIELD:
4539    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
4540        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
4541            my $DynamicFieldName = $1;
4542
4543            # Get the Config of the current DynamicField (the first element of the grep result array)
4544            my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{$DynamicField} )[0];
4545
4546            if ( !IsHashRefWithData($DynamicFieldConfig) ) {
4547
4548                my $Message
4549                    = "DynamicFieldConfig missing for field: $Param{FieldName}, or is not a Ticket Dynamic Field!";
4550
4551                # log error but does not stop the execution as it could be an old Article
4552                # DynamicField, see bug#11666
4553                $Kernel::OM->Get('Kernel::System::Log')->Log(
4554                    Priority => 'error',
4555                    Message  => $Message,
4556                );
4557
4558                next DIALOGFIELD;
4559            }
4560
4561            # Will be extended later on for ACL Checking:
4562            my $PossibleValuesFilter;
4563
4564            # if we have an invisible field, use config's default value
4565            if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 0 ) {
4566                if (
4567                    defined $ActivityDialog->{Fields}->{$CurrentField}->{DefaultValue}
4568                    && length $ActivityDialog->{Fields}->{$CurrentField}->{DefaultValue}
4569                    )
4570                {
4571                    $TicketParam{$CurrentField} = $ActivityDialog->{Fields}->{$CurrentField}->{DefaultValue};
4572                }
4573                else {
4574                    $TicketParam{$CurrentField} = '';
4575                }
4576            }
4577
4578            # only validate visible fields
4579            else {
4580                # Check DynamicField Values
4581                my $ValidationResult = $DynamicFieldBackendObject->EditFieldValueValidate(
4582                    DynamicFieldConfig   => $DynamicFieldConfig,
4583                    PossibleValuesFilter => $PossibleValuesFilter,
4584                    ParamObject          => $ParamObject,
4585                    Mandatory            => $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 2,
4586                );
4587
4588                if ( !IsHashRefWithData($ValidationResult) ) {
4589                    $LayoutObject->FatalError(
4590                        Message => $LayoutObject->{LanguageObject}->Translate(
4591                            'Could not perform validation on field %s!',
4592                            $DynamicFieldConfig->{Label},
4593                        ),
4594                    );
4595                }
4596
4597                if ( $ValidationResult->{ServerError} ) {
4598                    $Error{ $DynamicFieldConfig->{Name} }         = 1;
4599                    $ErrorMessages{ $DynamicFieldConfig->{Name} } = $ValidationResult->{ErrorMessage};
4600                }
4601
4602                $TicketParam{$CurrentField} =
4603                    $DynamicFieldBackendObject->EditFieldValueGet(
4604                    DynamicFieldConfig => $DynamicFieldConfig,
4605                    ParamObject        => $ParamObject,
4606                    LayoutObject       => $LayoutObject,
4607                    );
4608            }
4609
4610            # In case of DynamicFields there is no NameToID translation
4611            # so just take the DynamicField name
4612            $CheckedFields{$CurrentField} = 1;
4613        }
4614        elsif (
4615            $Self->{NameToID}->{$CurrentField} eq 'CustomerID'
4616            || $Self->{NameToID}->{$CurrentField} eq 'CustomerUserID'
4617            )
4618        {
4619
4620            next DIALOGFIELD if $CheckedFields{ $Self->{NameToID}->{'CustomerID'} };
4621
4622            # is not possible to a have an invisible field for this particular value
4623            # on agent interface
4624            if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 0 ) {
4625                $LayoutObject->FatalError(
4626                    Message => Translatable('Couldn\'t use CustomerID as an invisible field.'),
4627                    Comment => Translatable('Please contact the administrator.'),
4628                );
4629            }
4630
4631            # CustomerID should not be mandatory as in other screens
4632            $TicketParam{CustomerID} = $Param{GetParam}->{CustomerID} || '';
4633
4634            # Unfortunately TicketCreate needs 'CustomerUser' as param instead of 'CustomerUserID'
4635            my $CustomerUserID = $ParamObject->GetParam( Param => 'SelectedCustomerUser' );
4636
4637            # fall-back, if customer auto-complete does not shown any results, then try to use
4638            # the content of the original field as customer user id
4639            if ( !$CustomerUserID ) {
4640
4641                $CustomerUserID = $ParamObject->GetParam( Param => 'CustomerUserID' );
4642
4643                # check email address
4644                for my $Email ( Mail::Address->parse($CustomerUserID) ) {
4645                    if (
4646                        !$Kernel::OM->Get('Kernel::System::CheckItem')->CheckEmail( Address => $Email->address() )
4647                        )
4648                    {
4649                        $Error{'CustomerUserID'} = 1;
4650                    }
4651                }
4652            }
4653
4654            if ( !$CustomerUserID ) {
4655                $Error{'CustomerUserID'} = 1;
4656            }
4657            else {
4658                $TicketParam{CustomerUser} = $CustomerUserID;
4659            }
4660            $CheckedFields{ $Self->{NameToID}->{'CustomerID'} }     = 1;
4661            $CheckedFields{ $Self->{NameToID}->{'CustomerUserID'} } = 1;
4662
4663        }
4664        elsif ( $CurrentField eq 'PendingTime' ) {
4665            my $Prefix = 'PendingTime';
4666
4667            # Make sure we have Values otherwise take an empty string
4668            if (
4669                IsHashRefWithData( $Param{GetParam}->{PendingTime} )
4670                && defined $Param{GetParam}->{PendingTime}->{Year}
4671                && defined $Param{GetParam}->{PendingTime}->{Month}
4672                && defined $Param{GetParam}->{PendingTime}->{Day}
4673                && defined $Param{GetParam}->{PendingTime}->{Hour}
4674                && defined $Param{GetParam}->{PendingTime}->{Minute}
4675                )
4676            {
4677                $TicketParam{$CurrentField} = $Param{GetParam}->{PendingTime};
4678            }
4679
4680            # if we have no Pending status we have no time to set
4681            else {
4682                $TicketParam{$CurrentField} = '';
4683            }
4684            $CheckedFields{'PendingTime'} = 1;
4685        }
4686
4687        else {
4688
4689            # skip if we've already checked ID or Name
4690            next DIALOGFIELD if $CheckedFields{ $Self->{NameToID}->{$CurrentField} };
4691
4692            my $Result = $Self->_CheckField(
4693                Field => $Self->{NameToID}->{$CurrentField},
4694                %{ $ActivityDialog->{Fields}{$CurrentField} },
4695            );
4696
4697            if ( !$Result ) {
4698
4699                # special case for Article (Subject & Body)
4700                if ( $CurrentField eq 'Article' ) {
4701                    for my $ArticlePart (qw(Subject Body)) {
4702                        if ( !$Param{GetParam}->{$ArticlePart} ) {
4703
4704                            # set error for each part (if any)
4705                            $Error{ 'Article' . $ArticlePart } = 1;
4706                        }
4707                    }
4708                }
4709
4710                # all other fields
4711                elsif ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 2 ) {
4712                    $Error{ $Self->{NameToID}->{$CurrentField} } = 1;
4713                }
4714            }
4715
4716            if (
4717                $CurrentField eq 'Article'
4718                && $ActivityDialog->{Fields}->{$CurrentField}->{Config}->{TimeUnits}
4719                && $ActivityDialog->{Fields}->{$CurrentField}->{Config}->{TimeUnits} == 2
4720                )
4721            {
4722                if ( !$Param{GetParam}->{TimeUnits} ) {
4723
4724                    # set error for the time-units (if any)
4725                    $Error{'TimeUnits'} = 1;
4726                }
4727            }
4728
4729            elsif ($Result) {
4730                $TicketParam{ $Self->{NameToID}->{$CurrentField} } = $Result;
4731            }
4732            $CheckedFields{ $Self->{NameToID}->{$CurrentField} } = 1;
4733        }
4734    }
4735
4736    # create process object
4737    $Kernel::OM->ObjectParamAdd(
4738        'Kernel::System::ProcessManagement::Process' => {
4739            ActivityObject         => $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity'),
4740            ActivityDialogObject   => $ActivityDialogObject,
4741            TransitionObject       => $Kernel::OM->Get('Kernel::System::ProcessManagement::Transition'),
4742            TransitionActionObject => $Kernel::OM->Get('Kernel::System::ProcessManagement::TransitionAction'),
4743        }
4744    );
4745    my $ProcessObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::Process');
4746
4747    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
4748
4749    my @Notify;
4750
4751    my $NewTicketID;
4752    my $NewOwnerID;
4753    if ( !$TicketID ) {
4754
4755        $ProcessEntityID = $Param{GetParam}->{ProcessEntityID};
4756        if ( !$ProcessEntityID )
4757        {
4758            return $LayoutObject->FatalError(
4759                Message => Translatable('Missing ProcessEntityID, check your ActivityDialogHeader.tt!'),
4760            );
4761        }
4762
4763        $ProcessStartpoint = $ProcessObject->ProcessStartpointGet(
4764            ProcessEntityID => $Param{ProcessEntityID},
4765        );
4766
4767        if (
4768            !$ProcessStartpoint
4769            || !IsHashRefWithData($ProcessStartpoint)
4770            || !$ProcessStartpoint->{Activity} || !$ProcessStartpoint->{ActivityDialog}
4771            )
4772        {
4773            $LayoutObject->FatalError(
4774                Message => $LayoutObject->{LanguageObject}->Translate(
4775                    'No StartActivityDialog or StartActivityDialog for Process "%s" configured!',
4776                    $Param{ProcessEntityID},
4777                ),
4778            );
4779        }
4780
4781        $ActivityEntityID = $ProcessStartpoint->{Activity};
4782
4783        NEEDEDLOOP:
4784        for my $Needed (qw(Queue State Lock Priority)) {
4785
4786            if ( !$TicketParam{ $Self->{NameToID}->{$Needed} } ) {
4787
4788                # if a required field has no value call _CheckField as filed is hidden
4789                # (No Display param = Display => 0) and no DefaultValue, to use global default as
4790                # fall-back. One reason for this to happen is that ActivityDialog DefaultValue tried
4791                # to set before, was not valid.
4792                my $Result = $Self->_CheckField(
4793                    Field => $Self->{NameToID}->{$Needed},
4794                );
4795
4796                if ( !$Result ) {
4797                    $Error{ $Self->{NameToID}->{$Needed} } = ' ServerError';
4798                }
4799                elsif ($Result) {
4800                    $TicketParam{ $Self->{NameToID}->{$Needed} } = $Result;
4801                }
4802            }
4803        }
4804
4805        # If we had no Errors, we can create the Ticket and Set ActivityEntityID as well as
4806        # ProcessEntityID
4807        if ( !IsHashRefWithData( \%Error ) ) {
4808
4809            $TicketParam{UserID} = $Self->{UserID};
4810
4811            if ( $TicketParam{OwnerID} ) {
4812                $NewOwnerID = $TicketParam{OwnerID};
4813            }
4814
4815            # Set OwnerID to 1 on TicketCreate. This will be updated later on, so events can be triggered.
4816            $TicketParam{OwnerID} = 1;
4817
4818            # if StartActivityDialog does not provide a ticket title set a default value
4819            if ( !$TicketParam{Title} ) {
4820
4821                # get the current server Time-stamp
4822                my $DateTimeObject   = $Kernel::OM->Create('Kernel::System::DateTime');
4823                my $CurrentTimeStamp = $DateTimeObject->ToString();
4824                my $OTRSTimeZone     = $DateTimeObject->OTRSTimeZoneGet();
4825                $TicketParam{Title} = "$Param{ProcessName} - $CurrentTimeStamp ($OTRSTimeZone)";
4826
4827                # use article subject from the web request if any
4828                if ( IsStringWithData( $Param{GetParam}->{Subject} ) ) {
4829                    $TicketParam{Title} = $Param{GetParam}->{Subject};
4830                }
4831            }
4832
4833            # create a new ticket
4834            $TicketID = $TicketObject->TicketCreate(%TicketParam);
4835
4836            if ( !$TicketID ) {
4837                $LayoutObject->FatalError(
4838                    Message => $LayoutObject->{LanguageObject}->Translate(
4839                        'Couldn\'t create ticket for Process with ProcessEntityID "%s"!',
4840                        $Param{ProcessEntityID},
4841                    ),
4842                );
4843            }
4844
4845            my $Success = $ProcessObject->ProcessTicketProcessSet(
4846                ProcessEntityID => $Param{ProcessEntityID},
4847                TicketID        => $TicketID,
4848                UserID          => $Self->{UserID},
4849            );
4850            if ( !$Success ) {
4851                $LayoutObject->FatalError(
4852                    Message => $LayoutObject->{LanguageObject}->Translate(
4853                        'Couldn\'t set ProcessEntityID "%s" on TicketID "%s"!',
4854                        $Param{ProcessEntityID},
4855                        $TicketID,
4856                    ),
4857                );
4858            }
4859
4860            $Success = undef;
4861
4862            $Success = $ProcessObject->ProcessTicketActivitySet(
4863                ProcessEntityID  => $Param{ProcessEntityID},
4864                ActivityEntityID => $ProcessStartpoint->{Activity},
4865                TicketID         => $TicketID,
4866                UserID           => $Self->{UserID},
4867            );
4868
4869            if ( !$Success ) {
4870                $LayoutObject->FatalError(
4871                    Message => $LayoutObject->{LanguageObject}->Translate(
4872                        'Couldn\'t set ActivityEntityID "%s" on TicketID "%s"!',
4873                        $Param{ProcessEntityID},
4874                        $TicketID,
4875                    ),
4876                    Comment => Translatable('Please contact the administrator.'),
4877                );
4878            }
4879
4880            %Ticket = $TicketObject->TicketGet(
4881                TicketID      => $TicketID,
4882                UserID        => $Self->{UserID},
4883                DynamicFields => 1,
4884            );
4885
4886            if ( !IsHashRefWithData( \%Ticket ) ) {
4887                $LayoutObject->FatalError(
4888                    Message => $LayoutObject->{LanguageObject}->Translate(
4889                        'Could not store ActivityDialog, invalid TicketID: %s!',
4890                        $TicketID,
4891                    ),
4892                    Comment => Translatable('Please contact the administrator.'),
4893                );
4894            }
4895            for my $DynamicFieldConfig (
4896
4897                # 2. remove "DynamicField_" from string
4898                map {
4899                    my $Field = $_;
4900                    $Field =~ s{^DynamicField_(.*)}{$1}xms;
4901
4902                    # 3. grep from the DynamicFieldConfigs the resulting DynamicFields without
4903                    # "DynamicField_"
4904                    grep { $_->{Name} eq $Field } @{$DynamicField}
4905                }
4906
4907                # 1. grep all DynamicFields
4908                grep {m{^DynamicField_(.*)}xms} @{ $ActivityDialog->{FieldOrder} }
4909                )
4910            {
4911
4912                # and now it's easy, just store the dynamic Field Values ;)
4913                $DynamicFieldBackendObject->ValueSet(
4914                    DynamicFieldConfig => $DynamicFieldConfig,
4915                    ObjectID           => $TicketID,
4916                    Value              => $TicketParam{ 'DynamicField_' . $DynamicFieldConfig->{Name} },
4917                    UserID             => $Self->{UserID},
4918                );
4919            }
4920
4921            # remember new created TicketID
4922            $NewTicketID = $TicketID;
4923        }
4924    }
4925
4926    elsif ( $TicketID && $Self->{IsProcessEnroll} ) {
4927
4928        # use Error instead of FatalError as we are in a Pop-up window
4929        # Get Ticket to check TicketID was valid
4930        %Ticket = $TicketObject->TicketGet(
4931            TicketID      => $TicketID,
4932            UserID        => $Self->{UserID},
4933            DynamicFields => 0,
4934        );
4935
4936        if ( !IsHashRefWithData( \%Ticket ) ) {
4937            $LayoutObject->Error(
4938                Message => $LayoutObject->{LanguageObject}->Translate( 'Invalid TicketID: %s!', $TicketID ),
4939            );
4940        }
4941
4942        my $Success = $ProcessObject->ProcessTicketProcessSet(
4943            ProcessEntityID => $Param{ProcessEntityID},
4944            TicketID        => $TicketID,
4945            UserID          => $Self->{UserID},
4946        );
4947        if ( !$Success ) {
4948            $LayoutObject->Error(
4949                Message => $LayoutObject->{LanguageObject}->Translate(
4950                    'Couldn\'t set ProcessEntityID "%s" on TicketID "%s"!',
4951                    $Param{ProcessEntityID},
4952                    $TicketID,
4953                ),
4954            );
4955        }
4956
4957        $Success = undef;
4958
4959        $ProcessStartpoint = $ProcessObject->ProcessStartpointGet(
4960            ProcessEntityID => $Param{ProcessEntityID},
4961        );
4962
4963        if (
4964            !$ProcessStartpoint
4965            || !IsHashRefWithData($ProcessStartpoint)
4966            || !$ProcessStartpoint->{Activity} || !$ProcessStartpoint->{ActivityDialog}
4967            )
4968        {
4969            $LayoutObject->Error(
4970                Message => $LayoutObject->{LanguageObject}->Translate(
4971                    'No StartActivityDialog or StartActivityDialog for Process "%s" configured!',
4972                    $Param{ProcessEntityID},
4973                ),
4974            );
4975        }
4976
4977        $Success = $ProcessObject->ProcessTicketActivitySet(
4978            ProcessEntityID  => $Param{ProcessEntityID},
4979            ActivityEntityID => $ProcessStartpoint->{Activity},
4980            TicketID         => $TicketID,
4981            UserID           => $Self->{UserID},
4982        );
4983
4984        if ( !$Success ) {
4985            $LayoutObject->Error(
4986                Message => $LayoutObject->{LanguageObject}->Translate(
4987                    'Couldn\'t set ActivityEntityID "%s" on TicketID "%s"!',
4988                    $Param{ProcessEntityID},
4989                    $TicketID,
4990                ),
4991                Comment => Translatable('Please contact the administrator.'),
4992            );
4993        }
4994
4995        # use ProcessEntityID from the web request
4996        $ProcessEntityID = $Param{ProcessEntityID};
4997
4998        # Check if we deal with a Ticket Update
4999        my $UpdateTicketID = $TicketID;
5000    }
5001
5002    # If we had a TicketID, get the Ticket
5003    else {
5004
5005        # Get Ticket to check TicketID was valid
5006        %Ticket = $TicketObject->TicketGet(
5007            TicketID      => $TicketID,
5008            UserID        => $Self->{UserID},
5009            DynamicFields => 1,
5010        );
5011
5012        if ( !IsHashRefWithData( \%Ticket ) ) {
5013            $LayoutObject->FatalError(
5014                Message => $LayoutObject->{LanguageObject}->Translate(
5015                    'Could not store ActivityDialog, invalid TicketID: %s!',
5016                    $TicketID,
5017                ),
5018            );
5019        }
5020
5021        # get config object
5022        my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
5023
5024        $ActivityEntityID = $Ticket{
5025            'DynamicField_'
5026                . $ConfigObject->Get('Process::DynamicFieldProcessManagementActivityID')
5027        };
5028        if ( !$ActivityEntityID )
5029        {
5030
5031            return $Self->_ShowDialogError(
5032                Message => $LayoutObject->{LanguageObject}->Translate(
5033                    'Missing ActivityEntityID in Ticket %s!',
5034                    $Ticket{TicketID},
5035                ),
5036                Comment => Translatable('Please contact the administrator.'),
5037            );
5038        }
5039
5040        # Make sure the activity dialog to save is still the correct activity
5041        my $Activity = $Kernel::OM->Get('Kernel::System::ProcessManagement::Activity')->ActivityGet(
5042            ActivityEntityID => $ActivityEntityID,
5043            Interface        => ['AgentInterface'],
5044        );
5045        my %ActivityDialogs = reverse %{ $Activity->{ActivityDialog} // {} };
5046        if ( !$ActivityDialogs{$ActivityDialogEntityID} ) {
5047
5048            my $TicketHook        = $ConfigObject->Get('Ticket::Hook');
5049            my $TicketHookDivider = $ConfigObject->Get('Ticket::HookDivider');
5050
5051            $Error{WrongActivity} = 1;
5052            push @Notify, {
5053                Priority => 'Error',
5054                Data     => $LayoutObject->{LanguageObject}->Translate(
5055                    'This step does not belong anymore to the current activity in process for ticket \'%s%s%s\'! Another user changed this ticket in the meantime. Please close this window and reload the ticket.',
5056                    $TicketHook,
5057                    $TicketHookDivider,
5058                    $Ticket{TicketNumber},
5059                ),
5060            };
5061        }
5062
5063        $ProcessEntityID = $Ticket{
5064            'DynamicField_'
5065                . $ConfigObject->Get('Process::DynamicFieldProcessManagementProcessID')
5066        };
5067
5068        if ( !$ProcessEntityID )
5069        {
5070            return $Self->_ShowDialogError(
5071                Message => $LayoutObject->{LanguageObject}->Translate(
5072                    'Missing ProcessEntityID in Ticket %s!',
5073                    $Ticket{TicketID},
5074                ),
5075                Comment => Translatable('Please contact the administrator.'),
5076            );
5077        }
5078    }
5079
5080    # if we got errors go back to displaying the ActivityDialog
5081    if ( IsHashRefWithData( \%Error ) ) {
5082        return $Self->_OutputActivityDialog(
5083            ProcessEntityID        => $ProcessEntityID,
5084            TicketID               => $TicketID || undef,
5085            ActivityDialogEntityID => $ActivityDialogEntityID,
5086            Error                  => \%Error,
5087            ErrorMessages          => \%ErrorMessages,
5088            GetParam               => $Param{GetParam},
5089            Notify                 => \@Notify,
5090        );
5091    }
5092
5093    # Check if we deal with a Ticket Update
5094    my $UpdateTicketID = $Param{GetParam}->{TicketID};
5095
5096    # We save only once, no matter if one or more configurations are set for the same param
5097    my %StoredFields;
5098
5099    # Save loop for storing Ticket Values that were not required on the initial TicketCreate
5100    DIALOGFIELD:
5101    for my $CurrentField ( @{ $ActivityDialog->{FieldOrder} } ) {
5102
5103        if ( !IsHashRefWithData( $ActivityDialog->{Fields}{$CurrentField} ) ) {
5104            $LayoutObject->FatalError(
5105                Message => $LayoutObject->{LanguageObject}->Translate(
5106                    'Can\'t get data for Field "%s" of ActivityDialog "%s"!',
5107                    $CurrentField,
5108                    $ActivityDialogEntityID,
5109                ),
5110            );
5111        }
5112
5113        if ( $CurrentField =~ m{^DynamicField_(.*)}xms ) {
5114            my $DynamicFieldName   = $1;
5115            my $DynamicFieldConfig = ( grep { $_->{Name} eq $DynamicFieldName } @{$DynamicField} )[0];
5116
5117            if ( !IsHashRefWithData($DynamicFieldConfig) ) {
5118
5119                my $Message
5120                    = "DynamicFieldConfig missing for field: $Param{FieldName}, or is not a Ticket Dynamic Field!";
5121
5122                # log error but does not stop the execution as it could be an old Article
5123                # DynamicField, see bug#11666
5124                $Kernel::OM->Get('Kernel::System::Log')->Log(
5125                    Priority => 'error',
5126                    Message  => $Message,
5127                );
5128
5129                next DIALOGFIELD;
5130            }
5131
5132            my $Success = $DynamicFieldBackendObject->ValueSet(
5133                DynamicFieldConfig => $DynamicFieldConfig,
5134                ObjectID           => $TicketID,
5135                Value              => $TicketParam{$CurrentField},
5136                UserID             => $Self->{UserID},
5137            );
5138            if ( !$Success ) {
5139                $LayoutObject->FatalError(
5140                    Message => $LayoutObject->{LanguageObject}->Translate(
5141                        'Could not set DynamicField value for %s of Ticket with ID "%s" in ActivityDialog "%s"!',
5142                        $CurrentField,
5143                        $TicketID,
5144                        $ActivityDialogEntityID,
5145                    ),
5146                );
5147            }
5148        }
5149        elsif ( $CurrentField eq 'PendingTime' ) {
5150
5151            # This Value is just set if Status was on a Pending state
5152            # so it has to be possible to store the ticket if this one's empty
5153            if ( IsHashRefWithData( $TicketParam{'PendingTime'} ) ) {
5154                my $Success = $TicketObject->TicketPendingTimeSet(
5155                    UserID   => $Self->{UserID},
5156                    TicketID => $TicketID,
5157                    %{ $TicketParam{'PendingTime'} },
5158                );
5159                if ( !$Success ) {
5160                    $LayoutObject->FatalError(
5161                        Message => $LayoutObject->{LanguageObject}->Translate(
5162                            'Could not set PendingTime for Ticket with ID "%s" in ActivityDialog "%s"!',
5163                            $TicketID,
5164                            $ActivityDialogEntityID,
5165                        ),
5166                    );
5167                }
5168            }
5169        }
5170
5171        elsif ( $CurrentField eq 'Article' && ( $UpdateTicketID || $NewTicketID ) ) {
5172
5173            my $TicketID = $UpdateTicketID || $NewTicketID;
5174
5175            if ( $Param{GetParam}->{Subject} && $Param{GetParam}->{Body} ) {
5176
5177                # add note
5178                my $ArticleID = '';
5179                my $MimeType  = 'text/plain';
5180
5181                # get pre loaded attachment
5182                my @Attachments = $UploadCacheObject->FormIDGetAllFilesData(
5183                    FormID => $Self->{FormID},
5184                );
5185
5186                # get submit attachment
5187                my %UploadStuff = $ParamObject->GetUploadAll(
5188                    Param => 'FileUpload',
5189                );
5190                if (%UploadStuff) {
5191                    push @Attachments, \%UploadStuff;
5192                }
5193
5194                if ( $LayoutObject->{BrowserRichText} ) {
5195                    $MimeType = 'text/html';
5196
5197                    # write attachments
5198                    my @NewAttachmentData;
5199                    ATTACHMENT:
5200                    for my $Attachment (@Attachments) {
5201
5202                        # skip, deleted not used inline images
5203                        my $ContentID = $Attachment->{ContentID};
5204                        if (
5205                            $ContentID
5206                            && ( $Attachment->{ContentType} =~ /image/i )
5207                            && ( $Attachment->{Disposition} eq 'inline' )
5208                            )
5209                        {
5210                            my $ContentIDHTMLQuote = $LayoutObject->Ascii2Html(
5211                                Text => $ContentID,
5212                            );
5213
5214                            # workaround for link encode of rich text editor, see bug#5053
5215                            my $ContentIDLinkEncode = $LayoutObject->LinkEncode($ContentID);
5216                            $Param{GetParam}->{Body} =~ s/(ContentID=)$ContentIDLinkEncode/$1$ContentID/g;
5217
5218                            # ignore attachment if not linked in body
5219                            if ( $Param{GetParam}->{Body} !~ /(\Q$ContentIDHTMLQuote\E|\Q$ContentID\E)/i )
5220                            {
5221                                next ATTACHMENT;
5222                            }
5223                        }
5224
5225                        # Remember inline images and normal attachments.
5226                        push @NewAttachmentData, \%{$Attachment};
5227                    }
5228
5229                    @Attachments = @NewAttachmentData;
5230
5231                    # verify html document
5232                    $Param{GetParam}->{Body} = $LayoutObject->RichTextDocumentComplete(
5233                        String => $Param{GetParam}->{Body},
5234                    );
5235                }
5236
5237                my $CommunicationChannel = $ActivityDialog->{Fields}->{Article}->{Config}->{CommunicationChannel}
5238                    // 'Internal';
5239
5240                my $ArticleBackendObject = $Kernel::OM->Get('Kernel::System::Ticket::Article')->BackendForChannel(
5241                    ChannelName => $CommunicationChannel,
5242                );
5243
5244                # Change history type and comment accordingly to the process article.
5245                my $HistoryType    = 'AddNote';
5246                my $HistoryComment = '%%Note';
5247                if ( $CommunicationChannel eq 'Phone' ) {
5248                    $HistoryType    = 'PhoneCallAgent';
5249                    $HistoryComment = '%%';
5250                }
5251
5252                my $From = "\"$Self->{UserFullname}\" <$Self->{UserEmail}>";
5253                $ArticleID = $ArticleBackendObject->ArticleCreate(
5254                    TicketID             => $TicketID,
5255                    SenderType           => 'agent',
5256                    IsVisibleForCustomer => $ActivityDialog->{Fields}->{Article}->{Config}->{IsVisibleForCustomer} // 0,
5257                    From                 => $From,
5258                    MimeType             => $MimeType,
5259                    Charset              => $LayoutObject->{UserCharset},
5260                    UserID               => $Self->{UserID},
5261                    HistoryType          => $HistoryType,
5262                    HistoryComment       => $HistoryComment,
5263                    Body                 => $Param{GetParam}{Body},
5264                    Subject              => $Param{GetParam}{Subject},
5265                    ForceNotificationToUserID => $ActivityDialog->{Fields}->{Article}->{Config}->{InformAgents}
5266                    ? $Param{GetParam}{InformUserID}
5267                    : [],
5268                );
5269                if ( !$ArticleID ) {
5270                    return $LayoutObject->ErrorScreen();
5271                }
5272
5273                # write attachments
5274                for my $Attachment (@Attachments) {
5275                    $ArticleBackendObject->ArticleWriteAttachment(
5276                        %{$Attachment},
5277                        ArticleID => $ArticleID,
5278                        UserID    => $Self->{UserID},
5279                    );
5280                }
5281
5282                # Remove pre submitted attachments.
5283                $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} );
5284
5285                # time accounting
5286                if ( $Param{GetParam}->{TimeUnits} ) {
5287                    $TicketObject->TicketAccountTime(
5288                        TicketID  => $TicketID,
5289                        ArticleID => $ArticleID,
5290                        TimeUnit  => $Param{GetParam}{TimeUnits},
5291                        UserID    => $Self->{UserID},
5292                    );
5293                }
5294            }
5295        }
5296
5297        # If we have to Update a ticket, update the transmitted values
5298        elsif ($UpdateTicketID) {
5299
5300            my $Success;
5301            if ( $Self->{NameToID}->{$CurrentField} eq 'Title' ) {
5302
5303                # if there is no title, nothing is needed to be done
5304                if (
5305                    !defined $TicketParam{'Title'}
5306                    || ( defined $TicketParam{'Title'} && $TicketParam{'Title'} eq '' )
5307                    )
5308                {
5309                    $Success = 1;
5310                }
5311
5312                # otherwise set the ticket title
5313                else {
5314                    $Success = $TicketObject->TicketTitleUpdate(
5315                        Title    => $TicketParam{'Title'},
5316                        TicketID => $TicketID,
5317                        UserID   => $Self->{UserID},
5318                    );
5319                }
5320            }
5321            elsif (
5322                (
5323                    $Self->{NameToID}->{$CurrentField} eq 'CustomerID'
5324                    || $Self->{NameToID}->{$CurrentField} eq 'CustomerUserID'
5325                )
5326                )
5327            {
5328                next DIALOGFIELD if $StoredFields{ $Self->{NameToID}->{$CurrentField} };
5329
5330                if ( $ActivityDialog->{Fields}->{$CurrentField}->{Display} == 1 ) {
5331                    $LayoutObject->FatalError(
5332                        Message => $LayoutObject->{LanguageObject}->Translate(
5333                            'Wrong ActivityDialog Field config: %s can\'t be Display => 1 / Show field (Please change its configuration to be Display => 0 / Do not show field or Display => 2 / Show field as mandatory)!',
5334                            $CurrentField,
5335                        ),
5336                    );
5337                }
5338
5339                # skip TicketCustomerSet() if there is no change in the customer
5340                if (
5341                    $Ticket{CustomerID} eq $TicketParam{CustomerID}
5342                    && $Ticket{CustomerUserID} eq $TicketParam{CustomerUser}
5343                    )
5344                {
5345
5346                    # In this case we don't want to call any additional stores
5347                    # on Customer, CustomerNo, CustomerID or CustomerUserID
5348                    # so make sure both fields are set to "Stored" ;)
5349                    $StoredFields{ $Self->{NameToID}->{'CustomerID'} }     = 1;
5350                    $StoredFields{ $Self->{NameToID}->{'CustomerUserID'} } = 1;
5351                    next DIALOGFIELD;
5352                }
5353
5354                $Success = $TicketObject->TicketCustomerSet(
5355                    No => $TicketParam{CustomerID},
5356
5357                    # here too: unfortunately TicketCreate takes Param 'CustomerUser'
5358                    # instead of CustomerUserID, so our TicketParam hash
5359                    # has the CustomerUser Key instead of 'CustomerUserID'
5360                    User     => $TicketParam{CustomerUser},
5361                    TicketID => $TicketID,
5362                    UserID   => $Self->{UserID},
5363                );
5364
5365                # In this case we don't want to call any additional stores
5366                # on Customer, CustomerNo, CustomerID or CustomerUserID
5367                # so make sure both fields are set to "Stored" ;)
5368                $StoredFields{ $Self->{NameToID}->{'CustomerID'} }     = 1;
5369                $StoredFields{ $Self->{NameToID}->{'CustomerUserID'} } = 1;
5370            }
5371            else {
5372                next DIALOGFIELD if $StoredFields{ $Self->{NameToID}->{$CurrentField} };
5373
5374                my $TicketFieldSetSub = $CurrentField;
5375                $TicketFieldSetSub =~ s{ID$}{}xms;
5376                $TicketFieldSetSub = 'Ticket' . $TicketFieldSetSub . 'Set';
5377
5378                if ( $TicketObject->can($TicketFieldSetSub) )
5379                {
5380                    my $UpdateFieldName;
5381
5382                    # sadly we need an exception for Owner(ID) and Responsible(ID), because the
5383                    # Ticket*Set subs need NewUserID as param
5384                    if (
5385                        scalar grep { $Self->{NameToID}->{$CurrentField} eq $_ }
5386                        qw( OwnerID ResponsibleID )
5387                        )
5388                    {
5389                        $UpdateFieldName = 'NewUserID';
5390                    }
5391                    else {
5392                        $UpdateFieldName = $Self->{NameToID}->{$CurrentField};
5393                    }
5394
5395                    # to store if the field needs to be updated
5396                    my $FieldUpdate;
5397
5398                    # only Service and SLA fields accepts empty values if the hash key is not
5399                    # defined set it to empty so the Ticket*Set function call will get the empty
5400                    # value
5401                    if (
5402                        ( $UpdateFieldName eq 'ServiceID' || $UpdateFieldName eq 'SLAID' )
5403                        && !defined $TicketParam{ $Self->{NameToID}->{$CurrentField} }
5404                        )
5405                    {
5406                        $TicketParam{ $Self->{NameToID}->{$CurrentField} } = '';
5407                        $FieldUpdate = 1;
5408                    }
5409
5410                    # update Service an SLA fields if they have a defined value (even empty)
5411                    elsif ( $UpdateFieldName eq 'ServiceID' || $UpdateFieldName eq 'SLAID' )
5412                    {
5413                        $FieldUpdate = 1;
5414                    }
5415
5416                    # update any other field that its value is defined and not empty
5417                    elsif (
5418                        $UpdateFieldName ne 'ServiceID'
5419                        && $UpdateFieldName ne 'SLAID'
5420                        && defined $TicketParam{ $Self->{NameToID}->{$CurrentField} }
5421                        && $TicketParam{ $Self->{NameToID}->{$CurrentField} } ne ''
5422                        )
5423                    {
5424                        $FieldUpdate = 1;
5425                    }
5426
5427                    $Success = 1;
5428
5429                    # check if field needs to be updated
5430                    if ($FieldUpdate) {
5431                        $Success = $TicketObject->$TicketFieldSetSub(
5432                            $UpdateFieldName => $TicketParam{ $Self->{NameToID}->{$CurrentField} },
5433                            TicketID         => $TicketID,
5434                            UserID           => $Self->{UserID},
5435                        );
5436
5437                        # in case of a new service and no new SLA is to be set, check if current
5438                        # assigned SLA is still valid
5439                        if (
5440                            $UpdateFieldName eq 'ServiceID'
5441                            && !defined $TicketParam{SLAID}
5442                            )
5443                        {
5444
5445                            # get ticket details
5446                            my %Ticket = $TicketObject->TicketGet(
5447                                TicketID      => $TicketID,
5448                                DynamicFields => 0,
5449                                UserID        => $Self->{UserID},
5450                            );
5451
5452                            # if ticket already have an SLA assigned get the list SLAs for the new
5453                            # service
5454                            if ( IsPositiveInteger( $Ticket{SLAID} ) ) {
5455                                my %SLAList = $Kernel::OM->Get('Kernel::System::SLA')->SLAList(
5456                                    ServiceID => $TicketParam{ $Self->{NameToID}->{$CurrentField} },
5457                                    UserID    => $Self->{UserID},
5458                                );
5459
5460                                # if the current SLA is not in the list of SLA for new service
5461                                # remove SLA from ticket
5462                                if ( !$SLAList{ $Ticket{SLAID} } ) {
5463                                    $TicketObject->TicketSLASet(
5464                                        SLAID    => '',
5465                                        TicketID => $TicketID,
5466                                        UserID   => $Self->{UserID},
5467                                    );
5468                                }
5469                            }
5470                        }
5471                    }
5472                }
5473            }
5474            if ( !$Success ) {
5475                $LayoutObject->FatalError(
5476                    Message => $LayoutObject->{LanguageObject}->Translate(
5477                        'Could not set %s for Ticket with ID "%s" in ActivityDialog "%s"!',
5478                        $CurrentField,
5479                        $TicketID,
5480                        $ActivityDialogEntityID,
5481                    ),
5482                );
5483            }
5484        }
5485    }
5486
5487    # get the link ticket id if given
5488    my $LinkTicketID = $ParamObject->GetParam( Param => 'LinkTicketID' ) || '';
5489
5490    # get screen config
5491    my $Config = $Kernel::OM->Get('Kernel::Config')->Get("Ticket::Frontend::$Self->{Action}");
5492
5493    # link tickets
5494    if (
5495        $LinkTicketID
5496        && $Config->{SplitLinkType}
5497        && $Config->{SplitLinkType}->{LinkType}
5498        && $Config->{SplitLinkType}->{Direction}
5499        )
5500    {
5501
5502        my $Access = $TicketObject->TicketPermission(
5503            Type     => 'ro',
5504            TicketID => $LinkTicketID,
5505            UserID   => $Self->{UserID}
5506        );
5507
5508        if ( !$Access ) {
5509            return $LayoutObject->NoPermission(
5510                Message    => "You need ro permission!",
5511                WithHeader => 'yes',
5512            );
5513        }
5514
5515        my $SourceKey = $LinkTicketID;
5516        my $TargetKey = $TicketID;
5517
5518        if ( $Config->{SplitLinkType}->{Direction} eq 'Source' ) {
5519            $SourceKey = $TicketID;
5520            $TargetKey = $LinkTicketID;
5521        }
5522
5523        # link the tickets
5524        $Kernel::OM->Get('Kernel::System::LinkObject')->LinkAdd(
5525            SourceObject => 'Ticket',
5526            SourceKey    => $SourceKey,
5527            TargetObject => 'Ticket',
5528            TargetKey    => $TargetKey,
5529            Type         => $Config->{SplitLinkType}->{LinkType} || 'Normal',
5530            State        => 'Valid',
5531            UserID       => $Self->{UserID},
5532        );
5533    }
5534
5535    if ($NewOwnerID) {
5536        $TicketObject->TicketOwnerSet(
5537            TicketID  => $TicketID,
5538            NewUserID => $NewOwnerID,
5539            UserID    => $Self->{UserID},
5540        );
5541    }
5542
5543    # Transitions will be handled by ticket event module (TicketProcessTransitions.pm).
5544
5545    # if we were updating a ticket, close the pop-up and return to zoom
5546    # else (new ticket) just go to zoom to show the new ticket
5547    if ($UpdateTicketID) {
5548
5549        # load new URL in parent window and close pop-up
5550        return $LayoutObject->PopupClose(
5551            URL => "Action=AgentTicketZoom;TicketID=$UpdateTicketID",
5552        );
5553    }
5554
5555    return $LayoutObject->Redirect(
5556        OP => "Action=AgentTicketZoom;TicketID=$TicketID",
5557    );
5558}
5559
5560sub _DisplayProcessList {
5561    my ( $Self, %Param ) = @_;
5562
5563    # If we have a ProcessEntityID
5564    $Param{Errors}->{ProcessEntityIDInvalid} = ' ServerError'
5565        if ( $Param{ProcessEntityID} && !$Param{ProcessList}->{ $Param{ProcessEntityID} } );
5566
5567    # get layout object
5568    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
5569
5570    $Param{ProcessList} = $LayoutObject->BuildSelection(
5571        Class        => 'Modernize Validate_Required' . ( $Param{Errors}->{ProcessEntityIDInvalid} || ' ' ),
5572        Data         => $Param{ProcessList},
5573        Name         => 'ProcessEntityID',
5574        SelectedID   => $Param{ProcessEntityID},
5575        PossibleNone => 1,
5576        Sort         => 'AlphanumericValue',
5577        Translation  => 0,
5578        AutoComplete => 'off',
5579    );
5580
5581    # add rich text editor
5582    if ( $LayoutObject->{BrowserRichText} ) {
5583
5584        # use height/width defined for this screen
5585        $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
5586        $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;
5587
5588        # set up rich text editor
5589        $LayoutObject->SetRichTextParameters(
5590            Data => \%Param,
5591        );
5592    }
5593
5594    if ( $Param{PreSelectProcess} && $Param{ProcessID} ) {
5595
5596        # send data to JS
5597        $LayoutObject->AddJSData(
5598            Key   => 'ProcessID',
5599            Value => $Param{ProcessID},
5600        );
5601    }
5602
5603    $LayoutObject->Block(
5604        Name => 'ProcessList',
5605        Data => {
5606            %Param,
5607            FormID => $Self->{FormID},
5608        },
5609    );
5610
5611    # on initial screen from navbar there is no IsMainWinow but also no IsProcessEnroll,
5612    # then it must be a MainWindow
5613    if ( !$Self->{IsMainWindow} && !$Self->{IsProcessEnroll} ) {
5614        $Self->{IsMainWindow} = 1;
5615    }
5616
5617    my $Type = $Self->{IsMainWindow} ? '' : 'Small';
5618
5619    my $Output = $LayoutObject->Header(
5620        Type => $Type,
5621    );
5622    if ( $Self->{IsMainWindow} ) {
5623        $Output .= $LayoutObject->NavigationBar();
5624    }
5625
5626    $Output .= $LayoutObject->Output(
5627        TemplateFile => 'AgentTicketProcess' . $Type,
5628        Data         => {
5629            %Param,
5630            FormID          => $Self->{FormID},
5631            IsProcessEnroll => $Self->{IsProcessEnroll},
5632        },
5633    );
5634
5635    # workaround when activity dialog is loaded by AJAX as first activity dialog, if there is
5636    # a date field like Pending Time or Dynamic Fields Date/Time or Date, there is no way to set
5637    # this options in the footer again
5638    $LayoutObject->{HasDatepicker} = 1;
5639
5640    $Output .= $LayoutObject->Footer( Type => $Type );
5641
5642    return $Output;
5643}
5644
5645# =cut
5646#
5647# _CheckField()
5648#
5649# checks all the possible ticket fields and returns the ID (if possible) value of the field, if valid
5650# and checks are successful
5651#
5652# if Display param is set to 0 or not given, it uses ActivityDialog field default value for all fields
5653# or global default value as fall-back only for certain fields
5654#
5655# if Display param is set to 1 or 2 it uses the value from the web request
5656#
5657#     my $PriorityID = $AgentTicketProcessObject->_CheckField(
5658#         Field        => 'PriorityID',
5659#         Display      => 1,                   # optional, 0 or 1 or 2
5660#         DefaultValue => '3 normal',          # ActivityDialog field default value (it uses global
5661#                                              #    default value as fall back for mandatory fields
5662#                                              #    (Queue, Sate, Lock and Priority)
5663#     );
5664#
5665# Returns:
5666#     $PriorityID = 1;                         # if PriorityID is set to 1 in the web request
5667#
5668#     my $PriorityID = $AgentTicketProcessObject->_CheckField(
5669#         Field        => 'PriorityID',
5670#         Display      => 0,
5671#         DefaultValue => '3 normal',
5672#     );
5673#
5674# Returns:
5675#     $PriorityID = 3;                        # since ActivityDialog default value is '3 normal' and
5676#                                             #     field is hidden
5677#
5678# =cut
5679
5680sub _CheckField {
5681    my ( $Self, %Param ) = @_;
5682
5683    # check needed stuff
5684    for my $Needed (qw(Field)) {
5685        if ( !$Param{$Needed} ) {
5686            $Kernel::OM->Get('Kernel::System::Log')->Log(
5687                Priority => 'error',
5688                Message  => "Need $Needed!"
5689            );
5690            return;
5691        }
5692    }
5693
5694    # remove the ID and check if the given field is required for creating a ticket
5695    my $FieldWithoutID = $Param{Field};
5696    $FieldWithoutID =~ s{ID$}{}xms;
5697    my $TicketRequiredField = scalar grep { $_ eq $FieldWithoutID } qw(Queue State Lock Priority);
5698
5699    my $Value;
5700
5701    # get needed objects
5702    my $ParamObject  = $Kernel::OM->Get('Kernel::System::Web::Request');
5703    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
5704
5705    # if no Display (or Display == 0) is committed
5706    if ( !$Param{Display} ) {
5707
5708        # Check if a DefaultValue is given
5709        if ( $Param{DefaultValue} ) {
5710
5711            # check if the given field param is valid
5712            $Value = $Self->_LookupValue(
5713                Field => $FieldWithoutID,
5714                Value => $Param{DefaultValue},
5715            );
5716        }
5717
5718        # if we got a required ticket field, check if we got a valid DefaultValue in the SysConfig
5719        if ( !$Value && $TicketRequiredField ) {
5720            $Value = $Kernel::OM->Get('Kernel::Config')->Get("Process::Default$FieldWithoutID");
5721
5722            if ( !$Value ) {
5723                $LayoutObject->FatalError(
5724                    Message => $LayoutObject->{LanguageObject}->Translate(
5725                        'Default Config for Process::Default%s missing!',
5726                        $FieldWithoutID,
5727                    ),
5728                );
5729            }
5730            else {
5731
5732                # check if the given field param is valid
5733                $Value = $Self->_LookupValue(
5734                    Field => $FieldWithoutID,
5735                    Value => $Value,
5736                );
5737                if ( !$Value ) {
5738                    $LayoutObject->FatalError(
5739                        Message => $LayoutObject->{LanguageObject}->Translate(
5740                            'Default Config for Process::Default%s invalid!',
5741                            $FieldWithoutID,
5742                        ),
5743                    );
5744                }
5745            }
5746        }
5747    }
5748    elsif ( $Param{Display} == 1 ) {
5749
5750        # Display == 1 is logicality not possible for a ticket required field
5751        if ($TicketRequiredField) {
5752            $LayoutObject->FatalError(
5753                Message => $LayoutObject->{LanguageObject}->Translate(
5754                    'Wrong ActivityDialog Field config: %s can\'t be Display => 1 / Show field (Please change its configuration to be Display => 0 / Do not show field or Display => 2 / Show field as mandatory)!',
5755                    $Param{Field},
5756                ),
5757            );
5758        }
5759
5760        # check if the given field param is valid
5761        if ( $Param{Field} eq 'Article' ) {
5762
5763            $Value = 1;
5764
5765            my ( $Body, $Subject, $AttachmentExists, $TimeUnits ) = (
5766                $ParamObject->GetParam( Param => 'Body' ),
5767                $ParamObject->GetParam( Param => 'Subject' ),
5768                $ParamObject->GetParam( Param => 'AttachmentExists' ),
5769                $ParamObject->GetParam( Param => 'TimeUnits' )
5770            );
5771
5772            # If attachment exists and body and subject not, it is error (see bug#13081).
5773            if ( $AttachmentExists && ( !$Body && !$Subject ) ) {
5774                $Value = 0;
5775            }
5776
5777            # If time units exists and body and subject not, it is error (see bug#13266).
5778            if ( $TimeUnits && ( !$Body && !$Subject ) ) {
5779                $Value = 0;
5780            }
5781        }
5782        else {
5783
5784            $Value = $Self->_LookupValue(
5785                Field => $Param{Field},
5786                Value => $ParamObject->GetParam( Param => $Param{Field} ) || '',
5787            );
5788        }
5789    }
5790    elsif ( $Param{Display} == 2 ) {
5791
5792        # check if the given field param is valid
5793        if ( $Param{Field} eq 'Article' ) {
5794
5795            my ( $Body, $Subject ) = (
5796                $ParamObject->GetParam( Param => 'Body' ),
5797                $ParamObject->GetParam( Param => 'Subject' )
5798            );
5799
5800            $Value = 0;
5801            if ( $Body && $Subject ) {
5802                $Value = 1;
5803            }
5804        }
5805        else {
5806            $Value = $Self->_LookupValue(
5807                Field => $Param{Field},
5808                Value => $ParamObject->GetParam( Param => $Param{Field} ) || '',
5809            );
5810        }
5811    }
5812
5813    return $Value;
5814}
5815
5816# =cut
5817#
5818# _LookupValue()
5819#
5820# returns the ID (if possible) of nearly all ticket fields and/or checks if its valid.
5821# Can handle IDs or Strings.
5822# Currently working with: State, Queue, Lock, Priority (possible more).
5823#
5824#     my $PriorityID = $AgentTicketProcessObject->_LookupValue(
5825#         PriorityID => 1,
5826#     );
5827#     $PriorityID = 1;
5828#
5829#     my $StateID = $AgentTicketProcessObject->_LookupValue(
5830#         State => 'open',
5831#     );
5832#     $StateID = 3;
5833#
5834#     my $PriorityID = $AgentTicketProcessObject->_LookupValue(
5835#         Priority => 'unknownpriority1234',
5836#     );
5837#     $PriorityID = undef;
5838#
5839# =cut
5840
5841sub _LookupValue {
5842    my ( $Self, %Param ) = @_;
5843
5844    # get log object
5845    my $LogObject = $Kernel::OM->Get('Kernel::System::Log');
5846
5847    # check needed stuff
5848    for my $Needed (qw(Field Value)) {
5849        if ( !defined $Param{$Needed} ) {
5850            $LogObject->Log(
5851                Priority => 'error',
5852                Message  => "Need $Needed!"
5853            );
5854            return;
5855        }
5856    }
5857
5858    if ( !$Param{Field} ) {
5859        $LogObject->Log(
5860            Priority => 'error',
5861            Message  => "Field should not be empty!"
5862        );
5863        return;
5864    }
5865
5866    # if there is no value, there is nothing to do
5867    return if !$Param{Value};
5868
5869    # remove the ID for function name purpose
5870    my $FieldWithoutID = $Param{Field};
5871    $FieldWithoutID =~ s{ID$}{}xms;
5872
5873    my $LookupFieldName;
5874    my $ObjectName;
5875    my $FunctionName;
5876
5877    # owner(ID) and responsible(ID) lookup needs UserID as parameter
5878    if ( scalar grep { $Param{Field} eq $_ } qw( OwnerID ResponsibleID ) ) {
5879        $LookupFieldName = 'UserID';
5880        $ObjectName      = 'User';
5881        $FunctionName    = 'UserLookup';
5882    }
5883
5884    # owner and responsible lookup needs UserLogin as parameter
5885    elsif ( scalar grep { $Param{Field} eq $_ } qw( Owner Responsible ) ) {
5886        $LookupFieldName = 'UserLogin';
5887        $ObjectName      = 'User';
5888        $FunctionName    = 'UserLookup';
5889    }
5890
5891    # service and SLA lookup needs Name as parameter (While ServiceID an SLAID uses standard)
5892    elsif ( scalar grep { $Param{Field} eq $_ } qw( Service SLA ) ) {
5893        $LookupFieldName = 'Name';
5894        $ObjectName      = $FieldWithoutID;
5895        $FunctionName    = $FieldWithoutID . 'Lookup';
5896    }
5897
5898    # other fields can use standard parameter names as Priority or PriorityID
5899    else {
5900        $LookupFieldName = $Param{Field};
5901        $ObjectName      = $FieldWithoutID;
5902        $FunctionName    = $FieldWithoutID . 'Lookup';
5903    }
5904
5905    # get appropriate object of field
5906    my $FieldObject;
5907    if ( $Kernel::OM->Get('Kernel::System::Main')->Require( 'Kernel::System::' . $ObjectName, Silent => 1 ) ) {
5908        $FieldObject = $Kernel::OM->Get( 'Kernel::System::' . $ObjectName );
5909    }
5910
5911    my $Value;
5912
5913    # check if the backend module has the needed *Lookup sub
5914    if ( $FieldObject && $FieldObject->can($FunctionName) ) {
5915
5916        # call the *Lookup sub and get the value
5917        $Value = $FieldObject->$FunctionName(
5918            $LookupFieldName => $Param{Value},
5919        );
5920    }
5921
5922    # if we didn't have an object and the value has no ref a string e.g. Title and so on
5923    # return true
5924    elsif ( $Param{Field} eq $FieldWithoutID && !ref $Param{Value} ) {
5925        return $Param{Value};
5926    }
5927    else {
5928        $LogObject->Log(
5929            Priority => 'error',
5930            Message  => "Error while checking with " . $FieldWithoutID . "Object!"
5931        );
5932        return;
5933    }
5934
5935    return if ( !$Value );
5936
5937    # return the given ID value if the *Lookup result was a string
5938    if ( $Param{Field} ne $FieldWithoutID ) {
5939        return $Param{Value};
5940    }
5941
5942    # return the *Lookup string return value
5943    return $Value;
5944}
5945
5946sub _GetResponsibles {
5947    my ( $Self, %Param ) = @_;
5948
5949    # get users
5950    my %ShownUsers;
5951    my %AllGroupsMembers = $Kernel::OM->Get('Kernel::System::User')->UserList(
5952        Type  => 'Long',
5953        Valid => 1,
5954    );
5955
5956    # get needed objects
5957    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
5958    my $QueueObject  = $Kernel::OM->Get('Kernel::System::Queue');
5959    my $GroupObject  = $Kernel::OM->Get('Kernel::System::Group');
5960    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
5961
5962    # Get available permissions and set permission group type accordingly.
5963    my $ConfigPermissions   = $ConfigObject->Get('System::Permission');
5964    my $PermissionGroupType = ( grep { $_ eq 'responsible' } @{$ConfigPermissions} ) ? 'responsible' : 'rw';
5965
5966    # if we are updating a ticket show the full list of possible responsibles
5967    if ( $Param{TicketID} ) {
5968        if ( $Param{QueueID} && !$Param{AllUsers} ) {
5969            my $GID        = $QueueObject->GetQueueGroupID( QueueID => $Param{QueueID} );
5970            my %MemberList = $GroupObject->PermissionGroupGet(
5971                GroupID => $GID,
5972                Type    => $PermissionGroupType,
5973            );
5974            for my $UserID ( sort keys %MemberList ) {
5975                $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
5976            }
5977        }
5978    }
5979    else {
5980
5981        # the StartActivityDialog does not provide a TicketID and it could be that also there
5982        # is no QueueID information. Get the default QueueID for this matters.
5983        if ( !$Param{QueueID} ) {
5984            my $Queue   = $ConfigObject->Get("Process::DefaultQueue");
5985            my $QueueID = $QueueObject->QueueLookup( Queue => $Queue );
5986            if ($QueueID) {
5987                $Param{QueueID} = $QueueID;
5988            }
5989        }
5990
5991        # just show only users with selected custom queue
5992        if ( $Param{QueueID} && !$Param{ResponsibleAll} ) {
5993            my @UserIDs = $TicketObject->GetSubscribedUserIDsByQueueID(%Param);
5994            for my $KeyGroupMember ( sort keys %AllGroupsMembers ) {
5995                my $Hit = 0;
5996                for my $UID (@UserIDs) {
5997                    if ( $UID eq $KeyGroupMember ) {
5998                        $Hit = 1;
5999                    }
6000                }
6001                if ( !$Hit ) {
6002                    delete $AllGroupsMembers{$KeyGroupMember};
6003                }
6004            }
6005        }
6006
6007        # show all system users
6008        if ( $ConfigObject->Get('Ticket::ChangeOwnerToEveryone') ) {
6009            %ShownUsers = %AllGroupsMembers;
6010        }
6011
6012        # show all subscribed users who have the appropriate permission in the queue group
6013        elsif ( $Param{QueueID} ) {
6014            my $GID        = $QueueObject->GetQueueGroupID( QueueID => $Param{QueueID} );
6015            my %MemberList = $GroupObject->PermissionGroupGet(
6016                GroupID => $GID,
6017                Type    => $PermissionGroupType,
6018            );
6019            for my $KeyMember ( sort keys %MemberList ) {
6020                if ( $AllGroupsMembers{$KeyMember} ) {
6021                    $ShownUsers{$KeyMember} = $AllGroupsMembers{$KeyMember};
6022                }
6023            }
6024        }
6025    }
6026
6027    # workflow
6028    my $ACL = $TicketObject->TicketAcl(
6029        %Param,
6030        Action        => $Self->{Action},
6031        ReturnType    => 'Ticket',
6032        ReturnSubType => 'Responsible',
6033        Data          => \%ShownUsers,
6034        UserID        => $Self->{UserID},
6035    );
6036
6037    return { $TicketObject->TicketAclData() } if $ACL;
6038
6039    return \%ShownUsers;
6040}
6041
6042sub _GetOwners {
6043    my ( $Self, %Param ) = @_;
6044
6045    # get users
6046    my %ShownUsers;
6047    my %AllGroupsMembers = $Kernel::OM->Get('Kernel::System::User')->UserList(
6048        Type  => 'Long',
6049        Valid => 1,
6050    );
6051
6052    # get needed objects
6053    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
6054    my $QueueObject  = $Kernel::OM->Get('Kernel::System::Queue');
6055    my $GroupObject  = $Kernel::OM->Get('Kernel::System::Group');
6056    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
6057
6058    # Get available permissions and set permission group type accordingly.
6059    my $ConfigPermissions   = $ConfigObject->Get('System::Permission');
6060    my $PermissionGroupType = ( grep { $_ eq 'owner' } @{$ConfigPermissions} ) ? 'owner' : 'rw';
6061
6062    # if we are updating a ticket show the full list of possible owners
6063    if ( $Param{TicketID} ) {
6064        if ( $Param{QueueID} && !$Param{AllUsers} ) {
6065            my $GID        = $QueueObject->GetQueueGroupID( QueueID => $Param{QueueID} );
6066            my %MemberList = $GroupObject->PermissionGroupGet(
6067                GroupID => $GID,
6068                Type    => $PermissionGroupType,
6069            );
6070            for my $UserID ( sort keys %MemberList ) {
6071                $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
6072            }
6073        }
6074    }
6075    else {
6076
6077        # the StartActivityDialog does not provide a TicketID and it could be that also there
6078        # is no QueueID information. Get the default QueueID for this matters.
6079        if ( !$Param{QueueID} ) {
6080            my $Queue   = $ConfigObject->Get("Process::DefaultQueue");
6081            my $QueueID = $QueueObject->QueueLookup( Queue => $Queue );
6082            if ($QueueID) {
6083                $Param{QueueID} = $QueueID;
6084            }
6085        }
6086
6087        # just show only users with selected custom queue
6088        if ( $Param{QueueID} && !$Param{OwnerAll} ) {
6089            my @UserIDs = $TicketObject->GetSubscribedUserIDsByQueueID(%Param);
6090            for my $KeyGroupMember ( sort keys %AllGroupsMembers ) {
6091                my $Hit = 0;
6092                for my $UID (@UserIDs) {
6093                    if ( $UID eq $KeyGroupMember ) {
6094                        $Hit = 1;
6095                    }
6096                }
6097                if ( !$Hit ) {
6098                    delete $AllGroupsMembers{$KeyGroupMember};
6099                }
6100            }
6101        }
6102
6103        # show all system users
6104        if ( $ConfigObject->Get('Ticket::ChangeOwnerToEveryone') ) {
6105            %ShownUsers = %AllGroupsMembers;
6106        }
6107
6108        # show all subscribed users who have the appropriate permission in the queue group
6109        elsif ( $Param{QueueID} ) {
6110            my $GID        = $QueueObject->GetQueueGroupID( QueueID => $Param{QueueID} );
6111            my %MemberList = $GroupObject->PermissionGroupGet(
6112                GroupID => $GID,
6113                Type    => $PermissionGroupType,
6114            );
6115            for my $KeyMember ( sort keys %MemberList ) {
6116                if ( $AllGroupsMembers{$KeyMember} ) {
6117                    $ShownUsers{$KeyMember} = $AllGroupsMembers{$KeyMember};
6118                }
6119            }
6120        }
6121    }
6122
6123    # workflow
6124    my $ACL = $TicketObject->TicketAcl(
6125        %Param,
6126        Action        => $Self->{Action},
6127        ReturnType    => 'Ticket',
6128        ReturnSubType => 'Owner',
6129        Data          => \%ShownUsers,
6130        UserID        => $Self->{UserID},
6131    );
6132
6133    return { $TicketObject->TicketAclData() } if $ACL;
6134
6135    return \%ShownUsers;
6136}
6137
6138sub _GetSLAs {
6139    my ( $Self, %Param ) = @_;
6140
6141    # get sla
6142    my %SLA;
6143    if ( $Param{ServiceID} && $Param{Services} && %{ $Param{Services} } ) {
6144        if ( $Param{Services}->{ $Param{ServiceID} } ) {
6145            %SLA = $Kernel::OM->Get('Kernel::System::Ticket')->TicketSLAList(
6146                %Param,
6147                Action => $Self->{Action},
6148                UserID => $Self->{UserID},
6149            );
6150        }
6151    }
6152    return \%SLA;
6153}
6154
6155sub _GetServices {
6156    my ( $Self, %Param ) = @_;
6157
6158    # get service
6159    my %Service;
6160
6161    # check needed
6162    return \%Service if !$Param{QueueID} && !$Param{TicketID};
6163
6164    # get options for default services for unknown customers
6165    my $DefaultServiceUnknownCustomer
6166        = $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Service::Default::UnknownCustomer');
6167
6168    # check if no CustomerUserID is selected
6169    # if $DefaultServiceUnknownCustomer = 0 leave CustomerUserID empty, it will not get any services
6170    # if $DefaultServiceUnknownCustomer = 1 set CustomerUserID to get default services
6171    if ( !$Param{CustomerUserID} && $DefaultServiceUnknownCustomer ) {
6172        $Param{CustomerUserID} = '<DEFAULT>';
6173    }
6174
6175    # get service list
6176    if ( $Param{CustomerUserID} ) {
6177        %Service = $Kernel::OM->Get('Kernel::System::Ticket')->TicketServiceList(
6178            %Param,
6179            Action => $Self->{Action},
6180            UserID => $Self->{UserID},
6181        );
6182    }
6183    return \%Service;
6184}
6185
6186sub _GetLocks {
6187    my ( $Self, %Param ) = @_;
6188
6189    my %Locks = $Kernel::OM->Get('Kernel::System::Lock')->LockList(
6190        UserID => $Self->{UserID},
6191    );
6192
6193    return \%Locks;
6194}
6195
6196sub _GetPriorities {
6197    my ( $Self, %Param ) = @_;
6198
6199    my %Priorities;
6200
6201    # Initially we have just the default Queue Parameter
6202    # so make sure to get the ID in that case
6203    my $QueueID;
6204    if ( !$Param{QueueID} && $Param{Queue} ) {
6205        $QueueID = $Kernel::OM->Get('Kernel::System::Queue')->QueueLookup( Queue => $Param{Queue} );
6206    }
6207    if ( $Param{QueueID} || $QueueID || $Param{TicketID} ) {
6208        %Priorities = $Kernel::OM->Get('Kernel::System::Ticket')->TicketPriorityList(
6209            %Param,
6210            Action => $Self->{Action},
6211            UserID => $Self->{UserID},
6212        );
6213
6214    }
6215    return \%Priorities;
6216}
6217
6218sub _GetQueues {
6219    my ( $Self, %Param ) = @_;
6220
6221    # check which type of permission is needed: if the process ticket
6222    # already exists (= TicketID is present), we need the 'move_into'
6223    # permission otherwise the 'create' permission
6224    my $PermissionType = 'create';
6225    if ( $Param{TicketID} ) {
6226        $PermissionType = 'move_into';
6227    }
6228
6229    # get config object
6230    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
6231
6232    # check own selection
6233    my %NewQueues;
6234    if ( $ConfigObject->Get('Ticket::Frontend::NewQueueOwnSelection') ) {
6235        %NewQueues = %{ $ConfigObject->Get('Ticket::Frontend::NewQueueOwnSelection') };
6236    }
6237    else {
6238
6239        # SelectionType Queue or SystemAddress?
6240        my %Queues;
6241        if ( $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionType') eq 'Queue' ) {
6242            %Queues = $Kernel::OM->Get('Kernel::System::Ticket')->MoveList(
6243                %Param,
6244                Type    => $PermissionType,
6245                Action  => $Self->{Action},
6246                QueueID => $Self->{QueueID},
6247                UserID  => $Self->{UserID},
6248            );
6249        }
6250        else {
6251            %Queues = $Kernel::OM->Get('Kernel::System::SystemAddress')->SystemAddressQueueList();
6252        }
6253
6254        # get permission queues
6255        my %UserGroups = $Kernel::OM->Get('Kernel::System::Group')->PermissionUserGet(
6256            UserID => $Self->{UserID},
6257            Type   => $PermissionType,
6258        );
6259
6260        # build selection string
6261        QUEUEID:
6262        for my $QueueID ( sort keys %Queues ) {
6263            my %QueueData = $Kernel::OM->Get('Kernel::System::Queue')->QueueGet( ID => $QueueID );
6264
6265            # permission check, can we create new tickets in queue
6266            next QUEUEID if !$UserGroups{ $QueueData{GroupID} };
6267
6268            my $String = $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionString')
6269                || '<Realname> <<Email>> - Queue: <Queue>';
6270            $String =~ s/<Queue>/$QueueData{Name}/g;
6271            $String =~ s/<QueueComment>/$QueueData{Comment}/g;
6272
6273            # remove trailing spaces
6274            $String =~ s{\s+\z}{} if !$QueueData{Comment};
6275
6276            if ( $ConfigObject->Get('Ticket::Frontend::NewQueueSelectionType') ne 'Queue' )
6277            {
6278                my %SystemAddressData = $Self->{SystemAddress}->SystemAddressGet(
6279                    ID => $Queues{$QueueID},
6280                );
6281                $String =~ s/<Realname>/$SystemAddressData{Realname}/g;
6282                $String =~ s/<Email>/$SystemAddressData{Name}/g;
6283            }
6284            $NewQueues{$QueueID} = $String;
6285        }
6286    }
6287
6288    return \%NewQueues;
6289}
6290
6291sub _GetStates {
6292    my ( $Self, %Param ) = @_;
6293
6294    my %States = $Kernel::OM->Get('Kernel::System::Ticket')->TicketStateList(
6295        %Param,
6296
6297        # Set default values for new process ticket
6298        QueueID  => $Param{QueueID}  || 1,
6299        TicketID => $Param{TicketID} || '',
6300
6301        # remove type, since if Ticket::Type is active in sysconfig, the Type parameter will
6302        # be sent and the TicketStateList will send the parameter as State Type
6303        Type => undef,
6304
6305        Action => $Self->{Action},
6306        UserID => $Self->{UserID},
6307    );
6308
6309    return \%States;
6310}
6311
6312sub _GetTypes {
6313    my ( $Self, %Param ) = @_;
6314
6315    # get type
6316    my %Type;
6317    if ( $Param{QueueID} || $Param{TicketID} ) {
6318        %Type = $Kernel::OM->Get('Kernel::System::Ticket')->TicketTypeList(
6319            %Param,
6320            Action => $Self->{Action},
6321            UserID => $Self->{UserID},
6322        );
6323    }
6324    return \%Type;
6325}
6326
6327sub _GetAJAXUpdatableFields {
6328    my ( $Self, %Param ) = @_;
6329
6330    my %DefaultUpdatableFields = (
6331        PriorityID    => 1,
6332        QueueID       => 1,
6333        ResponsibleID => 1,
6334        ServiceID     => 1,
6335        SLAID         => 1,
6336        StateID       => 1,
6337        OwnerID       => 1,
6338        LockID        => 1,
6339        TypeID        => 1,
6340    );
6341
6342    my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
6343        Valid      => 1,
6344        ObjectType => 'Ticket',
6345    );
6346
6347    # create a DynamicFieldLookupTable
6348    my %DynamicFieldLookup = map { 'DynamicField_' . $_->{Name} => $_ } @{$DynamicField};
6349
6350    my @UpdatableFields;
6351    FIELD:
6352    for my $Field ( sort keys %{ $Param{ActivityDialogFields} } ) {
6353
6354        my $FieldData = $Param{ActivityDialogFields}->{$Field};
6355
6356        # skip hidden fields
6357        next FIELD if !$FieldData->{Display};
6358
6359        # for Dynamic Fields check if is AJAXUpdatable
6360        if ( $Field =~ m{^DynamicField_(.*)}xms ) {
6361            my $DynamicFieldConfig = $DynamicFieldLookup{$Field};
6362
6363            # skip any field with wrong config
6364            next FIELD if !IsHashRefWithData($DynamicFieldConfig);
6365
6366            # skip field if is not IsACLReducible (updatable)
6367            my $IsACLReducible = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->HasBehavior(
6368                DynamicFieldConfig => $DynamicFieldConfig,
6369                Behavior           => 'IsACLReducible',
6370            );
6371            next FIELD if !$IsACLReducible;
6372
6373            push @UpdatableFields, $Field;
6374        }
6375
6376        # for all others use %DefaultUpdatableFields table
6377        else {
6378
6379            # standarize the field name (e.g. use StateID for State field)
6380            my $FieldName = $Self->{NameToID}->{$Field};
6381
6382            # skip if field name could not be converted (this means that field is unknown)
6383            next FIELD if !$FieldName;
6384
6385            # skip if the field is not updatable via ajax
6386            next FIELD if !$DefaultUpdatableFields{$FieldName};
6387
6388            push @UpdatableFields, $FieldName;
6389        }
6390    }
6391
6392    return \@UpdatableFields;
6393}
6394
6395sub _GetFieldsToUpdateStrg {
6396    my ( $Self, %Param ) = @_;
6397
6398    my $FieldsToUpdate = '';
6399    if ( IsArrayRefWithData( $Param{AJAXUpdatableFields} ) ) {
6400        my $FirstItem = 1;
6401        FIELD:
6402        for my $Field ( @{ $Param{AJAXUpdatableFields} } ) {
6403            next FIELD if $Field eq $Param{TriggerField};
6404            if ($FirstItem) {
6405                $FirstItem = 0;
6406            }
6407            else {
6408                $FieldsToUpdate .= ', ';
6409            }
6410            $FieldsToUpdate .= "'" . $Field . "'";
6411        }
6412    }
6413    return $FieldsToUpdate;
6414}
6415
6416sub _ShowDialogError {
6417    my ( $Self, %Param ) = @_;
6418
6419    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
6420
6421    my $Output = $LayoutObject->Header( Type => 'Small' );
6422    $Output .= $LayoutObject->Error(%Param);
6423    $Output .= $LayoutObject->Footer( Type => 'Small' );
6424    return $Output;
6425}
6426
64271;
6428