Bug 7331 - Circulation.pl generates errors in the log
[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.01;
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
77     my $dbh = C4::Context->dbh;
78     my $sth=$dbh->prepare("Insert into action_logs (timestamp,user,module,action,object,info) values (now(),?,?,?,?,?)");
79     $sth->execute($usernumber,$modulename,$actionname,$objectnumber,$infos);
80     $sth->finish;
81 }
82
83 =item GetLogStatus
84
85   $status = GetLogStatus;
86
87 C<$status> is a hasref like this example:
88     $hash = {
89         BorrowersLog   => 1,
90         CataloguingLog => 0,
91         IssueLog       => 0,
92         ...
93     }
94
95 =cut
96
97 #'
98 sub GetLogStatus {
99     my %hash;
100     $hash{BorrowersLog}    = C4::Context->preference("BorrowersLog");
101     $hash{CataloguingLog}  = C4::Context->preference("CataloguingLog");
102     $hash{IssueLog}        = C4::Context->preference("IssueLog");
103     $hash{ReturnLog}       = C4::Context->preference("ReturnLog");
104     $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog");
105     $hash{LetterLog}       = C4::Context->preference("LetterLog");
106     $hash{FinesLog}        = C4::Context->preference("FinesLog");
107     return \%hash;
108 }
109
110 =item displaylog
111
112   &displaylog($modulename, @filters);
113   $modulename is the name of the module on which the user wants to display logs
114   @filters is an optional table of hash containing :
115       - name : the name of the variable to filter
116     - value : the value of the filter.... May be with * joker
117
118 returns a table of hash containing who did what on which object at what time
119
120 =cut
121
122 #'
123 sub displaylog {
124   my ($modulename, @filters) = @_;
125     my $dbh = C4::Context->dbh;
126     my $strsth=qq|
127                 SELECT action_logs.timestamp, action_logs.action, action_logs.info,
128                                 borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
129                         biblio.biblionumber, biblio.title, biblio.author
130         FROM action_logs 
131                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
132         LEFT JOIN  biblio   ON action_logs.object=biblio.biblionumber
133         WHERE action_logs.module = 'cataloguing' 
134         |;
135         my %filtermap = ();
136     if ($modulename eq "catalogue" or $modulename eq "acqui") {
137                 %filtermap = (
138                           user => 'borrowers.surname',
139                          title => 'biblio.title',
140                         author => 'biblio.author',
141                 );
142     } elsif ($modulename eq "members") {
143         $strsth=qq|
144                 SELECT action_logs.timestamp, action_logs.action, action_logs.info, 
145                         borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
146                         bor2.cardnumber, bor2.surname, bor2.firstname, bor2.userid
147         FROM action_logs 
148                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
149                 LEFT JOIN borrowers as bor2 ON action_logs.object=bor2.borrowernumber
150         WHERE action_logs.module = 'members' 
151                 |;
152                 %filtermap = (
153                        user => 'borrowers.surname',
154                     surname => 'bor2.surname',
155                   firstname => 'bor2.firstname',
156                  cardnumber => 'bor2.cardnumber',
157                 );
158     } else {
159                 return 0;
160         }
161
162     if (@filters) {
163                 foreach my $filter (@filters) {
164                         my $tempname = $filter->{name}         or next;
165                         (grep {/^$tempname$/} keys %filtermap) or next;
166                         $filter->{value} =~ s/\*/%/g;
167                         $strsth .= " AND " . $filtermap{$tempname} . " LIKE " . $filter->{value};
168                 }
169         }
170     my $sth=$dbh->prepare($strsth);
171     $sth->execute;
172     my @results;
173     my $count;
174     my $hilighted=1;
175     while (my $data = $sth->fetchrow_hashref){
176         $data->{hilighted} = ($hilighted>0);
177         $data->{info} =~ s/\n/<br\/>/g;
178         $data->{day} = format_date($data->{timestamp});
179         push @results, $data;
180         $count++;
181         $hilighted = -$hilighted;
182     }
183     return ($count, \@results);
184 }
185
186 =item GetLogs
187
188 $logs = GetLogs($datefrom,$dateto,$user,\@modules,$action,$object,$info);
189
190 Return: 
191 C<$logs> is a ref to a hash which containts all columns from action_logs
192
193 =cut
194
195 sub GetLogs {
196     my $datefrom = shift;
197     my $dateto   = shift;
198     my $user     = shift;
199     my $modules   = shift;
200     my $action   = shift;
201     my $object   = shift;
202     my $info     = shift;
203    
204     my $iso_datefrom = C4::Dates->new($datefrom,C4::Context->preference("dateformat"))->output('iso');
205     my $iso_dateto = C4::Dates->new($dateto,C4::Context->preference("dateformat"))->output('iso');
206
207     my $dbh = C4::Context->dbh;
208     my $query = "
209         SELECT *
210         FROM   action_logs
211         WHERE 1
212     ";
213
214     my @parameters;
215     $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') >= \"".$iso_datefrom."\" " if $iso_datefrom;   #fix me - mysql specific
216     $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') <= \"".$iso_dateto."\" " if $iso_dateto;
217     if($user ne "") {
218         $query .= " AND user = ? ";
219         push(@parameters,$user);
220     }
221     if($modules && scalar(@$modules)) {
222         $query .= " AND module IN (".join(",",map {"?"} @$modules).") ";
223         push(@parameters,@$modules);
224     }
225     if($action && scalar(@$action)) {
226         $query .= " AND action IN (".join(",",map {"?"} @$action).") ";
227         push(@parameters,@$action);
228     }
229     if($object) {
230         $query .= " AND object = ? ";
231         push(@parameters,$object);
232     }
233     if($info) {
234         $query .= " AND info LIKE ? ";
235         push(@parameters,"%".$info."%");
236     }
237    
238     my $sth = $dbh->prepare($query);
239     $sth->execute(@parameters);
240     
241     my @logs;
242     while( my $row = $sth->fetchrow_hashref ) {
243         $row->{$row->{module}} = 1;
244         push @logs , $row;
245     }
246     return \@logs;
247 }
248
249 1;
250 __END__
251
252 =back
253
254 =head1 AUTHOR
255
256 Koha Development Team <http://koha-community.org/>
257
258 =cut