Bug 11230 - Refactor C4::Stats::UpdateStats and add UT
[koha.git] / C4 / Log.pm
1 package C4::Log;
2
3 #package to deal with Logging Actions in DB
4
5
6 # Copyright 2000-2002 Katipo Communications
7 # Copyright 2011 MJ Ray and software.coop
8 #
9 # This file is part of Koha.
10 #
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 #
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License along
21 # with Koha; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24 use strict;
25 use warnings;
26
27 use C4::Context;
28 use C4::Dates qw(format_date);
29
30 use vars qw($VERSION @ISA @EXPORT);
31
32 BEGIN {
33         # set the version for version checking
34     $VERSION = 3.07.00.049;
35         require Exporter;
36         @ISA = qw(Exporter);
37         @EXPORT = qw(&logaction &GetLogStatus &displaylog &GetLogs);
38 }
39
40 =head1 NAME
41
42 C4::Log - Koha Log Facility functions
43
44 =head1 SYNOPSIS
45
46   use C4::Log;
47
48 =head1 DESCRIPTION
49
50 The functions in this module perform various functions in order to log all the operations done on the Database, including deleting and undeleting books, adding/editing members, etc.
51
52 =head1 FUNCTIONS
53
54 =over 2
55
56 =item logaction
57
58   &logaction($modulename, $actionname, $objectnumber, $infos);
59
60 Adds a record into action_logs table to report the different changes upon the database.
61 Each log entry includes the number of the user currently logged in.  For batch
62 jobs, which operate without authenticating a user and setting up a session, the user
63 number is set to 0, which is the same as the superlibrarian's number.
64
65 =cut
66
67 #'
68 sub logaction {
69     my ($modulename, $actionname, $objectnumber, $infos)=@_;
70
71     # Get ID of logged in user.  if called from a batch job,
72     # no user session exists and C4::Context->userenv() returns
73     # the scalar '0'.
74     my $userenv = C4::Context->userenv();
75     my $usernumber = (ref($userenv) eq 'HASH') ? $userenv->{'number'} : 0;
76     $usernumber ||= 0;
77
78     my $dbh = C4::Context->dbh;
79     my $sth=$dbh->prepare("Insert into action_logs (timestamp,user,module,action,object,info) values (now(),?,?,?,?,?)");
80     $sth->execute($usernumber,$modulename,$actionname,$objectnumber,$infos);
81     $sth->finish;
82 }
83
84 =item GetLogStatus
85
86   $status = GetLogStatus;
87
88 C<$status> is a hasref like this example:
89     $hash = {
90         BorrowersLog   => 1,
91         CataloguingLog => 0,
92         IssueLog       => 0,
93         ...
94     }
95
96 =cut
97
98 #'
99 sub GetLogStatus {
100     my %hash;
101     $hash{BorrowersLog}    = C4::Context->preference("BorrowersLog");
102     $hash{CataloguingLog}  = C4::Context->preference("CataloguingLog");
103     $hash{IssueLog}        = C4::Context->preference("IssueLog");
104     $hash{ReturnLog}       = C4::Context->preference("ReturnLog");
105     $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog");
106     $hash{LetterLog}       = C4::Context->preference("LetterLog");
107     $hash{FinesLog}        = C4::Context->preference("FinesLog");
108     return \%hash;
109 }
110
111 =item displaylog
112
113   &displaylog($modulename, @filters);
114   $modulename is the name of the module on which the user wants to display logs
115   @filters is an optional table of hash containing :
116       - name : the name of the variable to filter
117     - value : the value of the filter.... May be with * joker
118
119 returns a table of hash containing who did what on which object at what time
120
121 =cut
122
123 #'
124 sub displaylog {
125   my ($modulename, @filters) = @_;
126     my $dbh = C4::Context->dbh;
127     my $strsth=qq|
128                 SELECT action_logs.timestamp, action_logs.action, action_logs.info,
129                                 borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
130                         biblio.biblionumber, biblio.title, biblio.author
131         FROM action_logs 
132                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
133         LEFT JOIN  biblio   ON action_logs.object=biblio.biblionumber
134         WHERE action_logs.module = 'cataloguing' 
135         |;
136         my %filtermap = ();
137     if ($modulename eq "catalogue" or $modulename eq "acqui") {
138                 %filtermap = (
139                           user => 'borrowers.surname',
140                          title => 'biblio.title',
141                         author => 'biblio.author',
142                 );
143     } elsif ($modulename eq "members") {
144         $strsth=qq|
145                 SELECT action_logs.timestamp, action_logs.action, action_logs.info, 
146                         borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
147                         bor2.cardnumber, bor2.surname, bor2.firstname, bor2.userid
148         FROM action_logs 
149                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
150                 LEFT JOIN borrowers as bor2 ON action_logs.object=bor2.borrowernumber
151         WHERE action_logs.module = 'members' 
152                 |;
153                 %filtermap = (
154                        user => 'borrowers.surname',
155                     surname => 'bor2.surname',
156                   firstname => 'bor2.firstname',
157                  cardnumber => 'bor2.cardnumber',
158                 );
159     } else {
160                 return 0;
161         }
162
163     if (@filters) {
164                 foreach my $filter (@filters) {
165                         my $tempname = $filter->{name}         or next;
166                         (grep {/^$tempname$/} keys %filtermap) or next;
167                         $filter->{value} =~ s/\*/%/g;
168                         $strsth .= " AND " . $filtermap{$tempname} . " LIKE " . $filter->{value};
169                 }
170         }
171     my $sth=$dbh->prepare($strsth);
172     $sth->execute;
173     my @results;
174     my $count;
175     my $hilighted=1;
176     while (my $data = $sth->fetchrow_hashref){
177         $data->{hilighted} = ($hilighted>0);
178         $data->{info} =~ s/\n/<br\/>/g;
179         $data->{day} = format_date($data->{timestamp});
180         push @results, $data;
181         $count++;
182         $hilighted = -$hilighted;
183     }
184     return ($count, \@results);
185 }
186
187 =item GetLogs
188
189 $logs = GetLogs($datefrom,$dateto,$user,\@modules,$action,$object,$info);
190
191 Return: 
192 C<$logs> is a ref to a hash which containts all columns from action_logs
193
194 =cut
195
196 sub GetLogs {
197     my $datefrom = shift;
198     my $dateto   = shift;
199     my $user     = shift;
200     my $modules   = shift;
201     my $action   = shift;
202     my $object   = shift;
203     my $info     = shift;
204    
205     my $iso_datefrom = C4::Dates->new($datefrom,C4::Context->preference("dateformat"))->output('iso');
206     my $iso_dateto = C4::Dates->new($dateto,C4::Context->preference("dateformat"))->output('iso');
207
208     my $dbh = C4::Context->dbh;
209     my $query = "
210         SELECT *
211         FROM   action_logs
212         WHERE 1
213     ";
214
215     my @parameters;
216     $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') >= \"".$iso_datefrom."\" " if $iso_datefrom;   #fix me - mysql specific
217     $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') <= \"".$iso_dateto."\" " if $iso_dateto;
218     if($user ne "") {
219         $query .= " AND user = ? ";
220         push(@parameters,$user);
221     }
222     if($modules && scalar(@$modules)) {
223         $query .= " AND module IN (".join(",",map {"?"} @$modules).") ";
224         push(@parameters,@$modules);
225     }
226     if($action && scalar(@$action)) {
227         $query .= " AND action IN (".join(",",map {"?"} @$action).") ";
228         push(@parameters,@$action);
229     }
230     if($object) {
231         $query .= " AND object = ? ";
232         push(@parameters,$object);
233     }
234     if($info) {
235         $query .= " AND info LIKE ? ";
236         push(@parameters,"%".$info."%");
237     }
238    
239     my $sth = $dbh->prepare($query);
240     $sth->execute(@parameters);
241     
242     my @logs;
243     while( my $row = $sth->fetchrow_hashref ) {
244         $row->{$row->{module}} = 1;
245         push @logs , $row;
246     }
247     return \@logs;
248 }
249
250 1;
251 __END__
252
253 =back
254
255 =head1 AUTHOR
256
257 Koha Development Team <http://koha-community.org/>
258
259 =cut