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::System::GenericAgent; 10 11use strict; 12use warnings; 13 14use Time::HiRes qw(usleep); 15 16use Kernel::System::VariableCheck qw(:all); 17 18our @ObjectDependencies = ( 19 'Kernel::Config', 20 'Kernel::System::Cache', 21 'Kernel::System::DateTime', 22 'Kernel::System::DB', 23 'Kernel::System::DynamicField', 24 'Kernel::System::DynamicField::Backend', 25 'Kernel::System::Log', 26 'Kernel::System::Main', 27 'Kernel::System::Queue', 28 'Kernel::System::State', 29 'Kernel::System::Ticket', 30 'Kernel::System::Ticket::Article', 31 'Kernel::System::TemplateGenerator', 32 'Kernel::System::CustomerUser', 33); 34 35=head1 NAME 36 37Kernel::System::GenericAgent - to manage the generic agent jobs 38 39=head1 DESCRIPTION 40 41All functions to manage the generic agent and the generic agent jobs. 42 43=head1 PUBLIC INTERFACE 44 45=head2 new() 46 47Don't use the constructor directly, use the ObjectManager instead: 48 49 my $GenericAgentObject = $Kernel::OM->Get('Kernel::System::GenericAgent'); 50 51=cut 52 53sub new { 54 my ( $Type, %Param ) = @_; 55 56 # allocate new hash for object 57 my $Self = {}; 58 bless( $Self, $Type ); 59 60 # get dynamic field objects 61 my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField'); 62 my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); 63 64 # get the dynamic fields for ticket object 65 $Self->{DynamicField} = $DynamicFieldObject->DynamicFieldListGet( 66 Valid => 1, 67 ObjectType => ['Ticket'], 68 ); 69 70 # debug 71 $Self->{Debug} = $Param{Debug} || 0; 72 73 # notice on STDOUT 74 $Self->{NoticeSTDOUT} = $Param{NoticeSTDOUT} || 0; 75 76 my %Map = ( 77 TicketNumber => 'SCALAR', 78 Title => 'SCALAR', 79 MIMEBase_From => 'SCALAR', 80 MIMEBase_To => 'SCALAR', 81 MIMEBase_Cc => 'SCALAR', 82 MIMEBase_Subject => 'SCALAR', 83 MIMEBase_Body => 'SCALAR', 84 TimeUnit => 'SCALAR', 85 CustomerID => 'SCALAR', 86 CustomerUserLogin => 'SCALAR', 87 Agent => 'SCALAR', 88 StateIDs => 'ARRAY', 89 StateTypeIDs => 'ARRAY', 90 QueueIDs => 'ARRAY', 91 PriorityIDs => 'ARRAY', 92 OwnerIDs => 'ARRAY', 93 LockIDs => 'ARRAY', 94 TypeIDs => 'ARRAY', 95 ResponsibleIDs => 'ARRAY', 96 ServiceIDs => 'ARRAY', 97 SLAIDs => 'ARRAY', 98 NewTitle => 'SCALAR', 99 NewCustomerID => 'SCALAR', 100 NewCustomerUserLogin => 'SCALAR', 101 NewStateID => 'SCALAR', 102 NewQueueID => 'SCALAR', 103 NewPriorityID => 'SCALAR', 104 NewOwnerID => 'SCALAR', 105 NewLockID => 'SCALAR', 106 NewTypeID => 'SCALAR', 107 NewResponsibleID => 'SCALAR', 108 NewServiceID => 'SCALAR', 109 NewSLAID => 'SCALAR', 110 ScheduleLastRun => 'SCALAR', 111 ScheduleLastRunUnixTime => 'SCALAR', 112 Valid => 'SCALAR', 113 ScheduleDays => 'ARRAY', 114 ScheduleMinutes => 'ARRAY', 115 ScheduleHours => 'ARRAY', 116 EventValues => 'ARRAY', 117 ); 118 119 # add time attributes 120 for my $Type ( 121 qw(Time ChangeTime CloseTime TimePending EscalationTime EscalationResponseTime EscalationUpdateTime EscalationSolutionTime) 122 ) 123 { 124 my $Key = $Type . 'SearchType'; 125 $Map{$Key} = 'SCALAR'; 126 } 127 for my $Type ( 128 qw(TicketCreate TicketChange TicketClose TicketLastChange TicketLastClose TicketPending TicketEscalation TicketEscalationResponse TicketEscalationUpdate TicketEscalationSolution) 129 ) 130 { 131 for my $Attribute ( 132 qw(PointFormat Point PointStart Start StartDay StartMonth StartYear Stop StopDay StopMonth StopYear) 133 ) 134 { 135 my $Key = $Type . 'Time' . $Attribute; 136 $Map{$Key} = 'SCALAR'; 137 } 138 } 139 140 # Add Dynamic Fields attributes 141 DYNAMICFIELD: 142 for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) { 143 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 144 145 # get the field type of the dynamic fields for edit and search 146 my $FieldValueType = $DynamicFieldBackendObject->TemplateValueTypeGet( 147 DynamicFieldConfig => $DynamicFieldConfig, 148 FieldType => 'All', 149 ); 150 151 # Add field type to Map 152 if ( IsHashRefWithData($FieldValueType) ) { 153 for my $FieldName ( sort keys %{$FieldValueType} ) { 154 $Map{$FieldName} = $FieldValueType->{$FieldName}; 155 } 156 } 157 } 158 159 $Self->{Map} = \%Map; 160 161 return $Self; 162} 163 164=head2 JobRun() 165 166run a generic agent job 167 168 $GenericAgentObject->JobRun( 169 Job => 'JobName', 170 OnlyTicketID => 123, # (optional) for event based Job execution 171 SleepTime => 100_000 # (optional) sleeptime per ticket in microseconds 172 UserID => 1, 173 ); 174 175=cut 176 177sub JobRun { 178 my ( $Self, %Param ) = @_; 179 180 # check needed stuff 181 for (qw(Job UserID)) { 182 if ( !$Param{$_} ) { 183 $Kernel::OM->Get('Kernel::System::Log')->Log( 184 Priority => 'error', 185 Message => "Need $_!" 186 ); 187 return; 188 } 189 } 190 if ( $Self->{NoticeSTDOUT} ) { 191 print "Job: '$Param{Job}'\n"; 192 } 193 194 # get job from param 195 my %Job; 196 my %DynamicFieldSearchTemplate; 197 if ( $Param{Config} ) { 198 %Job = %{ $Param{Config} }; 199 200 # log event 201 $Kernel::OM->Get('Kernel::System::Log')->Log( 202 Priority => 'notice', 203 Message => "Run GenericAgent Job '$Param{Job}' from config file.", 204 ); 205 } 206 207 # get db job 208 else { 209 210 # log event 211 $Kernel::OM->Get('Kernel::System::Log')->Log( 212 Priority => 'notice', 213 Message => "Run GenericAgent Job '$Param{Job}' from db.", 214 ); 215 216 # get job data 217 my %DBJobRaw = $Self->JobGet( Name => $Param{Job} ); 218 219 # updated last run time 220 $Self->_JobUpdateRunTime( 221 Name => $Param{Job}, 222 UserID => $Param{UserID} 223 ); 224 225 # rework 226 for my $Key ( sort keys %DBJobRaw ) { 227 if ( $Key =~ /^New/ ) { 228 my $NewKey = $Key; 229 $NewKey =~ s/^New//; 230 $Job{New}->{$NewKey} = $DBJobRaw{$Key}; 231 } 232 else { 233 234 # skip dynamic fields 235 if ( $Key !~ m{ DynamicField_ }xms ) { 236 $Job{$Key} = $DBJobRaw{$Key}; 237 } 238 } 239 240 # convert dynamic fields 241 if ( $Key =~ m{ \A DynamicField_ }xms ) { 242 $Job{New}->{$Key} = $DBJobRaw{$Key}; 243 } 244 elsif ( $Key =~ m{ \A Search_DynamicField_ }xms ) { 245 $DynamicFieldSearchTemplate{$Key} = $DBJobRaw{$Key}; 246 } 247 } 248 249 # Pass module parameters directly to the module in %Param, 250 # but don't overwrite existing keys 251 for my $Counter ( 1 .. 6 ) { 252 if ( $Job{New}->{"ParamKey$Counter"} ) { 253 $Job{New}->{ $Job{New}->{"ParamKey$Counter"} } //= $Job{New}->{"ParamValue$Counter"}; 254 } 255 } 256 257 if ( exists $Job{SearchInArchive} && $Job{SearchInArchive} eq 'ArchivedTickets' ) { 258 $Job{ArchiveFlags} = ['y']; 259 } 260 if ( exists $Job{SearchInArchive} && $Job{SearchInArchive} eq 'AllTickets' ) { 261 $Job{ArchiveFlags} = [ 'y', 'n' ]; 262 } 263 } 264 265 # get dynamic field backend objects 266 my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); 267 268 # set dynamic fields search parameters 269 my %DynamicFieldSearchParameters; 270 DYNAMICFIELD: 271 for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) { 272 273 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 274 275 # get search field preferences 276 my $SearchFieldPreferences = $DynamicFieldBackendObject->SearchFieldPreferences( 277 DynamicFieldConfig => $DynamicFieldConfig, 278 ); 279 280 next DYNAMICFIELD if !IsArrayRefWithData($SearchFieldPreferences); 281 282 PREFERENCE: 283 for my $Preference ( @{$SearchFieldPreferences} ) { 284 285 my $DynamicFieldTemp = $DynamicFieldSearchTemplate{ 286 'Search_DynamicField_' 287 . $DynamicFieldConfig->{Name} 288 . $Preference->{Type} 289 }; 290 291 next PREFERENCE if !defined $DynamicFieldTemp; 292 293 # extract the dynamic field value from the profile 294 my $SearchParameter = $DynamicFieldBackendObject->SearchFieldParameterBuild( 295 DynamicFieldConfig => $DynamicFieldConfig, 296 Profile => \%DynamicFieldSearchTemplate, 297 Type => $Preference->{Type}, 298 ); 299 300 # set search parameter 301 if ( defined $SearchParameter ) { 302 $DynamicFieldSearchParameters{ 'DynamicField_' . $DynamicFieldConfig->{Name} } 303 = $SearchParameter->{Parameter}; 304 } 305 } 306 } 307 308 if ( $Param{OnlyTicketID} ) { 309 $Job{TicketID} = $Param{OnlyTicketID}; 310 } 311 312 # get needed objects 313 my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket'); 314 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 315 316 # escalation tickets 317 my %Tickets; 318 319 # get ticket limit on job run 320 my $RunLimit = $ConfigObject->Get('Ticket::GenericAgentRunLimit'); 321 if ( $Job{Escalation} ) { 322 323 # Find all tickets which will escalate within the next five days. 324 # The notification module will determine if a notification must be sent out or not. 325 my @Tickets = $TicketObject->TicketSearch( 326 %Job, 327 Result => 'ARRAY', 328 Limit => $Job{Limit} || $Param{Limit} || 100, 329 TicketEscalationTimeOlderMinutes => $Job{TicketEscalationTimeOlderMinutes} 330 || -( 5 * 24 * 60 ), 331 Permission => 'rw', 332 UserID => $Param{UserID} || 1, 333 ); 334 335 for (@Tickets) { 336 if ( !$Job{Queue} ) { 337 $Tickets{$_} = $TicketObject->TicketNumberLookup( TicketID => $_ ); 338 } 339 else { 340 my %Ticket = $TicketObject->TicketGet( 341 TicketID => $_, 342 DynamicFields => 0, 343 ); 344 if ( $Ticket{Queue} eq $Job{Queue} ) { 345 $Tickets{$_} = $Ticket{TicketNumber}; 346 } 347 } 348 } 349 } 350 351 # pending tickets 352 elsif ( $Job{PendingReminder} || $Job{PendingAuto} ) { 353 my $Type = ''; 354 if ( $Job{PendingReminder} ) { 355 $Type = 'PendingReminder'; 356 } 357 else { 358 $Type = 'PendingAuto'; 359 } 360 if ( !$Job{Queue} ) { 361 %Tickets = ( 362 $TicketObject->TicketSearch( 363 %Job, 364 %DynamicFieldSearchParameters, 365 ConditionInline => 1, 366 StateType => $Type, 367 Limit => $Param{Limit} || $RunLimit, 368 UserID => $Param{UserID}, 369 ), 370 %Tickets 371 ); 372 } 373 elsif ( ref $Job{Queue} eq 'ARRAY' ) { 374 for ( @{ $Job{Queue} } ) { 375 if ( $Self->{NoticeSTDOUT} ) { 376 print " For Queue: $_\n"; 377 } 378 %Tickets = ( 379 $TicketObject->TicketSearch( 380 %Job, 381 %DynamicFieldSearchParameters, 382 ConditionInline => 1, 383 Queues => [$_], 384 StateType => $Type, 385 Limit => $Param{Limit} || $RunLimit, 386 UserID => $Param{UserID}, 387 ), 388 %Tickets 389 ); 390 } 391 } 392 else { 393 %Tickets = ( 394 $TicketObject->TicketSearch( 395 %Job, 396 %DynamicFieldSearchParameters, 397 ConditionInline => 1, 398 StateType => $Type, 399 Queues => [ $Job{Queue} ], 400 Limit => $Param{Limit} || $RunLimit, 401 UserID => $Param{UserID}, 402 ), 403 %Tickets 404 ); 405 } 406 for ( sort keys %Tickets ) { 407 my %Ticket = $TicketObject->TicketGet( 408 TicketID => $_, 409 DynamicFields => 0, 410 ); 411 if ( $Ticket{UntilTime} > 1 ) { 412 delete $Tickets{$_}; 413 } 414 } 415 } 416 417 # get regular tickets 418 else { 419 if ( !$Job{Queue} ) { 420 421 # check min. one search arg 422 my $Count = 0; 423 for ( sort keys %Job ) { 424 if ( $_ !~ /^(New|Name|Valid|Schedule|Event)/ && $Job{$_} ) { 425 $Count++; 426 } 427 } 428 429 # also search in Dynamic fields search attributes 430 for my $DynamicFieldName ( sort keys %DynamicFieldSearchParameters ) { 431 $Count++; 432 } 433 434 # log no search attribute 435 if ( !$Count ) { 436 $Kernel::OM->Get('Kernel::System::Log')->Log( 437 Priority => 'error', 438 Message => "Attention: Can't run GenericAgent Job '$Param{Job}' because no " 439 . "search attributes are used!.", 440 ); 441 return; 442 } 443 444 # search tickets 445 if ( $Self->{NoticeSTDOUT} ) { 446 print " For all Queues: \n"; 447 } 448 my $GenericAgentTicketSearch = $ConfigObject->Get("Ticket::GenericAgentTicketSearch") || {}; 449 %Tickets = $TicketObject->TicketSearch( 450 %Job, 451 %DynamicFieldSearchParameters, 452 ConditionInline => $GenericAgentTicketSearch->{ExtendedSearchCondition}, 453 Limit => $Param{Limit} || $RunLimit, 454 UserID => $Param{UserID}, 455 ); 456 } 457 elsif ( ref $Job{Queue} eq 'ARRAY' ) { 458 for ( @{ $Job{Queue} } ) { 459 if ( $Self->{NoticeSTDOUT} ) { 460 print " For Queue: $_\n"; 461 } 462 %Tickets = ( 463 $TicketObject->TicketSearch( 464 %Job, 465 %DynamicFieldSearchParameters, 466 ConditionInline => 1, 467 Queues => [$_], 468 Limit => $Param{Limit} || $RunLimit, 469 UserID => $Param{UserID}, 470 ), 471 %Tickets 472 ); 473 } 474 } 475 else { 476 %Tickets = $TicketObject->TicketSearch( 477 %Job, 478 %DynamicFieldSearchParameters, 479 ConditionInline => 1, 480 Queues => [ $Job{Queue} ], 481 Limit => $Param{Limit} || $RunLimit, 482 UserID => $Param{UserID}, 483 ); 484 } 485 } 486 487 # process each ticket 488 TICKETID: 489 for my $TicketID ( sort keys %Tickets ) { 490 491 $Self->_JobRunTicket( 492 Config => \%Job, 493 Job => $Param{Job}, 494 TicketID => $TicketID, 495 TicketNumber => $Tickets{$TicketID}, 496 UserID => $Param{UserID}, 497 ); 498 499 next TICKETID if !$Param{SleepTime}; 500 501 Time::HiRes::usleep( $Param{SleepTime} ); 502 } 503 504 return 1; 505} 506 507=head2 JobList() 508 509returns a hash of jobs 510 511 my %List = $GenericAgentObject->JobList(); 512 513=cut 514 515sub JobList { 516 my ( $Self, %Param ) = @_; 517 518 # get cache object 519 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 520 521 # check cache 522 my $CacheKey = "JobList"; 523 my $Cache = $CacheObject->Get( 524 Type => 'GenericAgent', 525 Key => $CacheKey, 526 ); 527 return %{$Cache} if ref $Cache; 528 529 # get database object 530 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 531 532 return if !$DBObject->Prepare( 533 SQL => 'SELECT DISTINCT(job_name) FROM generic_agent_jobs', 534 ); 535 536 my %Data; 537 while ( my @Row = $DBObject->FetchrowArray() ) { 538 $Data{ $Row[0] } = $Row[0]; 539 } 540 541 $CacheObject->Set( 542 Type => 'GenericAgent', 543 Key => $CacheKey, 544 Value => \%Data, 545 TTL => 24 * 60 * 60, 546 ); 547 548 return %Data; 549} 550 551=head2 JobGet() 552 553returns a hash of the job data 554 555 my %Job = $GenericAgentObject->JobGet(Name => 'JobName'); 556 557=cut 558 559sub JobGet { 560 my ( $Self, %Param ) = @_; 561 562 # check needed stuff 563 for (qw(Name)) { 564 if ( !$Param{$_} ) { 565 $Kernel::OM->Get('Kernel::System::Log')->Log( 566 Priority => 'error', 567 Message => "Need $_!" 568 ); 569 return; 570 } 571 } 572 573 # get cache object 574 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 575 576 # check cache 577 my $CacheKey = 'JobGet::' . $Param{Name}; 578 my $Cache = $CacheObject->Get( 579 Type => 'GenericAgent', 580 Key => $CacheKey, 581 ); 582 return %{$Cache} if ref $Cache; 583 584 # get database object 585 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 586 587 return if !$DBObject->Prepare( 588 SQL => ' 589 SELECT job_key, job_value 590 FROM generic_agent_jobs 591 WHERE job_name = ?', 592 Bind => [ \$Param{Name} ], 593 ); 594 595 my %Data; 596 while ( my @Row = $DBObject->FetchrowArray() ) { 597 if ( $Self->{Map}->{ $Row[0] } && $Self->{Map}->{ $Row[0] } eq 'ARRAY' ) { 598 push @{ $Data{ $Row[0] } }, $Row[1]; 599 } 600 else { 601 $Data{ $Row[0] } = $Row[1]; 602 } 603 } 604 605 # get time settings 606 my %Map = ( 607 TicketCreate => 'Time', 608 TicketChange => 'ChangeTime', 609 TicketClose => 'CloseTime', 610 TicketLastChange => 'LastChangeTime', 611 TicketLastClose => 'LastCloseTime', 612 TicketPending => 'TimePending', 613 TicketEscalation => 'EscalationTime', 614 TicketEscalationResponse => 'EscalationResponseTime', 615 TicketEscalationUpdate => 'EscalationUpdateTime', 616 TicketEscalationSolution => 'EscalationSolutionTime', 617 ); 618 619 for my $Type ( 620 qw(TicketCreate TicketChange TicketClose TicketLastChange TicketLastClose TicketPending TicketEscalation TicketEscalationResponse TicketEscalationUpdate TicketEscalationSolution) 621 ) 622 { 623 my $SearchType = $Map{$Type} . 'SearchType'; 624 625 if ( !$Data{$SearchType} || $Data{$SearchType} eq 'None' ) { 626 627 # do nothing on time stuff 628 for ( 629 qw(TimeStartMonth TimeStopMonth TimeStopDay 630 TimeStartDay TimeStopYear TimePoint 631 TimeStartYear TimePointFormat TimePointStart) 632 ) 633 { 634 delete $Data{ $Type . $_ }; 635 } 636 } 637 elsif ( $Data{$SearchType} && $Data{$SearchType} eq 'TimeSlot' ) { 638 for (qw(TimePoint TimePointFormat TimePointStart)) { 639 delete $Data{ $Type . $_ }; 640 } 641 for (qw(Month Day)) { 642 $Data{ $Type . "TimeStart$_" } = sprintf( '%02d', $Data{ $Type . "TimeStart$_" } ); 643 $Data{ $Type . "TimeStop$_" } = sprintf( '%02d', $Data{ $Type . "TimeStop$_" } ); 644 } 645 if ( 646 $Data{ $Type . 'TimeStartDay' } 647 && $Data{ $Type . 'TimeStartMonth' } 648 && $Data{ $Type . 'TimeStartYear' } 649 ) 650 { 651 $Data{ $Type . 'TimeNewerDate' } = $Data{ $Type . 'TimeStartYear' } . '-' 652 . $Data{ $Type . 'TimeStartMonth' } . '-' 653 . $Data{ $Type . 'TimeStartDay' } 654 . ' 00:00:01'; 655 } 656 if ( 657 $Data{ $Type . 'TimeStopDay' } 658 && $Data{ $Type . 'TimeStopMonth' } 659 && $Data{ $Type . 'TimeStopYear' } 660 ) 661 { 662 $Data{ $Type . 'TimeOlderDate' } = $Data{ $Type . 'TimeStopYear' } . '-' 663 . $Data{ $Type . 'TimeStopMonth' } . '-' 664 . $Data{ $Type . 'TimeStopDay' } 665 . ' 23:59:59'; 666 } 667 } 668 elsif ( $Data{$SearchType} && $Data{$SearchType} eq 'TimePoint' ) { 669 for ( 670 qw(TimeStartMonth TimeStopMonth TimeStopDay 671 TimeStartDay TimeStopYear TimeStartYear) 672 ) 673 { 674 delete $Data{ $Type . $_ }; 675 } 676 if ( 677 $Data{ $Type . 'TimePoint' } 678 && $Data{ $Type . 'TimePointStart' } 679 && $Data{ $Type . 'TimePointFormat' } 680 ) 681 { 682 my $Time = 0; 683 if ( $Data{ $Type . 'TimePointFormat' } eq 'minute' ) { 684 $Time = $Data{ $Type . 'TimePoint' }; 685 } 686 elsif ( $Data{ $Type . 'TimePointFormat' } eq 'hour' ) { 687 $Time = $Data{ $Type . 'TimePoint' } * 60; 688 } 689 elsif ( $Data{ $Type . 'TimePointFormat' } eq 'day' ) { 690 $Time = $Data{ $Type . 'TimePoint' } * 60 * 24; 691 } 692 elsif ( $Data{ $Type . 'TimePointFormat' } eq 'week' ) { 693 $Time = $Data{ $Type . 'TimePoint' } * 60 * 24 * 7; 694 } 695 elsif ( $Data{ $Type . 'TimePointFormat' } eq 'month' ) { 696 $Time = $Data{ $Type . 'TimePoint' } * 60 * 24 * 30; 697 } 698 elsif ( $Data{ $Type . 'TimePointFormat' } eq 'year' ) { 699 $Time = $Data{ $Type . 'TimePoint' } * 60 * 24 * 365; 700 } 701 if ( $Data{ $Type . 'TimePointStart' } eq 'Before' ) { 702 703 # more than ... ago 704 $Data{ $Type . 'TimeOlderMinutes' } = $Time; 705 } 706 elsif ( $Data{ $Type . 'TimePointStart' } eq 'Next' ) { 707 708 # within the next ... 709 $Data{ $Type . 'TimeNewerMinutes' } = 0; 710 $Data{ $Type . 'TimeOlderMinutes' } = -$Time; 711 } 712 else { 713 714 # within the last ... 715 $Data{ $Type . 'TimeOlderMinutes' } = 0; 716 $Data{ $Type . 'TimeNewerMinutes' } = $Time; 717 } 718 } 719 } 720 } 721 722 # check valid 723 if ( %Data && !defined $Data{Valid} ) { 724 $Data{Valid} = 1; 725 } 726 if (%Data) { 727 $Data{Name} = $Param{Name}; 728 } 729 730 $CacheObject->Set( 731 Type => 'GenericAgent', 732 Key => $CacheKey, 733 Value => \%Data, 734 TTL => 24 * 60 * 60, 735 ); 736 737 return %Data; 738} 739 740=head2 JobAdd() 741 742adds a new job to the database 743 744 $GenericAgentObject->JobAdd( 745 Name => 'JobName', 746 Data => { 747 Queue => 'SomeQueue', 748 ... 749 Valid => 1, 750 }, 751 UserID => 123, 752 ); 753 754=cut 755 756sub JobAdd { 757 my ( $Self, %Param ) = @_; 758 759 # check needed stuff 760 for (qw(Name Data UserID)) { 761 if ( !$Param{$_} ) { 762 $Kernel::OM->Get('Kernel::System::Log')->Log( 763 Priority => 'error', 764 Message => "Need $_!" 765 ); 766 return; 767 } 768 } 769 770 # check if job name already exists 771 my %Check = $Self->JobGet( Name => $Param{Name} ); 772 if (%Check) { 773 $Kernel::OM->Get('Kernel::System::Log')->Log( 774 Priority => 'error', 775 Message => "A job with the name '$Param{Name}' already exists.", 776 ); 777 return; 778 } 779 780 # get database object 781 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 782 783 # insert data into db 784 for my $Key ( sort keys %{ $Param{Data} } ) { 785 if ( ref $Param{Data}->{$Key} eq 'ARRAY' ) { 786 for my $Item ( @{ $Param{Data}->{$Key} } ) { 787 if ( defined $Item ) { 788 $DBObject->Do( 789 SQL => 'INSERT INTO generic_agent_jobs ' 790 . '(job_name, job_key, job_value) VALUES (?, ?, ?)', 791 Bind => [ \$Param{Name}, \$Key, \$Item ], 792 ); 793 } 794 } 795 } 796 else { 797 if ( defined $Param{Data}->{$Key} ) { 798 $DBObject->Do( 799 SQL => 'INSERT INTO generic_agent_jobs ' 800 . '(job_name, job_key, job_value) VALUES (?, ?, ?)', 801 Bind => [ \$Param{Name}, \$Key, \$Param{Data}->{$Key} ], 802 ); 803 } 804 } 805 } 806 807 $Kernel::OM->Get('Kernel::System::Log')->Log( 808 Priority => 'notice', 809 Message => "New GenericAgent job '$Param{Name}' added (UserID=$Param{UserID}).", 810 ); 811 812 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 813 Type => 'GenericAgent', 814 ); 815 816 return 1; 817} 818 819=head2 JobDelete() 820 821deletes a job from the database 822 823 my $Success = $GenericAgentObject->JobDelete( 824 Name => 'JobName', 825 UserID => 123, 826 ); 827 828returns: 829 830 $Success = 1; # or false in case of a failure 831 832=cut 833 834sub JobDelete { 835 my ( $Self, %Param ) = @_; 836 837 # check needed stuff 838 for (qw(Name UserID)) { 839 if ( !$Param{$_} ) { 840 $Kernel::OM->Get('Kernel::System::Log')->Log( 841 Priority => 'error', 842 Message => "Need $_!" 843 ); 844 return; 845 } 846 } 847 848 # delete job 849 $Kernel::OM->Get('Kernel::System::DB')->Do( 850 SQL => 'DELETE FROM generic_agent_jobs WHERE job_name = ?', 851 Bind => [ \$Param{Name} ], 852 ); 853 854 $Kernel::OM->Get('Kernel::System::Log')->Log( 855 Priority => 'notice', 856 Message => "GenericAgent job '$Param{Name}' deleted (UserID=$Param{UserID}).", 857 ); 858 859 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 860 Type => 'GenericAgent', 861 ); 862 863 return 1; 864} 865 866=head2 JobEventList() 867 868returns a hash of events for each job 869 870 my %List = $GenericAgentObject->JobEventList(); 871 872=cut 873 874sub JobEventList { 875 my ( $Self, %Param ) = @_; 876 877 # get cache object 878 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 879 880 # check cache 881 my $CacheKey = "JobEventList"; 882 my $Cache = $CacheObject->Get( 883 Type => 'GenericAgent', 884 Key => $CacheKey, 885 ); 886 return %{$Cache} if ref $Cache; 887 888 my %JobList = $Self->JobList(); 889 my %Data; 890 JOB_NAME: 891 for my $JobName ( sort keys %JobList ) { 892 my %Job = $Self->JobGet( Name => $JobName ); 893 next JOB_NAME if !$Job{Valid}; 894 $Data{$JobName} = $Job{EventValues}; 895 } 896 897 $CacheObject->Set( 898 Type => 'GenericAgent', 899 Key => $CacheKey, 900 Value => \%Data, 901 TTL => 24 * 60 * 60, 902 ); 903 904 return %Data; 905} 906 907=begin Internal: 908 909=cut 910 911=head2 _JobRunTicket() 912 913run a generic agent job on a ticket 914 915 $GenericAgentObject->_JobRunTicket( 916 TicketID => 123, 917 TicketNumber => '2004081400001', 918 Config => { 919 %Job, 920 }, 921 UserID => 1, 922 ); 923 924=cut 925 926sub _JobRunTicket { 927 my ( $Self, %Param ) = @_; 928 929 # check needed stuff 930 for (qw(TicketID TicketNumber Config UserID)) { 931 if ( !$Param{$_} ) { 932 $Kernel::OM->Get('Kernel::System::Log')->Log( 933 Priority => 'error', 934 Message => "Need $_!" 935 ); 936 return; 937 } 938 } 939 940 # get ticket object 941 my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket'); 942 943 my $Ticket = "($Param{TicketNumber}/$Param{TicketID})"; 944 945 # disable sending emails 946 $TicketObject->{SendNoNotification} = $Param{Config}->{New}->{SendNoNotification} ? 1 : 0; 947 948 # move ticket 949 if ( $Param{Config}->{New}->{Queue} ) { 950 if ( $Self->{NoticeSTDOUT} ) { 951 print " - Move Ticket $Ticket to Queue '$Param{Config}->{New}->{Queue}'\n"; 952 } 953 $TicketObject->TicketQueueSet( 954 QueueID => $Kernel::OM->Get('Kernel::System::Queue')->QueueLookup( 955 Queue => $Param{Config}->{New}->{Queue}, 956 Cache => 1, 957 ), 958 UserID => $Param{UserID}, 959 TicketID => $Param{TicketID}, 960 ); 961 } 962 if ( $Param{Config}->{New}->{QueueID} ) { 963 if ( $Self->{NoticeSTDOUT} ) { 964 print " - Move Ticket $Ticket to QueueID '$Param{Config}->{New}->{QueueID}'\n"; 965 } 966 $TicketObject->TicketQueueSet( 967 QueueID => $Param{Config}->{New}->{QueueID}, 968 UserID => $Param{UserID}, 969 TicketID => $Param{TicketID}, 970 ); 971 } 972 973 my $ContentType = 'text/plain'; 974 975 # add note if wanted 976 if ( $Param{Config}->{New}->{Note}->{Body} || $Param{Config}->{New}->{NoteBody} ) { 977 if ( $Self->{NoticeSTDOUT} ) { 978 print " - Add note to Ticket $Ticket\n"; 979 } 980 981 my %Ticket = $TicketObject->TicketGet( 982 TicketID => $Param{TicketID}, 983 DynamicFields => 0, 984 ); 985 986 if ( IsHashRefWithData( \%Ticket ) ) { 987 988 my %CustomerUserData = {}; 989 if ( IsStringWithData( $Ticket{CustomerUserID} ) ) { 990 %CustomerUserData = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserDataGet( 991 User => $Ticket{CustomerUserID}, 992 ); 993 } 994 995 my %Notification = ( 996 Subject => $Param{Config}->{New}->{NoteSubject}, 997 Body => $Param{Config}->{New}->{NoteBody}, 998 ContentType => 'text/plain', 999 ); 1000 1001 my %GenericAgentArticle = $Kernel::OM->Get('Kernel::System::TemplateGenerator')->GenericAgentArticle( 1002 TicketID => $Param{TicketID}, 1003 Recipient => \%CustomerUserData, 1004 Notification => \%Notification, 1005 UserID => $Param{UserID}, 1006 ); 1007 1008 if ( 1009 IsStringWithData( $GenericAgentArticle{Body} ) 1010 || IsHashRefWithData( $GenericAgentArticle{Subject} ) 1011 ) 1012 { 1013 $Param{Config}->{New}->{Note}->{Subject} = $GenericAgentArticle{Subject} || ''; 1014 $Param{Config}->{New}->{Note}->{Body} = $GenericAgentArticle{Body} || ''; 1015 $ContentType = $GenericAgentArticle{ContentType}; 1016 } 1017 } 1018 1019 my $ArticleBackendObject = $Kernel::OM->Get('Kernel::System::Ticket::Article')->BackendForChannel( 1020 ChannelName => 'Internal', 1021 ); 1022 1023 my $ArticleID = $ArticleBackendObject->ArticleCreate( 1024 TicketID => $Param{TicketID}, 1025 SenderType => 'agent', 1026 IsVisibleForCustomer => $Param{Config}->{New}->{Note}->{IsVisibleForCustomer} 1027 // $Param{Config}->{New}->{NoteIsVisibleForCustomer} 1028 // 0, 1029 From => $Param{Config}->{New}->{Note}->{From} 1030 || $Param{Config}->{New}->{NoteFrom} 1031 || 'GenericAgent', 1032 Subject => $Param{Config}->{New}->{Note}->{Subject} 1033 || $Param{Config}->{New}->{NoteSubject} 1034 || 'Note', 1035 Body => $Param{Config}->{New}->{Note}->{Body} || $Param{Config}->{New}->{NoteBody}, 1036 MimeType => $ContentType, 1037 Charset => 'utf-8', 1038 UserID => $Param{UserID}, 1039 HistoryType => 'AddNote', 1040 HistoryComment => 'Generic Agent note added.', 1041 NoAgentNotify => $Param{Config}->{New}->{SendNoNotification} || 0, 1042 ); 1043 my $TimeUnits = $Param{Config}->{New}->{Note}->{TimeUnits} 1044 || $Param{Config}->{New}->{NoteTimeUnits}; 1045 if ( $ArticleID && $TimeUnits ) { 1046 $TicketObject->TicketAccountTime( 1047 TicketID => $Param{TicketID}, 1048 ArticleID => $ArticleID, 1049 TimeUnit => $TimeUnits, 1050 UserID => $Param{UserID}, 1051 ); 1052 } 1053 } 1054 1055 my %PendingStates = $Kernel::OM->Get('Kernel::System::State')->StateGetStatesByType( 1056 StateType => [ 'pending auto', 'pending reminder' ], 1057 Result => 'HASH', 1058 ); 1059 1060 $Self->{PendingStateList} = \%PendingStates || {}; 1061 1062 # set new state 1063 my $IsPendingState; 1064 if ( $Param{Config}->{New}->{State} ) { 1065 if ( $Self->{NoticeSTDOUT} ) { 1066 print " - changed state of Ticket $Ticket to '$Param{Config}->{New}->{State}'\n"; 1067 } 1068 $TicketObject->TicketStateSet( 1069 TicketID => $Param{TicketID}, 1070 UserID => $Param{UserID}, 1071 State => $Param{Config}->{New}->{State}, 1072 ); 1073 1074 $IsPendingState = grep { $_ eq $Param{Config}->{New}->{State} } values %{ $Self->{PendingStateList} }; 1075 } 1076 if ( $Param{Config}->{New}->{StateID} ) { 1077 if ( $Self->{NoticeSTDOUT} ) { 1078 print " - changed state id of ticket $Ticket to '$Param{Config}->{New}->{StateID}'\n"; 1079 } 1080 $TicketObject->TicketStateSet( 1081 TicketID => $Param{TicketID}, 1082 UserID => $Param{UserID}, 1083 StateID => $Param{Config}->{New}->{StateID}, 1084 ); 1085 1086 $IsPendingState = grep { $_ == $Param{Config}->{New}->{StateID} } keys %{ $Self->{PendingStateList} }; 1087 } 1088 1089 if ( 1090 $Param{Config}->{New}->{PendingTime} 1091 && !$Param{Config}->{New}->{State} 1092 && !$Param{Config}->{New}->{StateID} 1093 ) 1094 { 1095 # if pending time is provided, but there is no new ticket state provided, 1096 # check if ticket is already in pending state 1097 my %Ticket = $TicketObject->TicketGet( 1098 TicketID => $Param{TicketID}, 1099 DynamicFields => 0, 1100 ); 1101 1102 $IsPendingState = grep { $_ eq $Ticket{State} } values %{ $Self->{PendingStateList} }; 1103 } 1104 1105 # set pending time, if new state is pending state 1106 if ( $IsPendingState && $Param{Config}->{New}->{PendingTime} ) { 1107 1108 # pending time 1109 my $PendingTime = $Param{Config}->{New}->{PendingTime}; 1110 1111 # calculate pending time based on hours, minutes, years... 1112 if ( $Param{Config}->{New}->{PendingTimeType} ) { 1113 $PendingTime *= $Param{Config}->{New}->{PendingTimeType}; 1114 } 1115 1116 # add systemtime 1117 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 1118 $DateTimeObject->Add( Seconds => $PendingTime ); 1119 1120 # set pending time 1121 $TicketObject->TicketPendingTimeSet( 1122 Year => $DateTimeObject->Format( Format => '%Y' ), 1123 Month => $DateTimeObject->Format( Format => '%m' ), 1124 Day => $DateTimeObject->Format( Format => '%d' ), 1125 Hour => $DateTimeObject->Format( Format => '%H' ), 1126 Minute => $DateTimeObject->Format( Format => '%M' ), 1127 TicketID => $Param{TicketID}, 1128 UserID => $Param{UserID}, 1129 ); 1130 } 1131 1132 # set customer id and customer user 1133 if ( $Param{Config}->{New}->{CustomerID} || $Param{Config}->{New}->{CustomerUserLogin} ) { 1134 1135 # If CustomerID or CustomerUserID is updated but not both in same call, 1136 # keep original values for non updated ones. See bug#14864 (https://bugs.otrs.org/show_bug.cgi?id=14864). 1137 my %Ticket = $TicketObject->TicketGet( 1138 TicketID => $Param{TicketID}, 1139 DynamicFields => 0, 1140 ); 1141 1142 if ( $Param{Config}->{New}->{CustomerID} ) { 1143 if ( $Self->{NoticeSTDOUT} ) { 1144 print 1145 " - set customer id of Ticket $Ticket to '$Param{Config}->{New}->{CustomerID}'\n"; 1146 } 1147 } 1148 if ( $Param{Config}->{New}->{CustomerUserLogin} ) { 1149 if ( $Self->{NoticeSTDOUT} ) { 1150 print 1151 " - set customer user id of Ticket $Ticket to '$Param{Config}->{New}->{CustomerUserLogin}'\n"; 1152 } 1153 } 1154 $TicketObject->TicketCustomerSet( 1155 TicketID => $Param{TicketID}, 1156 No => $Param{Config}->{New}->{CustomerID} || $Ticket{CustomerID} || '', 1157 User => $Param{Config}->{New}->{CustomerUserLogin} || $Ticket{CustomerUserID} || '', 1158 UserID => $Param{UserID}, 1159 ); 1160 } 1161 1162 # set new title 1163 if ( $Param{Config}->{New}->{Title} ) { 1164 if ( $Self->{NoticeSTDOUT} ) { 1165 print " - set title of Ticket $Ticket to '$Param{Config}->{New}->{Title}'\n"; 1166 } 1167 $TicketObject->TicketTitleUpdate( 1168 Title => $Param{Config}->{New}->{Title}, 1169 TicketID => $Param{TicketID}, 1170 UserID => $Param{UserID}, 1171 ); 1172 } 1173 1174 # set new type 1175 if ( $Param{Config}->{New}->{Type} ) { 1176 if ( $Self->{NoticeSTDOUT} ) { 1177 print " - set type of Ticket $Ticket to '$Param{Config}->{New}->{Type}'\n"; 1178 } 1179 $TicketObject->TicketTypeSet( 1180 TicketID => $Param{TicketID}, 1181 UserID => $Param{UserID}, 1182 Type => $Param{Config}->{New}->{Type}, 1183 ); 1184 } 1185 if ( $Param{Config}->{New}->{TypeID} ) { 1186 if ( $Self->{NoticeSTDOUT} ) { 1187 print " - set type id of Ticket $Ticket to '$Param{Config}->{New}->{TypeID}'\n"; 1188 } 1189 $TicketObject->TicketTypeSet( 1190 TicketID => $Param{TicketID}, 1191 UserID => $Param{UserID}, 1192 TypeID => $Param{Config}->{New}->{TypeID}, 1193 ); 1194 } 1195 1196 # set new service 1197 if ( $Param{Config}->{New}->{Service} ) { 1198 if ( $Self->{NoticeSTDOUT} ) { 1199 print " - set service of Ticket $Ticket to '$Param{Config}->{New}->{Service}'\n"; 1200 } 1201 $TicketObject->TicketServiceSet( 1202 TicketID => $Param{TicketID}, 1203 UserID => $Param{UserID}, 1204 Service => $Param{Config}->{New}->{Service}, 1205 ); 1206 } 1207 if ( $Param{Config}->{New}->{ServiceID} ) { 1208 if ( $Self->{NoticeSTDOUT} ) { 1209 print " - set service id of Ticket $Ticket to '$Param{Config}->{New}->{ServiceID}'\n"; 1210 } 1211 $TicketObject->TicketServiceSet( 1212 TicketID => $Param{TicketID}, 1213 UserID => $Param{UserID}, 1214 ServiceID => $Param{Config}->{New}->{ServiceID}, 1215 ); 1216 } 1217 1218 # set new sla 1219 if ( $Param{Config}->{New}->{SLA} ) { 1220 if ( $Self->{NoticeSTDOUT} ) { 1221 print " - set sla of Ticket $Ticket to '$Param{Config}->{New}->{SLA}'\n"; 1222 } 1223 $TicketObject->TicketSLASet( 1224 TicketID => $Param{TicketID}, 1225 UserID => $Param{UserID}, 1226 SLA => $Param{Config}->{New}->{SLA}, 1227 ); 1228 } 1229 if ( $Param{Config}->{New}->{SLAID} ) { 1230 if ( $Self->{NoticeSTDOUT} ) { 1231 print " - set sla id of Ticket $Ticket to '$Param{Config}->{New}->{SLAID}'\n"; 1232 } 1233 $TicketObject->TicketSLASet( 1234 TicketID => $Param{TicketID}, 1235 UserID => $Param{UserID}, 1236 SLAID => $Param{Config}->{New}->{SLAID}, 1237 ); 1238 } 1239 1240 # set new priority 1241 if ( $Param{Config}->{New}->{Priority} ) { 1242 if ( $Self->{NoticeSTDOUT} ) { 1243 print " - set priority of Ticket $Ticket to '$Param{Config}->{New}->{Priority}'\n"; 1244 } 1245 $TicketObject->TicketPrioritySet( 1246 TicketID => $Param{TicketID}, 1247 UserID => $Param{UserID}, 1248 Priority => $Param{Config}->{New}->{Priority}, 1249 ); 1250 } 1251 if ( $Param{Config}->{New}->{PriorityID} ) { 1252 if ( $Self->{NoticeSTDOUT} ) { 1253 print 1254 " - set priority id of Ticket $Ticket to '$Param{Config}->{New}->{PriorityID}'\n"; 1255 } 1256 $TicketObject->TicketPrioritySet( 1257 TicketID => $Param{TicketID}, 1258 UserID => $Param{UserID}, 1259 PriorityID => $Param{Config}->{New}->{PriorityID}, 1260 ); 1261 } 1262 1263 # set new owner 1264 if ( $Param{Config}->{New}->{Owner} ) { 1265 if ( $Self->{NoticeSTDOUT} ) { 1266 print " - set owner of Ticket $Ticket to '$Param{Config}->{New}->{Owner}'\n"; 1267 } 1268 $TicketObject->TicketOwnerSet( 1269 TicketID => $Param{TicketID}, 1270 UserID => $Param{UserID}, 1271 NewUser => $Param{Config}->{New}->{Owner}, 1272 ); 1273 } 1274 if ( $Param{Config}->{New}->{OwnerID} ) { 1275 if ( $Self->{NoticeSTDOUT} ) { 1276 print " - set owner id of Ticket $Ticket to '$Param{Config}->{New}->{OwnerID}'\n"; 1277 } 1278 $TicketObject->TicketOwnerSet( 1279 TicketID => $Param{TicketID}, 1280 UserID => $Param{UserID}, 1281 NewUserID => $Param{Config}->{New}->{OwnerID}, 1282 ); 1283 } 1284 1285 # set new responsible 1286 if ( $Param{Config}->{New}->{Responsible} ) { 1287 if ( $Self->{NoticeSTDOUT} ) { 1288 print 1289 " - set responsible of Ticket $Ticket to '$Param{Config}->{New}->{Responsible}'\n"; 1290 } 1291 $TicketObject->TicketResponsibleSet( 1292 TicketID => $Param{TicketID}, 1293 UserID => $Param{UserID}, 1294 NewUser => $Param{Config}->{New}->{Responsible}, 1295 ); 1296 } 1297 if ( $Param{Config}->{New}->{ResponsibleID} ) { 1298 if ( $Self->{NoticeSTDOUT} ) { 1299 print 1300 " - set responsible id of Ticket $Ticket to '$Param{Config}->{New}->{ResponsibleID}'\n"; 1301 } 1302 $TicketObject->TicketResponsibleSet( 1303 TicketID => $Param{TicketID}, 1304 UserID => $Param{UserID}, 1305 NewUserID => $Param{Config}->{New}->{ResponsibleID}, 1306 ); 1307 } 1308 1309 # set new lock 1310 if ( $Param{Config}->{New}->{Lock} ) { 1311 if ( $Self->{NoticeSTDOUT} ) { 1312 print " - set lock of Ticket $Ticket to '$Param{Config}->{New}->{Lock}'\n"; 1313 } 1314 $TicketObject->TicketLockSet( 1315 TicketID => $Param{TicketID}, 1316 UserID => $Param{UserID}, 1317 Lock => $Param{Config}->{New}->{Lock}, 1318 ); 1319 } 1320 if ( $Param{Config}->{New}->{LockID} ) { 1321 if ( $Self->{NoticeSTDOUT} ) { 1322 print " - set lock id of Ticket $Ticket to '$Param{Config}->{New}->{LockID}'\n"; 1323 } 1324 $TicketObject->TicketLockSet( 1325 TicketID => $Param{TicketID}, 1326 UserID => $Param{UserID}, 1327 LockID => $Param{Config}->{New}->{LockID}, 1328 ); 1329 } 1330 1331 # get dynamic field backend objects 1332 my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); 1333 1334 # set new dynamic fields options 1335 # cycle trough the activated Dynamic Fields for this screen 1336 DYNAMICFIELD: 1337 for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) { 1338 1339 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 1340 1341 # extract the dynamic field value from the web request 1342 my $Value = $DynamicFieldBackendObject->EditFieldValueGet( 1343 DynamicFieldConfig => $DynamicFieldConfig, 1344 Template => $Param{Config}->{New}, 1345 TransformDates => 0, 1346 ); 1347 1348 # check if we got a value or an empty value if 1349 # an empty value is configured as valid (PossibleNone) 1350 # for the current dynamic field 1351 if ( 1352 defined $Value 1353 && ( 1354 $DynamicFieldConfig->{Config}->{PossibleNone} 1355 || $Value ne '' 1356 ) 1357 ) 1358 { 1359 my $Success = $DynamicFieldBackendObject->ValueSet( 1360 DynamicFieldConfig => $DynamicFieldConfig, 1361 ObjectID => $Param{TicketID}, 1362 Value => $Value, 1363 UserID => 1, 1364 ); 1365 1366 if ($Success) { 1367 if ( $Self->{NoticeSTDOUT} ) { 1368 my $ValueStrg = $DynamicFieldBackendObject->ReadableValueRender( 1369 DynamicFieldConfig => $DynamicFieldConfig, 1370 Value => $Value, 1371 ); 1372 print " - set ticket dynamic field $DynamicFieldConfig->{Name} " 1373 . "of Ticket $Ticket to $ValueStrg->{Title} '\n"; 1374 } 1375 } 1376 else { 1377 $Kernel::OM->Get('Kernel::System::Log')->Log( 1378 Priority => 'error', 1379 Message => "Could not set dynamic field $DynamicFieldConfig->{Name} " 1380 . "for Ticket $Ticket.", 1381 ); 1382 } 1383 } 1384 } 1385 1386 # run module 1387 my $AllowCustomModuleExecution 1388 = $Kernel::OM->Get('Kernel::Config')->Get('Ticket::GenericAgentAllowCustomModuleExecution') || 0; 1389 1390 if ( $Param{Config}->{New}->{Module} && $AllowCustomModuleExecution ) { 1391 if ( $Self->{NoticeSTDOUT} ) { 1392 print " - Use module ($Param{Config}->{New}->{Module}) for Ticket $Ticket.\n"; 1393 } 1394 $Kernel::OM->Get('Kernel::System::Log')->Log( 1395 Priority => 'notice', 1396 Message => "Use module ($Param{Config}->{New}->{Module}) for Ticket $Ticket.", 1397 ); 1398 if ( $Self->{Debug} ) { 1399 $Kernel::OM->Get('Kernel::System::Log')->Log( 1400 Priority => 'debug', 1401 Message => "Try to load module: $Param{Config}->{New}->{Module}!", 1402 ); 1403 } 1404 1405 if ( $Kernel::OM->Get('Kernel::System::Main')->Require( $Param{Config}->{New}->{Module} ) ) 1406 { 1407 1408 # protect parent process 1409 eval { 1410 my $Object = $Param{Config}->{New}->{Module}->new( 1411 Debug => $Self->{Debug}, 1412 ); 1413 if ($Object) { 1414 $Object->Run( 1415 %{ $Param{Config} }, 1416 TicketID => $Param{TicketID}, 1417 ); 1418 } 1419 }; 1420 1421 if ($@) { 1422 $Kernel::OM->Get('Kernel::System::Log')->Log( 1423 Priority => 'error', 1424 Message => $@ 1425 ); 1426 } 1427 } 1428 } 1429 elsif ( $Param{Config}->{New}->{Module} && !$AllowCustomModuleExecution ) { 1430 if ( $Self->{NoticeSTDOUT} ) { 1431 print " - Use module ($Param{Config}->{New}->{Module}) is not allowed by the system configuration.\n"; 1432 } 1433 $Kernel::OM->Get('Kernel::System::Log')->Log( 1434 Priority => 'error', 1435 Message => "Use module ($Param{Config}->{New}->{Module}) is not allowed by the system configuration.", 1436 ); 1437 } 1438 1439 # set new archive flag 1440 if ( 1441 $Param{Config}->{New}->{ArchiveFlag} 1442 && $Kernel::OM->Get('Kernel::Config')->Get('Ticket::ArchiveSystem') 1443 ) 1444 { 1445 if ( $Self->{NoticeSTDOUT} ) { 1446 print 1447 " - set archive flag of Ticket $Ticket to '$Param{Config}->{New}->{ArchiveFlag}'\n"; 1448 } 1449 $TicketObject->TicketArchiveFlagSet( 1450 TicketID => $Param{TicketID}, 1451 UserID => $Param{UserID}, 1452 ArchiveFlag => $Param{Config}->{New}->{ArchiveFlag}, 1453 ); 1454 } 1455 1456 # cmd 1457 my $AllowCustomScriptExecution 1458 = $Kernel::OM->Get('Kernel::Config')->Get('Ticket::GenericAgentAllowCustomScriptExecution') || 0; 1459 1460 if ( $Param{Config}->{New}->{CMD} && $AllowCustomScriptExecution ) { 1461 if ( $Self->{NoticeSTDOUT} ) { 1462 print " - Execute '$Param{Config}->{New}->{CMD}' for Ticket $Ticket.\n"; 1463 } 1464 $Kernel::OM->Get('Kernel::System::Log')->Log( 1465 Priority => 'notice', 1466 Message => "Execute '$Param{Config}->{New}->{CMD}' for Ticket $Ticket.", 1467 ); 1468 system("$Param{Config}->{New}->{CMD} $Param{TicketNumber} $Param{TicketID} "); 1469 1470 if ( $? ne 0 ) { 1471 $Kernel::OM->Get('Kernel::System::Log')->Log( 1472 Priority => 'notice', 1473 Message => "Command returned a nonzero return code: rc=$?, err=$!", 1474 ); 1475 } 1476 } 1477 elsif ( $Param{Config}->{New}->{CMD} && !$AllowCustomScriptExecution ) { 1478 if ( $Self->{NoticeSTDOUT} ) { 1479 print " - Execute '$Param{Config}->{New}->{CMD}' is not allowed by the system configuration..\n"; 1480 } 1481 $Kernel::OM->Get('Kernel::System::Log')->Log( 1482 Priority => 'error', 1483 Message => "Execute '$Param{Config}->{New}->{CMD}' is not allowed by the system configuration..", 1484 ); 1485 } 1486 1487 # delete ticket 1488 if ( $Param{Config}->{New}->{Delete} ) { 1489 if ( $Self->{NoticeSTDOUT} ) { 1490 print " - Delete Ticket $Ticket.\n"; 1491 } 1492 $Kernel::OM->Get('Kernel::System::Log')->Log( 1493 Priority => 'notice', 1494 Message => "Delete Ticket $Ticket.", 1495 ); 1496 $TicketObject->TicketDelete( 1497 UserID => $Param{UserID}, 1498 TicketID => $Param{TicketID}, 1499 ); 1500 } 1501 return 1; 1502} 1503 1504sub _JobUpdateRunTime { 1505 my ( $Self, %Param ) = @_; 1506 1507 # check needed stuff 1508 for (qw(Name UserID)) { 1509 if ( !$Param{$_} ) { 1510 $Kernel::OM->Get('Kernel::System::Log')->Log( 1511 Priority => 'error', 1512 Message => "Need $_!" 1513 ); 1514 return; 1515 } 1516 } 1517 1518 # get database object 1519 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 1520 1521 # delete old run times 1522 return if !$DBObject->Do( 1523 SQL => 'DELETE FROM generic_agent_jobs WHERE job_name = ? AND job_key IN (?, ?)', 1524 Bind => [ \$Param{Name}, \'ScheduleLastRun', \'ScheduleLastRunUnixTime' ], 1525 ); 1526 1527 # get time object 1528 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 1529 1530 # update new run time 1531 my %Insert = ( 1532 ScheduleLastRun => $DateTimeObject->ToString(), 1533 ScheduleLastRunUnixTime => $DateTimeObject->ToEpoch(), 1534 ); 1535 1536 for my $Key ( sort keys %Insert ) { 1537 $DBObject->Do( 1538 SQL => 'INSERT INTO generic_agent_jobs (job_name,job_key, job_value) VALUES (?, ?, ?)', 1539 Bind => [ \$Param{Name}, \$Key, \$Insert{$Key} ], 1540 ); 1541 } 1542 1543 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 1544 Key => 'JobGet::' . $Param{Name}, 1545 Type => 'GenericAgent', 1546 ); 1547 1548 return 1; 1549} 1550 15511; 1552 1553=end Internal: 1554 1555=head1 TERMS AND CONDITIONS 1556 1557This software is part of the OTRS project (L<https://otrs.org/>). 1558 1559This software comes with ABSOLUTELY NO WARRANTY. For details, see 1560the enclosed file COPYING for license information (GPL). If you 1561did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>. 1562 1563=cut 1564