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::AdminProcessManagementTransitionAction; 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 return $Self; 27} 28 29sub Run { 30 my ( $Self, %Param ) = @_; 31 32 my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); 33 34 $Self->{Subaction} = $ParamObject->GetParam( Param => 'Subaction' ) || ''; 35 36 my $TransitionActionID = $ParamObject->GetParam( Param => 'ID' ) || ''; 37 my $EntityID = $ParamObject->GetParam( Param => 'EntityID' ) || ''; 38 39 my %SessionData = $Kernel::OM->Get('Kernel::System::AuthSession')->GetSessionIDData( 40 SessionID => $Self->{SessionID}, 41 ); 42 43 # convert JSON string to array 44 $Self->{ScreensPath} = $Kernel::OM->Get('Kernel::System::JSON')->Decode( 45 Data => $SessionData{ProcessManagementScreensPath} 46 ); 47 48 # get needed objects 49 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 50 my $EntityObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::DB::Entity'); 51 my $TransitionActionObject = $Kernel::OM->Get('Kernel::System::ProcessManagement::DB::TransitionAction'); 52 53 # ------------------------------------------------------------ # 54 # TransitionActionNew 55 # ------------------------------------------------------------ # 56 if ( $Self->{Subaction} eq 'TransitionActionNew' ) { 57 58 return $Self->_ShowEdit( 59 %Param, 60 Action => 'New', 61 ); 62 } 63 64 # ------------------------------------------------------------ # 65 # TransitionActionNewAction 66 # ------------------------------------------------------------ # 67 elsif ( $Self->{Subaction} eq 'TransitionActionNewAction' ) { 68 69 # challenge token check for write action 70 $LayoutObject->ChallengeTokenCheck(); 71 72 # get transition action data 73 my $TransitionActionData; 74 75 # get parameter from web browser 76 my $GetParam = $Self->_GetParams(); 77 78 # set new configuration 79 $TransitionActionData->{Name} = $GetParam->{Name}; 80 $TransitionActionData->{Config}->{Module} = $GetParam->{Module}; 81 $TransitionActionData->{Config}->{Config} = $GetParam->{Config}; 82 83 # check required parameters 84 my %Error; 85 if ( !$GetParam->{Name} ) { 86 87 # add server error error class 88 $Error{NameServerError} = 'ServerError'; 89 $Error{NameServerErrorMessage} = Translatable('This field is required'); 90 } 91 92 if ( !$GetParam->{Module} ) { 93 94 # add server error error class 95 $Error{ModuleServerError} = 'ServerError'; 96 $Error{ModuleServerErrorMessage} = Translatable('This field is required'); 97 } 98 99 if ( !$GetParam->{Config} ) { 100 return $LayoutObject->ErrorScreen( 101 Message => Translatable('At least one valid config parameter is required.'), 102 ); 103 } 104 105 # if there is an error return to edit screen 106 if ( IsHashRefWithData( \%Error ) ) { 107 return $Self->_ShowEdit( 108 %Error, 109 %Param, 110 TransitionActionData => $TransitionActionData, 111 Action => 'New', 112 ); 113 } 114 115 # generate entity ID 116 my $EntityID = $EntityObject->EntityIDGenerate( 117 EntityType => 'TransitionAction', 118 UserID => $Self->{UserID}, 119 ); 120 121 # show error if can't generate a new EntityID 122 if ( !$EntityID ) { 123 return $LayoutObject->ErrorScreen( 124 Message => Translatable('There was an error generating a new EntityID for this TransitionAction'), 125 ); 126 } 127 128 # otherwise save configuration and return process screen 129 my $TransitionActionID = $TransitionActionObject->TransitionActionAdd( 130 Name => $TransitionActionData->{Name}, 131 Module => $TransitionActionData->{Module}, 132 EntityID => $EntityID, 133 Config => $TransitionActionData->{Config}, 134 UserID => $Self->{UserID}, 135 ); 136 137 # show error if can't create 138 if ( !$TransitionActionID ) { 139 return $LayoutObject->ErrorScreen( 140 Message => Translatable('There was an error creating the TransitionAction'), 141 ); 142 } 143 144 # set entitty sync state 145 my $Success = $EntityObject->EntitySyncStateSet( 146 EntityType => 'TransitionAction', 147 EntityID => $EntityID, 148 SyncState => 'not_sync', 149 UserID => $Self->{UserID}, 150 ); 151 152 # show error if can't set 153 if ( !$Success ) { 154 return $LayoutObject->ErrorScreen( 155 Message => $LayoutObject->{LanguageObject}->Translate( 156 'There was an error setting the entity sync status for TransitionAction entity: %s', 157 $EntityID 158 ), 159 ); 160 } 161 162 # remove this screen from session screen path 163 $Self->_PopSessionScreen( OnlyCurrent => 1 ); 164 165 my $Redirect = $ParamObject->GetParam( Param => 'PopupRedirect' ) || ''; 166 167 # get latest config data to send it back to main window 168 my $TransitionActionConfig = $Self->_GetTransitionActionConfig( 169 EntityID => $EntityID, 170 ); 171 172 # check if needed to open another window or if popup should go back 173 if ( $Redirect && $Redirect eq '1' ) { 174 175 $Self->_PushSessionScreen( 176 ID => $TransitionActionID, 177 EntityID => $EntityID, 178 Subaction => 'TransitionActionEdit' # always use edit screen 179 ); 180 181 my $RedirectAction = $ParamObject->GetParam( Param => 'PopupRedirectAction' ) || ''; 182 my $RedirectSubaction = $ParamObject->GetParam( Param => 'PopupRedirectSubaction' ) || ''; 183 my $RedirectID = $ParamObject->GetParam( Param => 'PopupRedirectID' ) || ''; 184 my $RedirectEntityID = $ParamObject->GetParam( Param => 'PopupRedirectEntityID' ) || ''; 185 186 # redirect to another popup window 187 return $Self->_PopupResponse( 188 Redirect => 1, 189 Screen => { 190 Action => $RedirectAction, 191 Subaction => $RedirectSubaction, 192 ID => $RedirectID, 193 EntityID => $RedirectID, 194 }, 195 ConfigJSON => $TransitionActionConfig, 196 ); 197 } 198 else { 199 200 # remove last screen 201 my $LastScreen = $Self->_PopSessionScreen(); 202 203 # check if needed to return to main screen or to be redirected to last screen 204 if ( $LastScreen->{Action} eq 'AdminProcessManagement' ) { 205 206 # close the popup 207 return $Self->_PopupResponse( 208 ClosePopup => 1, 209 ConfigJSON => $TransitionActionConfig, 210 ); 211 } 212 else { 213 214 # redirect to last screen 215 return $Self->_PopupResponse( 216 Redirect => 1, 217 Screen => $LastScreen, 218 ConfigJSON => $TransitionActionConfig, 219 ); 220 } 221 } 222 } 223 224 # ------------------------------------------------------------ # 225 # TransitionActionEdit 226 # ------------------------------------------------------------ # 227 elsif ( $Self->{Subaction} eq 'TransitionActionEdit' ) { 228 229 # check for TransitionActionID 230 if ( !$TransitionActionID ) { 231 return $LayoutObject->ErrorScreen( 232 Message => Translatable('Need TransitionActionID!'), 233 ); 234 } 235 236 # remove this screen from session screen path 237 $Self->_PopSessionScreen( OnlyCurrent => 1 ); 238 239 # get TransitionAction data 240 my $TransitionActionData = $TransitionActionObject->TransitionActionGet( 241 ID => $TransitionActionID, 242 UserID => $Self->{UserID}, 243 ); 244 245 # check for valid TransitionAction data 246 if ( !IsHashRefWithData($TransitionActionData) ) { 247 return $LayoutObject->ErrorScreen( 248 Message => $LayoutObject->{LanguageObject}->Translate( 249 'Could not get data for TransitionActionID %s', 250 $TransitionActionID 251 ), 252 ); 253 } 254 255 return $Self->_ShowEdit( 256 %Param, 257 TransitionActionID => $TransitionActionID, 258 TransitionActionData => $TransitionActionData, 259 Action => 'Edit', 260 ); 261 } 262 263 # ------------------------------------------------------------ # 264 # TransitionActionEditAction 265 # ------------------------------------------------------------ # 266 elsif ( $Self->{Subaction} eq 'TransitionActionEditAction' ) { 267 268 # challenge token check for write action 269 $LayoutObject->ChallengeTokenCheck(); 270 271 # get transition action data 272 my $TransitionActionData; 273 274 # get parameter from web browser 275 my $GetParam = $Self->_GetParams(); 276 277 # set new configuration 278 $TransitionActionData->{Name} = $GetParam->{Name}; 279 $TransitionActionData->{EntityID} = $GetParam->{EntityID}; 280 $TransitionActionData->{Config}->{Module} = $GetParam->{Module}; 281 $TransitionActionData->{Config}->{Config} = $GetParam->{Config}; 282 283 # check required parameters 284 my %Error; 285 if ( !$GetParam->{Name} ) { 286 287 # add server error error class 288 $Error{NameServerError} = 'ServerError'; 289 $Error{NameServerErrorMessage} = Translatable('This field is required'); 290 } 291 292 if ( !$GetParam->{Module} ) { 293 294 # add server error error class 295 $Error{ModuleServerError} = 'ServerError'; 296 $Error{ModuleServerErrorMessage} = Translatable('This field is required'); 297 } 298 299 if ( !$GetParam->{Config} ) { 300 return $LayoutObject->ErrorScreen( 301 Message => Translatable('At least one valid config parameter is required.'), 302 ); 303 } 304 305 # if there is an error return to edit screen 306 if ( IsHashRefWithData( \%Error ) ) { 307 return $Self->_ShowEdit( 308 %Error, 309 %Param, 310 TransitionActionData => $TransitionActionData, 311 Action => 'Edit', 312 ); 313 } 314 315 # otherwise save configuration and return to overview screen 316 my $Success = $TransitionActionObject->TransitionActionUpdate( 317 ID => $TransitionActionID, 318 EntityID => $TransitionActionData->{EntityID}, 319 Name => $TransitionActionData->{Name}, 320 Module => $TransitionActionData->{Module}, 321 Config => $TransitionActionData->{Config}, 322 UserID => $Self->{UserID}, 323 ); 324 325 # show error if can't update 326 if ( !$Success ) { 327 return $LayoutObject->ErrorScreen( 328 Message => Translatable('There was an error updating the TransitionAction'), 329 ); 330 } 331 332 # set entitty sync state 333 $Success = $EntityObject->EntitySyncStateSet( 334 EntityType => 'TransitionAction', 335 EntityID => $TransitionActionData->{EntityID}, 336 SyncState => 'not_sync', 337 UserID => $Self->{UserID}, 338 ); 339 340 # show error if can't set 341 if ( !$Success ) { 342 return $LayoutObject->ErrorScreen( 343 Message => $LayoutObject->{LanguageObject}->Translate( 344 'There was an error setting the entity sync status for TransitionAction entity: %s', 345 $TransitionActionData->{EntityID} 346 ), 347 ); 348 } 349 350 # remove this screen from session screen path 351 $Self->_PopSessionScreen( OnlyCurrent => 1 ); 352 353 my $Redirect = $ParamObject->GetParam( Param => 'PopupRedirect' ) || ''; 354 355 # get latest config data to send it back to main window 356 my $TransitionActionConfig = $Self->_GetTransitionActionConfig( 357 EntityID => $TransitionActionData->{EntityID}, 358 ); 359 360 # check if needed to open another window or if popup should go back 361 if ( $Redirect && $Redirect eq '1' ) { 362 363 $Self->_PushSessionScreen( 364 ID => $TransitionActionID, 365 EntityID => $TransitionActionData->{EntityID}, 366 Subaction => 'TransitionActionEdit' # always use edit screen 367 ); 368 369 my $RedirectAction = $ParamObject->GetParam( Param => 'PopupRedirectAction' ) || ''; 370 my $RedirectSubaction = $ParamObject->GetParam( Param => 'PopupRedirectSubaction' ) || ''; 371 my $RedirectID = $ParamObject->GetParam( Param => 'PopupRedirectID' ) || ''; 372 my $RedirectEntityID = $ParamObject->GetParam( Param => 'PopupRedirectEntityID' ) || ''; 373 374 # redirect to another popup window 375 return $Self->_PopupResponse( 376 Redirect => 1, 377 Screen => { 378 Action => $RedirectAction, 379 Subaction => $RedirectSubaction, 380 ID => $RedirectID, 381 EntityID => $RedirectID, 382 }, 383 ConfigJSON => $TransitionActionConfig, 384 ); 385 } 386 else { 387 388 # remove last screen 389 my $LastScreen = $Self->_PopSessionScreen(); 390 391 # check if needed to return to main screen or to be redirected to last screen 392 if ( $LastScreen->{Action} eq 'AdminProcessManagement' ) { 393 394 # close the popup 395 return $Self->_PopupResponse( 396 ClosePopup => 1, 397 ConfigJSON => $TransitionActionConfig, 398 ); 399 } 400 else { 401 402 # redirect to last screen 403 return $Self->_PopupResponse( 404 Redirect => 1, 405 Screen => $LastScreen, 406 ConfigJSON => $TransitionActionConfig, 407 ); 408 } 409 } 410 } 411 412 # ------------------------------------------------------------ # 413 # Close popup 414 # ------------------------------------------------------------ # 415 elsif ( $Self->{Subaction} eq 'ClosePopup' ) { 416 417 # close the popup 418 return $Self->_PopupResponse( 419 ClosePopup => 1, 420 ConfigJSON => '', 421 ); 422 } 423 424 # ------------------------------------------------------------ # 425 # Error 426 # ------------------------------------------------------------ # 427 else { 428 return $LayoutObject->ErrorScreen( 429 Message => Translatable('This subaction is not valid'), 430 ); 431 } 432} 433 434sub _GetTransitionActionConfig { 435 my ( $Self, %Param ) = @_; 436 437 # Get new Transition Config as JSON 438 my $ProcessDump = $Kernel::OM->Get('Kernel::System::ProcessManagement::DB::Process')->ProcessDump( 439 ResultType => 'HASH', 440 UserID => $Self->{UserID}, 441 ); 442 443 my %TransitionActionConfig; 444 $TransitionActionConfig{TransitionAction} = (); 445 $TransitionActionConfig{TransitionAction}->{ $Param{EntityID} } 446 = $ProcessDump->{TransitionAction}->{ $Param{EntityID} }; 447 448 return \%TransitionActionConfig; 449} 450 451sub _ShowEdit { 452 my ( $Self, %Param ) = @_; 453 454 # get TransitionAction information 455 my $TransitionActionData = $Param{TransitionActionData} || {}; 456 457 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 458 459 # check if last screen action is main screen 460 if ( $Self->{ScreensPath}->[-1]->{Action} eq 'AdminProcessManagement' ) { 461 462 # show close popup link 463 $LayoutObject->Block( 464 Name => 'ClosePopup', 465 Data => {}, 466 ); 467 } 468 else { 469 470 # show go back link 471 $LayoutObject->Block( 472 Name => 'GoBack', 473 Data => { 474 Action => $Self->{ScreensPath}->[-1]->{Action} || '', 475 Subaction => $Self->{ScreensPath}->[-1]->{Subaction} || '', 476 ID => $Self->{ScreensPath}->[-1]->{ID} || '', 477 EntityID => $Self->{ScreensPath}->[-1]->{EntityID} || '', 478 StartActivityID => $Self->{ScreensPath}->[-1]->{StartActivityID} || '', 479 }, 480 ); 481 } 482 483 if ( defined $Param{Action} && $Param{Action} eq 'Edit' ) { 484 $Param{Title} = $LayoutObject->{LanguageObject}->Translate( 485 'Edit Transition Action "%s"', 486 $TransitionActionData->{Name} 487 ); 488 } 489 else { 490 $Param{Title} = Translatable('Create New Transition Action'); 491 } 492 493 my $Output = $LayoutObject->Header( 494 Value => $Param{Title}, 495 Type => 'Small', 496 ); 497 498 if ( defined $Param{Action} && $Param{Action} eq 'Edit' ) { 499 500 my $Index = 1; 501 my @ConfigItems = sort keys %{ $TransitionActionData->{Config}->{Config} }; 502 for my $Key (@ConfigItems) { 503 504 $LayoutObject->Block( 505 Name => 'ConfigItemEditRow', 506 Data => { 507 Key => $Key, 508 Value => $TransitionActionData->{Config}->{Config}->{$Key}, 509 Index => $Index, 510 }, 511 ); 512 $Index++; 513 } 514 515 # display other affected transitions by editing this activity (if applicable) 516 my $AffectedProcesses = $Self->_CheckTransitionActionUsage( 517 EntityID => $TransitionActionData->{EntityID}, 518 ); 519 520 if ( @{$AffectedProcesses} ) { 521 522 $LayoutObject->Block( 523 Name => 'EditWarning', 524 Data => { 525 ProcessList => join( ', ', @{$AffectedProcesses} ), 526 } 527 ); 528 } 529 530 } 531 else { 532 $LayoutObject->Block( 533 Name => 'ConfigItemInitRow', 534 ); 535 } 536 537 # lookup existing Transition Actions on disk 538 my $Directory 539 = $Kernel::OM->Get('Kernel::Config')->Get('Home') . '/Kernel/System/ProcessManagement/TransitionAction'; 540 my @List = $Kernel::OM->Get('Kernel::System::Main')->DirectoryRead( 541 Directory => $Directory, 542 Filter => '*.pm', 543 ); 544 my %TransitionAction; 545 ITEM: 546 for my $Item (@List) { 547 548 # remove .pm 549 $Item =~ s/^.*\/(.+?)\.pm$/$1/; 550 next ITEM if $Item eq 'Base'; 551 $TransitionAction{ 'Kernel::System::ProcessManagement::TransitionAction::' . $Item } = $Item; 552 } 553 554 # build TransitionAction string 555 $Param{ModuleStrg} = $LayoutObject->BuildSelection( 556 Data => \%TransitionAction, 557 Name => 'Module', 558 PossibleNone => 1, 559 SelectedID => $TransitionActionData->{Config}->{Module}, 560 Class => 'Modernize Validate_Required ' . ( $Param{Errors}->{'ModuleInvalid'} || '' ), 561 ); 562 563 $Output .= $LayoutObject->Output( 564 TemplateFile => "AdminProcessManagementTransitionAction", 565 Data => { 566 %Param, 567 %{$TransitionActionData}, 568 Name => $TransitionActionData->{Name}, 569 }, 570 ); 571 572 $Output .= $LayoutObject->Footer(); 573 574 return $Output; 575} 576 577sub _GetParams { 578 my ( $Self, %Param ) = @_; 579 580 my $GetParam; 581 my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); 582 583 # get parameters from web browser 584 for my $ParamName ( 585 qw( Name Module EntityID ) 586 ) 587 { 588 $GetParam->{$ParamName} = $ParamObject->GetParam( Param => $ParamName ) || ''; 589 } 590 591 # get config params 592 my @ParamNames = $ParamObject->GetParamNames(); 593 my ( @ConfigParamKeys, @ConfigParamValues ); 594 595 for my $ParamName (@ParamNames) { 596 597 # get keys 598 if ( $ParamName =~ m{ConfigKey\[(\d+)\]}xms ) { 599 push @ConfigParamKeys, $1; 600 } 601 602 # get values 603 if ( $ParamName =~ m{ConfigValue\[(\d+)\]}xms ) { 604 push @ConfigParamValues, $1; 605 } 606 } 607 608 if ( @ConfigParamKeys != @ConfigParamValues ) { 609 return $Kernel::OM->Get('Kernel::Output::HTML::Layout')->ErrorScreen( 610 Message => Translatable('Error: Not all keys seem to have values or vice versa.'), 611 ); 612 } 613 614 my ( $KeyValue, $ValueValue ); 615 for my $Key (@ConfigParamKeys) { 616 $KeyValue = $ParamObject->GetParam( Param => "ConfigKey[$Key]" ); 617 $ValueValue = $ParamObject->GetParam( Param => "ConfigValue[$Key]" ); 618 $GetParam->{Config}->{$KeyValue} = $ValueValue; 619 } 620 621 return $GetParam; 622} 623 624sub _PopSessionScreen { 625 my ( $Self, %Param ) = @_; 626 627 my $LastScreen; 628 629 if ( defined $Param{OnlyCurrent} && $Param{OnlyCurrent} == 1 ) { 630 631 # check if last screen action is current screen action 632 if ( $Self->{ScreensPath}->[-1]->{Action} eq $Self->{Action} ) { 633 634 # remove last screen 635 $LastScreen = pop @{ $Self->{ScreensPath} }; 636 } 637 } 638 else { 639 640 # remove last screen 641 $LastScreen = pop @{ $Self->{ScreensPath} }; 642 } 643 644 # convert screens path to string (JSON) 645 my $JSONScreensPath = $Kernel::OM->Get('Kernel::Output::HTML::Layout')->JSONEncode( 646 Data => $Self->{ScreensPath}, 647 ); 648 649 # update session 650 $Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID( 651 SessionID => $Self->{SessionID}, 652 Key => 'ProcessManagementScreensPath', 653 Value => $JSONScreensPath, 654 ); 655 656 return $LastScreen; 657} 658 659sub _PushSessionScreen { 660 my ( $Self, %Param ) = @_; 661 662 # add screen to the screen path 663 push @{ $Self->{ScreensPath} }, { 664 Action => $Self->{Action} || '', 665 Subaction => $Param{Subaction}, 666 ID => $Param{ID}, 667 EntityID => $Param{EntityID}, 668 }; 669 670 # convert screens path to string (JSON) 671 my $JSONScreensPath = $Kernel::OM->Get('Kernel::Output::HTML::Layout')->JSONEncode( 672 Data => $Self->{ScreensPath}, 673 ); 674 675 # update session 676 $Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID( 677 SessionID => $Self->{SessionID}, 678 Key => 'ProcessManagementScreensPath', 679 Value => $JSONScreensPath, 680 ); 681 682 return 1; 683} 684 685sub _PopupResponse { 686 my ( $Self, %Param ) = @_; 687 688 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 689 690 if ( $Param{Redirect} && $Param{Redirect} eq 1 ) { 691 692 # send data to JS 693 $LayoutObject->AddJSData( 694 Key => 'Redirect', 695 Value => { 696 ConfigJSON => $Param{ConfigJSON}, 697 %{ $Param{Screen} }, 698 } 699 ); 700 } 701 elsif ( $Param{ClosePopup} && $Param{ClosePopup} eq 1 ) { 702 703 # send data to JS 704 $LayoutObject->AddJSData( 705 Key => 'ClosePopup', 706 Value => { 707 ConfigJSON => $Param{ConfigJSON}, 708 } 709 ); 710 } 711 712 my $Output = $LayoutObject->Header( Type => 'Small' ); 713 $Output .= $LayoutObject->Output( 714 TemplateFile => "AdminProcessManagementPopupResponse", 715 Data => {}, 716 ); 717 $Output .= $LayoutObject->Footer( Type => 'Small' ); 718 719 return $Output; 720} 721 722sub _CheckTransitionActionUsage { 723 my ( $Self, %Param ) = @_; 724 725 # get a list of parents with all the details 726 my $List = $Kernel::OM->Get('Kernel::System::ProcessManagement::DB::Process')->ProcessListGet( 727 UserID => 1, 728 ); 729 730 my @Usage; 731 732 # search entity id in all parents 733 PARENT: 734 for my $ParentData ( @{$List} ) { 735 next PARENT if !$ParentData; 736 next PARENT if !$ParentData->{TransitionActions}; 737 ENTITY: 738 for my $EntityID ( @{ $ParentData->{TransitionActions} } ) { 739 if ( $EntityID eq $Param{EntityID} ) { 740 push @Usage, $ParentData->{Name}; 741 last ENTITY; 742 } 743 } 744 } 745 746 return \@Usage; 747} 748 7491; 750