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