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