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::AgentCustomerUserAddressBook; 10 11use strict; 12use warnings; 13 14use List::Util qw(first); 15 16use Kernel::Language qw(Translatable); 17use Kernel::System::VariableCheck qw(:all); 18 19our $ObjectManagerDisabled = 1; 20 21sub new { 22 my ( $Type, %Param ) = @_; 23 24 my $Self = {%Param}; 25 bless( $Self, $Type ); 26 27 # Define some customer company values, to use the values later for the output. 28 $Self->{CustomerCompanySearchFieldPrefix} = 'CustomerCompany_'; 29 $Self->{CustomerCompanyLabelIdentifier} = Translatable('Customer'); 30 31 return $Self; 32} 33 34sub Run { 35 my ( $Self, %Param ) = @_; 36 37 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 38 my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); 39 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 40 41 $Self->{RecipientType} = $ParamObject->GetParam( Param => 'RecipientType' ) || 'Email'; 42 43 $Self->{Config} = $ConfigObject->Get("CustomerUser::Frontend::$Self->{Action}"); 44 45 # Check if the config settings exsists for the given recipient type. 46 for my $ConfigKey (qw(SearchParameters DefaultFields ShowColumns)) { 47 if ( !grep { $_ eq $Self->{RecipientType} } sort keys %{ $Self->{Config}->{$ConfigKey} } ) { 48 return $LayoutObject->ErrorScreen( 49 Message => Translatable("No config setting '$ConfigKey' for the given RecipientType!"), 50 Comment => Translatable('Please contact the administrator.'), 51 ); 52 } 53 } 54 55 # Get the diffrent values from the params or the config to set the default values. 56 $Self->{StartHit} = int( $ParamObject->GetParam( Param => 'StartHit' ) || 1 ); 57 $Self->{SearchLimit} = $Self->{Config}->{SearchParameters}->{ $Self->{RecipientType} }->{SearchLimit} || 500; 58 $Self->{SortBy} = $ParamObject->GetParam( Param => 'SortBy' ) 59 || $Self->{Config}->{SearchParameters}->{ $Self->{RecipientType} }->{'SortBy::Default'} 60 || 'UserLogin'; 61 $Self->{OrderBy} = $ParamObject->GetParam( Param => 'OrderBy' ) 62 || $Self->{Config}->{SearchParameters}->{ $Self->{RecipientType} }->{'Order::Default'} 63 || 'Up'; 64 $Self->{Profile} = $ParamObject->GetParam( Param => 'Profile' ) || ''; 65 $Self->{SaveProfile} = $ParamObject->GetParam( Param => 'SaveProfile' ) || ''; 66 $Self->{TakeLastSearch} = $ParamObject->GetParam( Param => 'TakeLastSearch' ) || ''; 67 $Self->{SelectTemplate} = $ParamObject->GetParam( Param => 'SelectTemplate' ) || ''; 68 $Self->{EraseTemplate} = $ParamObject->GetParam( Param => 'EraseTemplate' ) || ''; 69 $Self->{RecipientField} = $ParamObject->GetParam( Param => 'RecipientField' ); 70 $Self->{RecipientFieldLabel} = $ParamObject->GetParam( Param => 'RecipientFieldLabel' ) || $Self->{RecipientField}; 71 72 if ( !$Self->{RecipientField} ) { 73 return $LayoutObject->ErrorScreen( 74 Message => Translatable('No RecipientField is given!'), 75 Comment => Translatable('Please contact the administrator.'), 76 ); 77 } 78 79 if ( $ParamObject->GetParam( Param => 'SearchTemplate' ) && $Self->{Profile} ) { 80 return $LayoutObject->Redirect( 81 OP => 82 "Action=AgentCustomerUserAddressBook;Subaction=Search;TakeLastSearch=1;SaveProfile=1;Profile=$Self->{Profile}" 83 ); 84 } 85 86 my %GetParam; 87 88 # Get the dynamic fields from the customer user and company search fields. 89 my @CustomerUserDynamicFields = $Self->_GetCustomerUserSearchFields( 90 Types => ['DynamicField'], 91 ); 92 my @CustomerCompanyDynamicFields = $Self->_GetCustomerCompanySearchFields( 93 Types => ['DynamicField'], 94 WithoutPrefix => 1, 95 ); 96 97 my %LookupCustomerUserDynamicFields = map { $_->{DatabaseField} => 1 } @CustomerUserDynamicFields; 98 my %LookupCustomerCompanyDynamicFields = map { $_->{DatabaseField} => 1 } @CustomerCompanyDynamicFields; 99 100 # Get the dynamic fields for this screen. 101 $Self->{DynamicFieldCustomerUser} = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet( 102 Valid => 1, 103 ObjectType => [ 'CustomerUser', ], 104 FieldFilter => \%LookupCustomerUserDynamicFields, 105 ); 106 $Self->{DynamicFieldCustomerCompany} = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet( 107 Valid => 1, 108 ObjectType => [ 'CustomerCompany', ], 109 FieldFilter => \%LookupCustomerCompanyDynamicFields, 110 ); 111 112 my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); 113 my $SearchProfileObject = $Kernel::OM->Get('Kernel::System::SearchProfile'); 114 115 # Get the diffrent search fields for the customer user search. 116 my @CustomerUserInputSearchFields = $Self->_GetCustomerUserSearchFields( 117 Types => ['Input'], 118 ); 119 my @CustomerUserSelectionSearchFields = $Self->_GetCustomerUserSearchFields( 120 Types => ['Selection'], 121 ); 122 123 # Get the diffrent search fields for the customer company search. 124 my @CustomerCompanyInputSearchFields = $Self->_GetCustomerCompanySearchFields( 125 Types => ['Input'], 126 ); 127 my @CustomerCompanySelectionSearchFields = $Self->_GetCustomerCompanySearchFields( 128 Types => ['Selection'], 129 ); 130 131 # Load parameters from search profile, 132 # this happens when the next result page should be shown, or when the results are reordered. 133 if ( ( $Self->{Subaction} eq 'LoadProfile' && $Self->{Profile} ) || $Self->{TakeLastSearch} ) { 134 %GetParam = $SearchProfileObject->SearchProfileGet( 135 Base => 'CustomerUserAddressBook', 136 Name => $Self->{Profile}, 137 UserLogin => $Self->{UserLogin}, 138 ); 139 140 if ( $GetParam{ShownAttributes} && ref $GetParam{ShownAttributes} eq 'ARRAY' ) { 141 $GetParam{ShownAttributes} = join ';', @{ $GetParam{ShownAttributes} }; 142 } 143 144 # Use param ExcludeUserLogins only for the last-search profile (otherwise ignore the parameter). 145 if ( $Self->{Profile} ne 'last-search' ) { 146 delete $GetParam{ExcludeUserLogins}; 147 } 148 } 149 elsif ( $Self->{Subaction} eq 'DeleteProfile' ) { 150 151 $SearchProfileObject->SearchProfileDelete( 152 Base => 'CustomerUserAddressBook', 153 Name => $Self->{Profile}, 154 UserLogin => $Self->{UserLogin}, 155 ); 156 $Self->{Profile} = ''; 157 } 158 else { 159 160 # Get some general search params. 161 for my $ParamName (qw(ShownAttributes)) { 162 $GetParam{$ParamName} = $ParamObject->GetParam( Param => $ParamName ); 163 } 164 165 # Get the scalar search params for the customer user and customer company fields. 166 for my $Field ( @CustomerUserInputSearchFields, @CustomerCompanyInputSearchFields ) { 167 $GetParam{ $Field->{Name} } = $ParamObject->GetParam( Param => $Field->{Name} ); 168 169 # Remove the whitespace on the start and end of the given string. 170 if ( $GetParam{ $Field->{Name} } ) { 171 $GetParam{ $Field->{Name} } =~ s{ \A \s+ }{}xms; 172 $GetParam{ $Field->{Name} } =~ s{ \s+ \z }{}xms; 173 } 174 } 175 176 # Get the array search params for the customer user and customer company fields. 177 for my $Field ( @CustomerUserSelectionSearchFields, @CustomerCompanySelectionSearchFields ) { 178 my @Array = $ParamObject->GetArray( Param => $Field->{Name} ); 179 if (@Array) { 180 $GetParam{ $Field->{Name} } = \@Array; 181 } 182 } 183 184 # Get the excluded user logins, which were already selected in a recipient field. 185 my $ExcludeUserLoginsJSONString = $ParamObject->GetParam( Param => 'ExcludeUserLoginsJSON' ) || ''; 186 187 if ($ExcludeUserLoginsJSONString) { 188 $GetParam{ExcludeUserLogins} = $Kernel::OM->Get('Kernel::System::JSON')->Decode( 189 Data => $ExcludeUserLoginsJSONString, 190 ); 191 } 192 193 # Get Dynamic fields from param object and cycle trough the activated Dynamic Fields for this screen. 194 DYNAMICFIELD: 195 for my $DynamicFieldConfig ( @{ $Self->{DynamicFieldCustomerUser} }, @{ $Self->{DynamicFieldCustomerCompany} } ) 196 { 197 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 198 199 my $SearchFieldPreferences = $DynamicFieldBackendObject->SearchFieldPreferences( 200 DynamicFieldConfig => $DynamicFieldConfig, 201 ); 202 203 next DYNAMICFIELD if !IsArrayRefWithData($SearchFieldPreferences); 204 205 PREFERENCE: 206 for my $Preference ( @{$SearchFieldPreferences} ) { 207 208 # Extract the dynamic field value from the web request. 209 my $DynamicFieldValue = $DynamicFieldBackendObject->SearchFieldValueGet( 210 DynamicFieldConfig => $DynamicFieldConfig, 211 ParamObject => $ParamObject, 212 ReturnProfileStructure => 1, 213 LayoutObject => $LayoutObject, 214 Type => $Preference->{Type}, 215 ); 216 217 # Set the complete value structure in GetParam to store it later in the search profile. 218 if ( IsHashRefWithData($DynamicFieldValue) ) { 219 %GetParam = ( %GetParam, %{$DynamicFieldValue} ); 220 } 221 } 222 } 223 } 224 225 # Show result site or perform other actions. 226 if ( $Self->{Subaction} eq 'Search' && !$Self->{EraseTemplate} ) { 227 228 # Generate a lookup hash for the exluce user logins and delete the entry from the 'GetParam', because 229 # we disable the entries in the result. 230 my %LookupExcludeUserLogins; 231 if ( IsArrayRefWithData( $GetParam{ExcludeUserLogins} ) ) { 232 %LookupExcludeUserLogins = map { $_ => 1 } @{ $GetParam{ExcludeUserLogins} }; 233 delete $GetParam{ExcludeUserLogins}; 234 } 235 236 # Fill up profile name (e.g. with last-search). 237 if ( !$Self->{Profile} || !$Self->{SaveProfile} ) { 238 $Self->{Profile} = 'last-search'; 239 } 240 241 # Save search profile (under last-search or real profile name). 242 $Self->{SaveProfile} = 1; 243 244 # Remember the last search values, e.g. for sorting. 245 if ( $Self->{SaveProfile} && $Self->{Profile} ) { 246 247 # Remove old profile stuff, before the new stuff will be saved. 248 $SearchProfileObject->SearchProfileDelete( 249 Base => 'CustomerUserAddressBook', 250 Name => $Self->{Profile}, 251 UserLogin => $Self->{UserLogin}, 252 ); 253 254 if ( $GetParam{ShownAttributes} && ref $GetParam{ShownAttributes} eq '' ) { 255 $GetParam{ShownAttributes} = [ split /;/, $GetParam{ShownAttributes} ]; 256 } 257 258 KEY: 259 for my $Key ( sort keys %GetParam ) { 260 next KEY if !defined $GetParam{$Key}; 261 262 $SearchProfileObject->SearchProfileAdd( 263 Base => 'CustomerUserAddressBook', 264 Name => $Self->{Profile}, 265 Key => $Key, 266 Value => $GetParam{$Key}, 267 UserLogin => $Self->{UserLogin}, 268 ); 269 } 270 } 271 272 my %AttributeLookup; 273 274 for my $Attribute ( @{ $GetParam{ShownAttributes} || [] } ) { 275 $AttributeLookup{$Attribute} = 1; 276 } 277 278 my %DynamicFieldSearchParameters; 279 280 DYNAMICFIELD: 281 for my $DynamicFieldConfig ( @{ $Self->{DynamicFieldCustomerUser} }, @{ $Self->{DynamicFieldCustomerCompany} } ) 282 { 283 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 284 285 my $SearchFieldPreferences = $DynamicFieldBackendObject->SearchFieldPreferences( 286 DynamicFieldConfig => $DynamicFieldConfig, 287 ); 288 289 next DYNAMICFIELD if !IsArrayRefWithData($SearchFieldPreferences); 290 291 PREFERENCE: 292 for my $Preference ( @{$SearchFieldPreferences} ) { 293 294 if ( 295 !$AttributeLookup{ 'LabelSearch_DynamicField_' . $DynamicFieldConfig->{Name} . $Preference->{Type} } 296 ) 297 { 298 next PREFERENCE; 299 } 300 301 # Extract the dynamic field value from the profile. 302 my $SearchParameter = $DynamicFieldBackendObject->SearchFieldParameterBuild( 303 DynamicFieldConfig => $DynamicFieldConfig, 304 Profile => \%GetParam, 305 LayoutObject => $LayoutObject, 306 Type => $Preference->{Type}, 307 ); 308 309 if ( defined $SearchParameter ) { 310 $DynamicFieldSearchParameters{ 'DynamicField_' . $DynamicFieldConfig->{Name} } 311 = $SearchParameter->{Parameter}; 312 } 313 } 314 } 315 316 # Get only the customer company search params. 317 my %CustomerCompanyGetParam; 318 319 CUSTOMERCOMPANYFIELD: 320 for my $CustomerCompanyField ( @CustomerCompanySelectionSearchFields, @CustomerCompanyInputSearchFields ) { 321 322 next CUSTOMERCOMPANYFIELD if !$GetParam{ $CustomerCompanyField->{Name} }; 323 324 # Get the real field name. 325 my $RealFieldName = $CustomerCompanyField->{Name}; 326 $RealFieldName =~ s{ \A $Self->{CustomerCompanySearchFieldPrefix} }{}xms; 327 328 $CustomerCompanyGetParam{$RealFieldName} = $GetParam{ $CustomerCompanyField->{Name} }; 329 } 330 331 # Check if a dynamic field search param exists. 332 my $CustomerCompanyDynamicFieldExists; 333 334 CUSTOMERCOMPANYDYNAMICFIELD: 335 for my $CustomerCompanyDynamicField (@CustomerCompanyDynamicFields) { 336 next CUSTOMERCOMPANYDYNAMICFIELD if !$DynamicFieldSearchParameters{ $CustomerCompanyDynamicField->{Name} }; 337 338 $CustomerCompanyDynamicFieldExists = 1; 339 340 last CUSTOMERCOMPANYDYNAMICFIELD; 341 } 342 343 my $CustomerCompanyIDs; 344 345 # Search first for customer companies, if some customer company search params exists. 346 if ( %CustomerCompanyGetParam || $CustomerCompanyDynamicFieldExists ) { 347 348 $CustomerCompanyIDs = $Kernel::OM->Get('Kernel::System::CustomerCompany')->CustomerCompanySearchDetail( 349 Result => 'ARRAY', 350 %CustomerCompanyGetParam, 351 %DynamicFieldSearchParameters, 352 ) || []; 353 } 354 355 my $CustomerUserObject = $Kernel::OM->Get('Kernel::System::CustomerUser'); 356 357 my $ViewableCustomerUserLogins = []; 358 359 # Do the search only if no customer company get params are given or some customer company ids for the given 360 # customer company search params were found. 361 if ( 362 ( !%CustomerCompanyGetParam && !$CustomerCompanyDynamicFieldExists ) 363 || IsArrayRefWithData($CustomerCompanyIDs) 364 ) 365 { 366 367 $ViewableCustomerUserLogins = $CustomerUserObject->CustomerSearchDetail( 368 Result => 'ARRAY', 369 OrderBy => [ $Self->{SortBy} ], 370 OrderByDirection => [ $Self->{OrderBy} ], 371 Limit => $Self->{SearchLimit}, 372 CustomerCompanySearchCustomerIDs => $CustomerCompanyIDs, 373 %GetParam, 374 %DynamicFieldSearchParameters, 375 ) || []; 376 } 377 378 if ( $Self->{RecipientSelectionAJAX} ) { 379 380 my @CustomerUserLoginList; 381 382 if ( IsArrayRefWithData($ViewableCustomerUserLogins) ) { 383 384 CUSTOMERUSERLOGIN: 385 for my $CustomerUserLogin ( @{$ViewableCustomerUserLogins} ) { 386 387 my %CustomerUser = $CustomerUserObject->CustomerUserDataGet( 388 User => $CustomerUserLogin, 389 ); 390 391 push @CustomerUserLoginList, { 392 UserLogin => $CustomerUser{UserLogin}, 393 UserMailString => $CustomerUser{UserMailString}, 394 }; 395 } 396 } 397 398 my $Output = $LayoutObject->JSONEncode( 399 Data => \@CustomerUserLoginList, 400 ); 401 return $LayoutObject->Attachment( 402 NoCache => 1, 403 ContentType => 'text/html', 404 Content => $Output, 405 Type => 'inline' 406 ); 407 } 408 else { 409 410 my $Output = $LayoutObject->Header( 411 Type => 'Small', 412 ); 413 $LayoutObject->Print( Output => \$Output ); 414 $Output = ''; 415 416 $Self->{Filter} = $ParamObject->GetParam( Param => 'Filter' ) || ''; 417 $Self->{View} = $ParamObject->GetParam( Param => 'View' ) || ''; 418 419 my %LinkEncoded; 420 for my $Attribute (qw(RecipientField RecipientFieldLabel RecipientType Profile)) { 421 $LinkEncoded{$Attribute} = $LayoutObject->LinkEncode( $Self->{$Attribute} ); 422 } 423 424 my $LinkPage = 'RecipientField=' . $LinkEncoded{RecipientField} 425 . ';RecipientFieldLabel=' . $LinkEncoded{RecipientFieldLabel} 426 . ';RecipientType=' . $LinkEncoded{RecipientType} 427 . ';Filter=' . $LayoutObject->Ascii2Html( Text => $Self->{Filter} ) 428 . ';View=' . $LayoutObject->Ascii2Html( Text => $Self->{View} ) 429 . ';SortBy=' . $LayoutObject->Ascii2Html( Text => $Self->{SortBy} ) 430 . ';OrderBy=' . $LayoutObject->Ascii2Html( Text => $Self->{OrderBy} ) 431 . ';Profile=' . $LinkEncoded{Profile} 432 . ';TakeLastSearch=1;Subaction=Search' 433 . ';'; 434 my $LinkSort = 'RecipientField=' . $LinkEncoded{RecipientField} 435 . ';RecipientFieldLabel=' . $LinkEncoded{RecipientFieldLabel} 436 . ';RecipientType=' . $LinkEncoded{RecipientType} 437 . ';Filter=' . $LayoutObject->Ascii2Html( Text => $Self->{Filter} ) 438 . ';View=' . $LayoutObject->Ascii2Html( Text => $Self->{View} ) 439 . ';Profile=' . $LinkEncoded{Profile} 440 . ';TakeLastSearch=1;Subaction=Search' 441 . ';'; 442 my $LinkFilter = 'RecipientField=' . $LinkEncoded{RecipientField} 443 . ';RecipientFieldLabel=' . $LinkEncoded{RecipientFieldLabel} 444 . ';RecipientType=' . $LinkEncoded{RecipientType} 445 . ';Profile=' . $LayoutObject->Ascii2Html( Text => $Self->{Profile} ) 446 . ';TakeLastSearch=1;Subaction=Search' 447 . ';'; 448 my $LinkBack = 'RecipientField=' . $LinkEncoded{RecipientField} 449 . ';RecipientFieldLabel=' . $LinkEncoded{RecipientFieldLabel} 450 . ';RecipientType=' . $LinkEncoded{RecipientType} 451 . ';Profile=' . $LayoutObject->Ascii2Html( Text => $Self->{Profile} ) 452 . ';TakeLastSearch=1;Subaction=LoadProfile' 453 . ';'; 454 455 # Find out which columns should be shown. 456 my @ShowColumns; 457 if ( IsArrayRefWithData( $Self->{Config}->{ShowColumns}->{ $Self->{RecipientType} } ) ) { 458 @ShowColumns = @{ $Self->{Config}->{ShowColumns}->{ $Self->{RecipientType} } }; 459 } 460 461 # Get the already selected recipients, to remember the selected recipients for the diffrent pages. 462 my $RecipientsJSONString = $ParamObject->GetParam( Param => 'RecipientsJSON' ) || ''; 463 464 my $Recipients; 465 if ($RecipientsJSONString) { 466 $Recipients = $Kernel::OM->Get('Kernel::System::JSON')->Decode( 467 Data => $RecipientsJSONString, 468 ); 469 } 470 471 $Output .= $LayoutObject->CustomerUserAddressBookListShow( 472 CustomerUserIDs => $ViewableCustomerUserLogins, 473 Total => scalar @{$ViewableCustomerUserLogins}, 474 View => $Self->{View}, 475 Env => $Self, 476 LinkPage => $LinkPage, 477 LinkSort => $LinkSort, 478 LinkFilter => $LinkFilter, 479 LinkBack => $LinkBack, 480 Profile => $Self->{Profile}, 481 TitleName => Translatable('Customer User Address Book'), 482 ShowColumns => \@ShowColumns, 483 SortBy => $LayoutObject->Ascii2Html( Text => $Self->{SortBy} ), 484 OrderBy => $LayoutObject->Ascii2Html( Text => $Self->{OrderBy} ), 485 RequestedURL => 'Action=' . $Self->{Action} . ';' . $LinkPage, 486 Recipients => $Recipients || {}, 487 RecipientType => $Self->{RecipientType}, 488 RecipientField => $Self->{RecipientField}, 489 RecipientFieldLabel => $Self->{RecipientFieldLabel}, 490 CustomerTicketTextField => 491 $Self->{Config}->{SearchParameters}->{ $Self->{RecipientType} }->{CustomerTicketTextField} 492 || 'UserMailString', 493 LookupExcludeUserLogins => \%LookupExcludeUserLogins, 494 ); 495 496 $Output .= $LayoutObject->Footer( 497 Type => 'Small', 498 ); 499 500 return $Output; 501 } 502 } 503 504 # There was no 'SubAction', or there were validation errors, or an user or customer was searched 505 # generate search mask. 506 my $Output = $LayoutObject->Header( 507 Type => 'Small', 508 ); 509 510 $Output .= $Self->_MaskForm( 511 RecipientType => $Self->{RecipientType}, 512 RecipientField => $Self->{RecipientField}, 513 RecipientFieldLabel => $Self->{RecipientFieldLabel}, 514 %GetParam, 515 ); 516 517 $Output .= $LayoutObject->Footer( 518 Type => 'Small', 519 ); 520 521 return $Output; 522} 523 524sub _MaskForm { 525 my ( $Self, %Param ) = @_; 526 527 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 528 my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); 529 530 my $EmptySearch = $ParamObject->GetParam( Param => 'EmptySearch' ); 531 if ( !$Self->{Profile} ) { 532 $EmptySearch = 1; 533 } 534 535 my $SearchProfileObject = $Kernel::OM->Get('Kernel::System::SearchProfile'); 536 537 my %GetParam = $SearchProfileObject->SearchProfileGet( 538 Base => 'CustomerUserAddressBook', 539 Name => $Self->{Profile}, 540 UserLogin => $Self->{UserLogin}, 541 ); 542 543 # Allow profile overwrite the contents of %Param. 544 %Param = ( 545 %Param, 546 %GetParam, 547 ); 548 549 # Get the search fields for the customer user search. 550 my @CustomerUserSearchFields = $Self->_GetCustomerUserSearchFields( 551 Types => [ 'Input', 'Selection' ], 552 ); 553 554 # Get the search fields for the customer user search. 555 my @CustomerCompanySearchFields = $Self->_GetCustomerCompanySearchFields( 556 Types => [ 'Input', 'Selection' ], 557 ); 558 559 # Translate the customer company label identifier to add this to the labels. 560 my $TranslatedCustomerCompanyLabelIdentifier 561 = $LayoutObject->{LanguageObject}->Translate( $Self->{CustomerCompanyLabelIdentifier} ); 562 563 my @Attributes; 564 565 for my $Field (@CustomerUserSearchFields) { 566 567 push @Attributes, { 568 Key => $Field->{Name}, 569 Value => $Field->{Label}, 570 }; 571 } 572 573 my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); 574 575 if ( IsArrayRefWithData( $Self->{DynamicFieldCustomerUser} ) ) { 576 577 # Create dynamic fields search options for attribute select 578 # cycle trough the activated Dynamic Fields for this screen. 579 DYNAMICFIELD: 580 for my $DynamicFieldConfig ( @{ $Self->{DynamicFieldCustomerUser} } ) { 581 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 582 next DYNAMICFIELD if !$DynamicFieldConfig->{Name}; 583 next DYNAMICFIELD if $DynamicFieldConfig->{Name} eq ''; 584 585 my $SearchFieldPreferences = $DynamicFieldBackendObject->SearchFieldPreferences( 586 DynamicFieldConfig => $DynamicFieldConfig, 587 ); 588 589 next DYNAMICFIELD if !IsArrayRefWithData($SearchFieldPreferences); 590 591 my $TranslatedDynamicFieldLabel = $LayoutObject->{LanguageObject}->Translate( 592 $DynamicFieldConfig->{Label}, 593 ); 594 595 PREFERENCE: 596 for my $Preference ( @{$SearchFieldPreferences} ) { 597 598 my $TranslatedSuffix = $LayoutObject->{LanguageObject}->Translate( 599 $Preference->{LabelSuffix}, 600 ) || ''; 601 602 if ($TranslatedSuffix) { 603 $TranslatedSuffix = ' (' . $TranslatedSuffix . ')'; 604 } 605 606 push @Attributes, ( 607 { 608 Key => 'Search_DynamicField_' . $DynamicFieldConfig->{Name} . $Preference->{Type}, 609 Value => $TranslatedDynamicFieldLabel . $TranslatedSuffix, 610 }, 611 ); 612 } 613 } 614 } 615 616 if (@CustomerCompanySearchFields) { 617 618 push @Attributes, { 619 Key => '', 620 Value => '-', 621 Disabled => 1, 622 }; 623 624 for my $Field (@CustomerCompanySearchFields) { 625 626 my $TranslatedFieldLabel = $LayoutObject->{LanguageObject}->Translate( 627 $Field->{Label}, 628 ); 629 630 if ( 631 $TranslatedCustomerCompanyLabelIdentifier 632 && $TranslatedFieldLabel ne $TranslatedCustomerCompanyLabelIdentifier 633 ) 634 { 635 $TranslatedFieldLabel .= " ($TranslatedCustomerCompanyLabelIdentifier)"; 636 } 637 638 push @Attributes, { 639 Key => $Field->{Name}, 640 Value => $TranslatedFieldLabel, 641 }; 642 } 643 } 644 645 if ( IsArrayRefWithData( $Self->{DynamicFieldCustomerCompany} ) ) { 646 647 # Create dynamic fields search options for attribute select 648 # cycle trough the activated Dynamic Fields for this screen. 649 DYNAMICFIELD: 650 for my $DynamicFieldConfig ( @{ $Self->{DynamicFieldCustomerCompany} } ) { 651 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 652 next DYNAMICFIELD if !$DynamicFieldConfig->{Name}; 653 next DYNAMICFIELD if $DynamicFieldConfig->{Name} eq ''; 654 655 my $SearchFieldPreferences = $DynamicFieldBackendObject->SearchFieldPreferences( 656 DynamicFieldConfig => $DynamicFieldConfig, 657 ); 658 659 next DYNAMICFIELD if !IsArrayRefWithData($SearchFieldPreferences); 660 661 my $TranslatedDynamicFieldLabel = $LayoutObject->{LanguageObject}->Translate( 662 $DynamicFieldConfig->{Label}, 663 ); 664 665 PREFERENCE: 666 for my $Preference ( @{$SearchFieldPreferences} ) { 667 668 my $TranslatedSuffix = $LayoutObject->{LanguageObject}->Translate( 669 $Preference->{LabelSuffix}, 670 ) || ''; 671 672 if ($TranslatedSuffix) { 673 $TranslatedSuffix = ' (' . $TranslatedSuffix . ')'; 674 } 675 676 my $DynamicFieldLabel = $TranslatedDynamicFieldLabel . $TranslatedSuffix; 677 678 if ( 679 $TranslatedCustomerCompanyLabelIdentifier 680 && $TranslatedDynamicFieldLabel ne $TranslatedCustomerCompanyLabelIdentifier 681 ) 682 { 683 $DynamicFieldLabel 684 .= ( $TranslatedSuffix ? " - " : " " ) . "($TranslatedCustomerCompanyLabelIdentifier)"; 685 } 686 687 push @Attributes, ( 688 { 689 Key => 'Search_DynamicField_' . $DynamicFieldConfig->{Name} . $Preference->{Type}, 690 Value => $DynamicFieldLabel, 691 }, 692 ); 693 } 694 } 695 } 696 697 # Create HTML strings for all dynamic fields. 698 my %DynamicFieldHTML; 699 700 # Cycle trough the activated Dynamic Fields for this screen. 701 DYNAMICFIELD: 702 for my $DynamicFieldConfig ( @{ $Self->{DynamicFieldCustomerUser} }, @{ $Self->{DynamicFieldCustomerCompany} } ) { 703 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 704 705 my $SearchFieldPreferences = $DynamicFieldBackendObject->SearchFieldPreferences( 706 DynamicFieldConfig => $DynamicFieldConfig, 707 ); 708 709 next DYNAMICFIELD if !IsArrayRefWithData($SearchFieldPreferences); 710 711 my $PossibleValues = $DynamicFieldBackendObject->PossibleValuesGet( 712 DynamicFieldConfig => $DynamicFieldConfig, 713 OverridePossibleNone => 0, 714 ); 715 716 PREFERENCE: 717 for my $Preference ( @{$SearchFieldPreferences} ) { 718 719 $DynamicFieldHTML{ $DynamicFieldConfig->{Name} . $Preference->{Type} } 720 = $DynamicFieldBackendObject->SearchFieldRender( 721 DynamicFieldConfig => $DynamicFieldConfig, 722 Profile => \%GetParam, 723 PossibleValuesFilter => $PossibleValues, 724 LayoutObject => $LayoutObject, 725 Type => $Preference->{Type}, 726 ); 727 } 728 } 729 730 $Param{AttributesStrg} = $LayoutObject->BuildSelection( 731 PossibleNone => 1, 732 Data => \@Attributes, 733 Name => 'Attribute', 734 Multiple => 0, 735 Class => 'Modernize', 736 ); 737 $Param{AttributesOrigStrg} = $LayoutObject->BuildSelection( 738 PossibleNone => 1, 739 Data => \@Attributes, 740 Name => 'AttributeOrig', 741 Multiple => 0, 742 Class => 'Modernize', 743 ); 744 745 my @OutputSearchFields; 746 747 # Build the output for the input search fields. 748 for my $Field (@CustomerUserSearchFields) { 749 750 my %FieldData = ( 751 CustomerUserField => 1, 752 Name => $Field->{Name}, 753 Label => $Field->{Label}, 754 ); 755 756 if ( $Field->{Type} eq 'Selection' ) { 757 758 my $SelectionString = $LayoutObject->BuildSelection( 759 Data => $Field->{SelectionsData}, 760 Name => $Field->{Name}, 761 Translation => 1, 762 Multiple => 1, 763 Size => 5, 764 SelectedID => $Param{ $Field->{Name} }, 765 Class => 'Modernize', 766 ); 767 $FieldData{SelectionString} = $SelectionString; 768 } 769 else { 770 $FieldData{Value} = $Param{ $Field->{Name} }; 771 } 772 773 push @OutputSearchFields, \%FieldData; 774 } 775 776 # Build the output for the input search fields. 777 for my $Field (@CustomerCompanySearchFields) { 778 779 my $TranslatedFieldLabel = $LayoutObject->{LanguageObject}->Translate( 780 $Field->{Label}, 781 ); 782 783 if ( 784 $TranslatedCustomerCompanyLabelIdentifier 785 && $TranslatedFieldLabel ne $TranslatedCustomerCompanyLabelIdentifier 786 ) 787 { 788 $TranslatedFieldLabel .= " ($TranslatedCustomerCompanyLabelIdentifier)"; 789 } 790 791 my %FieldData = ( 792 CustomerCompanyField => 1, 793 Name => $Field->{Name}, 794 Label => $TranslatedFieldLabel, 795 ); 796 797 if ( $Field->{Type} eq 'Selection' ) { 798 799 my $SelectionString = $LayoutObject->BuildSelection( 800 Data => $Field->{SelectionsData}, 801 Name => $Field->{Name}, 802 Translation => 1, 803 Multiple => 1, 804 Size => 5, 805 SelectedID => $Param{ $Field->{Name} }, 806 Class => 'Modernize', 807 ); 808 $FieldData{SelectionString} = $SelectionString; 809 } 810 else { 811 $FieldData{Value} = $Param{ $Field->{Name} }; 812 } 813 814 push @OutputSearchFields, \%FieldData; 815 } 816 817 $Param{OutputSearchFields} = \@OutputSearchFields; 818 819 my %Profiles = $SearchProfileObject->SearchProfileList( 820 Base => 'CustomerUserAddressBook', 821 UserLogin => $Self->{UserLogin}, 822 ); 823 delete $Profiles{''}; 824 delete $Profiles{'last-search'}; 825 if ($EmptySearch) { 826 $Profiles{''} = '-'; 827 } 828 else { 829 $Profiles{'last-search'} = '-'; 830 } 831 $Param{ProfilesStrg} = $LayoutObject->BuildSelection( 832 Data => \%Profiles, 833 Name => 'Profile', 834 ID => 'SearchProfile', 835 SelectedID => $Self->{Profile}, 836 Class => 'Modernize', 837 838 # Do not modernize this field as this causes problems with the automatic focussing of the first element. 839 ); 840 841 # Output the dynamic fields blocks, cycle trough the activated Dynamic Fields for this screen. 842 DYNAMICFIELD: 843 for my $DynamicFieldConfig ( @{ $Self->{DynamicFieldCustomerUser} }, @{ $Self->{DynamicFieldCustomerCompany} } ) { 844 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 845 846 my $SearchFieldPreferences = $DynamicFieldBackendObject->SearchFieldPreferences( 847 DynamicFieldConfig => $DynamicFieldConfig, 848 ); 849 850 next DYNAMICFIELD if !IsArrayRefWithData($SearchFieldPreferences); 851 852 PREFERENCE: 853 for my $Preference ( @{$SearchFieldPreferences} ) { 854 855 # Skip fields that HTML could not be retrieved. 856 next PREFERENCE if !IsHashRefWithData( 857 $DynamicFieldHTML{ $DynamicFieldConfig->{Name} . $Preference->{Type} } 858 ); 859 860 my $DynamicFieldLabel = $DynamicFieldHTML{ $DynamicFieldConfig->{Name} . $Preference->{Type} }->{Label}; 861 862 # Add a identifier for the object type 'CustomerCompany' and if a identifier exists. 863 if ( $DynamicFieldConfig->{ObjectType} eq 'CustomerCompany' && $TranslatedCustomerCompanyLabelIdentifier ) { 864 my $LabelCustomerCompanyLabelIdentifier 865 = ( $Preference->{LabelSuffix} ? " - " : " " ) . "($TranslatedCustomerCompanyLabelIdentifier)"; 866 $DynamicFieldLabel =~ s{(<label.*>)(.*)(</label>)}{$1$2$LabelCustomerCompanyLabelIdentifier$3}xmsg; 867 } 868 869 $LayoutObject->Block( 870 Name => 'DynamicField', 871 Data => { 872 Label => $DynamicFieldLabel, 873 Field => $DynamicFieldHTML{ $DynamicFieldConfig->{Name} . $Preference->{Type} }->{Field}, 874 }, 875 ); 876 } 877 } 878 879 my @SearchAttributes; 880 881 if ( $Self->{Profile} ) { 882 883 my %AlreadyShown; 884 885 ITEM: 886 for my $Item (@Attributes) { 887 my $Key = $Item->{Key}; 888 next ITEM if !$Key; 889 next ITEM if !defined $Param{$Key}; 890 next ITEM if $AlreadyShown{$Key}; 891 892 if ( ref $Param{$Key} eq 'ARRAY' && !@{ $Param{$Key} } ) { 893 next ITEM; 894 } 895 896 $AlreadyShown{$Key} = 1; 897 898 push @SearchAttributes, $Key; 899 } 900 } 901 902 # No profile, then show default screen. 903 else { 904 905 my %LookupDefaultFields = map { $_ => 1 } @{ $Self->{Config}->{DefaultFields}->{ $Self->{RecipientType} } }; 906 907 ITEM: 908 for my $Item (@Attributes) { 909 my $Key = $Item->{Key}; 910 911 next ITEM if !$LookupDefaultFields{$Key}; 912 913 push @SearchAttributes, $Key; 914 } 915 } 916 917 $LayoutObject->AddJSData( 918 Key => 'ShowSearchDialog', 919 Value => 1, 920 ); 921 922 $LayoutObject->AddJSData( 923 Key => 'SearchAttributes', 924 Value => \@SearchAttributes, 925 ); 926 927 # build output 928 my $Output = $LayoutObject->Output( 929 TemplateFile => 'AgentCustomerUserAddressBook', 930 Data => { 931 %Param, 932 ShowSearchDialog => 1, 933 }, 934 ); 935 936 return $Output; 937} 938 939=head2 _GetCustomerUserSearchFields() 940 941Get the search fields from the customer user map config for the given types (otherwise all search fields). 942 943 my @SearchFields = $AgentCustomerUserAddressBookObject->_GetCustomerUserSearchFields( 944 Types => ['Input', 'Selection', 'DynamicField'], # optional 945 ); 946 947=cut 948 949sub _GetCustomerUserSearchFields { 950 my ( $Self, %Param ) = @_; 951 952 my @AllSearchFields = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserSearchFields(); 953 954 return @AllSearchFields if !IsArrayRefWithData( $Param{Types} ) || !@AllSearchFields; 955 956 my @SearchFields; 957 958 TYPE: 959 for my $Type ( @{ $Param{Types} } ) { 960 961 my @TypeSearchFields = grep { $Type eq $_->{Type} } @AllSearchFields; 962 963 next TYPE if !@TypeSearchFields; 964 965 @SearchFields = ( @SearchFields, @TypeSearchFields ); 966 } 967 return @SearchFields; 968} 969 970=head2 _GetCustomerCompanySearchFields() 971 972Get the search fields from the customer user map config for the given type (otherwise all search fields) 973with a special prefix. 974 975 my @SearchFields = $AgentCustomerUserAddressBookObject->_GetCustomerCompanySearchFields( 976 Types => ['Input', 'Selection', 'DynamicField'], # optional 977 WithoutPrefix => 1, # optional 978 ); 979 980=cut 981 982sub _GetCustomerCompanySearchFields { 983 my ( $Self, %Param ) = @_; 984 985 my @AllSearchFields = $Kernel::OM->Get('Kernel::System::CustomerCompany')->CustomerCompanySearchFields(); 986 987 # add a prefix for the customer company fields 988 if ( !$Param{WithoutPrefix} ) { 989 for my $Field (@AllSearchFields) { 990 $Field->{Name} = $Self->{CustomerCompanySearchFieldPrefix} . $Field->{Name}; 991 } 992 } 993 994 return @AllSearchFields if !IsArrayRefWithData( $Param{Types} ) || !@AllSearchFields; 995 996 my @SearchFields; 997 998 TYPE: 999 for my $Type ( @{ $Param{Types} } ) { 1000 1001 my @TypeSearchFields = grep { $Type eq $_->{Type} } @AllSearchFields; 1002 1003 next TYPE if !@TypeSearchFields; 1004 1005 @SearchFields = ( @SearchFields, @TypeSearchFields ); 1006 } 1007 return @SearchFields; 1008} 1009 10101; 1011