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::Console::Command::Maint::Stats::Dashboard::Generate;
10
11use strict;
12use warnings;
13
14use parent qw(Kernel::System::Console::BaseCommand);
15
16our @ObjectDependencies = (
17    'Kernel::Config',
18    'Kernel::System::PID',
19    'Kernel::System::User',
20    'Kernel::System::JSON',
21    'Kernel::System::Main',
22    'Kernel::System::Stats',
23);
24
25sub Configure {
26    my ( $Self, %Param ) = @_;
27
28    $Self->Description('Generate statistics widgets for the dashboard.');
29    $Self->AddOption(
30        Name        => 'number',
31        Description => "Statistic number as shown in the overview of AgentStats.",
32        Required    => 0,
33        HasValue    => 1,
34        ValueRegex  => qr/\d+/smx,
35    );
36    $Self->AddOption(
37        Name        => 'force-pid',
38        Description => "Start even if another process is still registered in the database.",
39        Required    => 0,
40        HasValue    => 0,
41    );
42    $Self->AddOption(
43        Name        => 'debug',
44        Description => "Output debug information while running.",
45        Required    => 0,
46        HasValue    => 0,
47        ValueRegex  => qr/.*/smx,
48    );
49
50    return;
51}
52
53sub PreRun {
54    my ($Self) = @_;
55
56    my $PIDCreated = $Kernel::OM->Get('Kernel::System::PID')->PIDCreate(
57        Name  => $Self->Name(),
58        Force => $Self->GetOption('force-pid'),
59        TTL   => 60 * 60 * 6,
60    );
61    if ( !$PIDCreated ) {
62        my $Error = "Unable to register the process in the database. Is another instance still running?\n";
63        $Error .= "You can use --force-pid to override this check.\n";
64        die $Error;
65    }
66
67    return;
68}
69
70sub Run {
71    my ( $Self, %Param ) = @_;
72
73    $Self->Print("<yellow>Generating dashboard widgets statistics...</yellow>\n");
74
75    my $StatNumber = $Self->GetOption('number');
76
77    # get the list of stats that can be used in agent dashboards
78    my $Stats = $Kernel::OM->Get('Kernel::System::Stats')->StatsListGet(
79        UserID => 1,
80    );
81
82    my $DefaultLanguage = $Kernel::OM->Get('Kernel::Config')->Get('DefaultLanguage') || 'en';
83
84    STATID:
85    for my $StatID ( sort keys %{ $Stats || {} } ) {
86
87        my %Stat = %{ $Stats->{$StatID} || {} };
88
89        next STATID if $StatNumber && $StatNumber ne $Stat{StatNumber};
90        next STATID if !$Stat{ShowAsDashboardWidget};
91
92        $Self->Print("<yellow>Stat $Stat{StatNumber}: $Stat{Title}</yellow>\n");
93
94        # now find out all users which have this statistic enabled in their dashboard
95        my $DashboardActiveSetting   = 'UserDashboard' . ( 1000 + $StatID ) . "-Stats";
96        my %UsersWithActivatedWidget = $Kernel::OM->Get('Kernel::System::User')->SearchPreferences(
97            Key   => $DashboardActiveSetting,
98            Value => 1,
99        );
100
101        my $UserWidgetConfigSetting = 'UserDashboardStatsStatsConfiguration' . ( 1000 + $StatID ) . "-Stats";
102
103        # Calculate the cache for each user, if needed. If several users have the same settings
104        #   for a stat, the cache will not be recalculated.
105        USERID:
106        for my $UserID ( sort keys %UsersWithActivatedWidget ) {
107
108            my $StartTime = time();    ## no critic
109
110            # ignore invalid users
111            my %UserData = $Kernel::OM->Get('Kernel::System::User')->GetUserData(
112                UserID        => $UserID,
113                Valid         => 1,
114                NoOutOfOffice => 1,
115            );
116
117            next USERID if !%UserData;
118
119            $Self->Print("<yellow>      User: $UserData{UserLogin} ($UserID)</yellow>\n");
120
121            my $UserGetParam = {};
122            if ( $UserData{$UserWidgetConfigSetting} ) {
123                $UserGetParam = $Kernel::OM->Get('Kernel::System::JSON')->Decode(
124                    Data => $UserData{$UserWidgetConfigSetting},
125                );
126            }
127
128            if ( $Self->GetOption('debug') ) {
129                print STDERR "DEBUG: user statistic configuration data:\n";
130                print STDERR $Kernel::OM->Get('Kernel::System::Main')->Dump($UserGetParam);
131            }
132
133            $Kernel::OM->ObjectsDiscard(
134                Objects => ['Kernel::Language'],
135            );
136
137            $Kernel::OM->ObjectParamAdd(
138                'Kernel::Language' => {
139                    UserLanguage => $UserData{UserLanguage} || $DefaultLanguage,
140                },
141            );
142
143            # Now run the stat to fill the cache with the current parameters (passing the
144            #   user language for the correct caching).
145            my $Result = $Kernel::OM->Get('Kernel::System::Stats')->StatsResultCacheCompute(
146                StatID       => $StatID,
147                UserGetParam => {
148                    %{$UserGetParam},
149                    UserLanguage => $UserData{UserLanguage} || $DefaultLanguage,
150                },
151                UserID => $UserID
152            );
153
154            if ( $Self->GetOption('debug') ) {
155                print STDERR sprintf( "DEBUG: time taken: %ss\n", time() - $StartTime );    ## no critic
156            }
157
158            if ( !$Result ) {
159                $Self->PrintError("        Stat calculation was not successful.");
160            }
161        }
162    }
163
164    $Self->Print("<green>Done.</green>\n");
165    return $Self->ExitCodeOk();
166}
167
168sub PostRun {
169    my ($Self) = @_;
170
171    return $Kernel::OM->Get('Kernel::System::PID')->PIDDelete( Name => $Self->Name() );
172}
173
1741;
175