source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Stat.pm @ 1904

Last change on this file since 1904 was 1902, checked in by nanardon, 7 years ago

Revert "Reset previous value to 0 when collection stats"

This reverts commit 347da73d1d5da2e18aa507327abb299142f67be2.

File size: 8.0 KB
Line 
1package LATMOS::Accounts::Bases::Sql::Stat;
2
3use 5.010000;
4use strict;
5use warnings;
6use LATMOS::Accounts::Log;
7
8use base qw(LATMOS::Accounts::Bases::Sql::objects);
9use LATMOS::Accounts::I18N;
10
11our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
12
13=head1 NAME
14
15LATMOS::Accounts::Bases::Sql::Site - Common Location/Address object
16
17=head1 DESCRIPTION
18
19Store common to many people office address (typically building location).
20
21=cut
22
23sub _object_table { 'stat' }
24
25sub _key_field { 'name' }
26
27sub _has_extended_attributes { 1 }
28
29sub _get_attr_schema {
30    my ($class, $base) = @_;
31
32    $class->SUPER::_get_attr_schema($base,
33        {
34            name   => { ro => 1, inline => 1, },
35            cn     => { ro => 1, inline => 1, iname => 'name' },
36            date   => { ro => 1, inline => 1, },
37            create => { ro => 1, inline => 1, },
38            filter => { multiple => 1 },
39            refFilter => { multiple => 1 },
40            refall => { },
41            otype  => { },
42            attribute => { },
43            description => { },
44            delay => { },
45            lastStatId => { },
46            aggregateFunction => {
47                can_values => sub { qw(sum avg count) },
48            },
49            nullValue => { },
50            display => { },
51            needRun => {
52                ro => 1,
53                managed => 1,
54                get => sub {
55                    my ($attr) = @_;
56                    my ($self) = $attr->object;
57
58                    my $days = $self->_get_attributes('delay') || 7;
59                    my $sth = $self->db->prepare(
60                        q{
61                        select tstamp from statsentry where okey = ?
62                            and tstamp > now() - (? * '1 day'::interval)
63                            order by tstamp desc
64                            limit 1
65                        }
66                    );
67                    $sth->execute($self->Iid, $days);
68                    if (my $res = $sth->fetchrow_hashref) {
69                        $self->base->log(LA_DEBUG, "Stat %s done recently: %s", $self->id, $res->{tstamp});
70                        return undef;
71                    } else {
72                        return 1;
73                    }
74                },
75            },
76        }
77    )
78}
79
80=head2 compute()
81
82Compute stat value and return hash with var/val peer value
83
84=cut
85
86sub compute {
87    my ($self) = @_;
88
89    my $otype = $self->_get_attributes('otype') or return;
90    my $attribute = $self->_get_attributes('attribute') or return;
91
92    my %stats;
93    my $reffiltered = undef;
94
95    my $op = $self->_get_attributes('aggregateFunction');
96
97    my ($refOtype, $refAttr) = ($otype, undef);
98
99    foreach (split(/\./, $attribute)) {
100        if (my $attr = $self->base->attribute($refOtype, $_)) {
101            if (my $obj = $attr->reference) {
102                ($refOtype, $refAttr) = ($obj, $attr);
103            } else {
104                ($refOtype, $refAttr) = (undef, undef);
105            }
106        }
107    }
108
109    if ($refAttr && $refOtype) {
110        if (my @reffilter = $self->_get_attributes('refFilter')) {
111            $reffiltered = {};
112            foreach ($self->base->search_objects($refOtype, @reffilter)) {
113                $reffiltered->{$_} = 1;
114            }
115        }
116        if ($self->_get_attributes('refall') && $refAttr->has_values_list && !$op) {
117            foreach ($refAttr->can_values) {
118                if ($reffiltered && !$reffiltered->{$_}) {
119                    next;
120                }
121                $stats{$_} = 0;
122            } 
123        }
124    } else {
125        $self->base->log(LA_ERR, "Cannot find attribute %s for object type %s", $attribute, $otype);
126    }
127
128    my %filtered;
129    if (my @fil = $self->_get_attributes('filter')) {
130        %filtered = map { $_ => 1 } $self->base->search_objects($otype, @fil);
131    } else {
132        %filtered = map { $_ => 1 } $self->base->list_objects($otype);
133    }
134
135    my %results = $self->base->attributes_summary_by_object($otype, $attribute);
136
137    my $nullValue = $self->_get_attributes('nullValue');
138    my %aggdata;
139    if ($nullValue) {
140        $results{ $_ } ||= [''] foreach(keys %filtered);
141    }
142    foreach my $id (keys %results) {
143        $filtered{ $id } or next;
144        foreach (@{ $results{ $id }}) {
145            next unless (defined($_) || $nullValue);
146            if ($_ && $reffiltered && !$reffiltered->{$_}) {
147                next;
148            }
149            defined($_) && $_ ne '' or $_ = '(none)';
150            if ($op) {
151                push(@{$aggdata{$id}}, $_);
152            } else {
153                $stats{ $_ } ||= 0;
154                $stats{ $_ }++;
155            }
156        }
157    }
158    if ($op) {
159        foreach my $key (keys %aggdata) {
160            if ($op eq 'sum') {
161                my $sum = 0;
162                $sum += $_ foreach (@{ $aggdata{$key} });
163                $stats{ $key } = $sum;
164            }
165            elsif ($op eq 'count') {
166                $stats{ $key } = scalar(@{ $aggdata{$key} });
167            }
168            elsif ($op eq 'average') {
169                my $sum = 0;
170                $sum += $_ foreach (@{ $aggdata{$key} });
171                $stats{ $key } = $sum / scalar(@{ $aggdata{$key} });
172            }
173        }
174    }
175
176    return \%stats;
177}
178
179=head2 collect()
180
181Store statistics for $attribute on $otype. @filters allow to limit result on
182$otype object matching the filters
183
184=cut
185
186sub collect {
187    my ($self) = @_;
188
189    my $otype = $self->_get_attributes('otype') or return;
190    my $attribute = $self->_get_attributes('attribute') or return;
191
192    if (!$self->_get_attributes('needRun')) {
193        return;
194    }
195
196    $self->base->log(LA_NOTICE, "Collecting data for stat: %s", $self->id);
197
198    my $stats = $self->compute();
199
200    my $sthr = $self->db->prepare(
201        q{ INSERT INTO statsentry (okey) values (?) }
202    );
203    $sthr->execute($self->Iid);
204
205    my $id = $self->db->last_insert_id(undef,undef,'statsentry',undef);
206
207    my $sthv =  $self->db->prepare(
208        q{
209        INSERT INTO statvalues (sid, value, count) values (?,?,?)
210        }
211    );
212    foreach (keys %$stats) {
213        $sthv->execute($id, $_, $stats->{$_});
214    }
215    $self->_set_c_fields('lastStatId' => $id) or do {
216        $self->base->log(LA_ERR, "Cannot update Stat object");
217        return;
218    };
219
220    return 1;
221}
222
223=head2 getStat($id)
224
225Return the statistics value for this stat entry.
226
227If not given, C<$id> will be the last entry found
228
229=cut
230
231sub getStat {
232    my ($self, $id) = @_;
233
234    ($id) ||= $self->_get_attributes('lastStatId');
235
236    if (!$id) {
237        $self->base->log(LA_ERR, "No Stat Id given for stat name %s", $self->id);
238        return;
239    }
240
241    my $sthentry = $self->db->prepare('SELECT * from statsentry where okey = ? and id = ?');
242    $sthentry->execute($self->Iid, $id);
243    if (!(my $res = $sthentry->fetchrow_hashref)) {
244        $self->base->log(LA_ERR, "No stat entry %d found for stat %s", $id, $self->id);
245        return;
246    }
247
248    my $sthvalues = $self->db->prepare("SELECT * FROM statvalues where sid = ?");
249    $sthvalues->execute($id);
250
251    my $stats = {};
252    while (my $res = $sthvalues->fetchrow_hashref) {
253        $stats->{$res->{value}} = $res->{count};
254    }
255
256    $stats
257}
258
259=head2 getAllStat()
260
261Return a hashref containing all statistics value per date
262
263=cut
264
265sub getAllStat {
266    my ($self) = @_;
267
268    my $sth = $self->db->prepare(q{
269        SELECT count, value, to_char(tstamp, 'YYYY-MM-DD HH24:MI') as d from statsentry join
270                      statvalues
271            on statsentry.id = statvalues.sid
272            where statsentry.okey = ?
273                order by statsentry.tstamp, value
274    });
275    $sth->execute($self->Iid);
276
277    my $stats = {};
278    while(my $res = $sth->fetchrow_hashref) {
279        $stats->{$res->{d}}{$res->{value}} = $res->{count};
280    }
281
282    return $stats;
283}
284
2851;
286
287__END__
288
289=head1 SEE ALSO
290
291L<LATMOS::Accounts::Bases::Sql>
292
293=head1 AUTHOR
294
295Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
296
297=head1 COPYRIGHT AND LICENSE
298
299Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS
300
301This library is free software; you can redistribute it and/or modify
302it under the same terms as Perl itself, either Perl version 5.10.0 or,
303at your option, any later version of Perl 5 you may have available.
304
305
306=cut
Note: See TracBrowser for help on using the repository browser.