View | Details | Raw Unified | Return to bug 20750
Collapse All | Expand All

(-)a/Koha/Illrequest.pm (-14 / +71 lines)
Lines 32-37 use Koha::Exceptions::Ill; Link Here
32
use Koha::Illcomments;
32
use Koha::Illcomments;
33
use Koha::Illrequestattributes;
33
use Koha::Illrequestattributes;
34
use Koha::AuthorisedValue;
34
use Koha::AuthorisedValue;
35
use Koha::Illrequest::Logger;
35
use Koha::Patron;
36
use Koha::Patron;
36
use Koha::AuthorisedValues;
37
use Koha::AuthorisedValues;
37
38
Lines 157-162 sub illcomments { Link Here
157
    );
158
    );
158
}
159
}
159
160
161
=head3 logs
162
163
=cut
164
165
sub logs {
166
    my ( $self ) = @_;
167
    my $logger = Koha::Illrequest::Logger->new;
168
    return $logger->get_request_logs($self);
169
}
170
160
=head3 patron
171
=head3 patron
161
172
162
=cut
173
=cut
Lines 210-234 sub status_alias { Link Here
210
221
211
=head3 status
222
=head3 status
212
223
224
    $Illrequest->status('CANREQ');
225
213
Overloaded getter/setter for request status,
226
Overloaded getter/setter for request status,
214
also nullifies status_alias
227
also nullifies status_alias and records the fact that the status has changed
215
228
216
=cut
229
=cut
217
230
218
sub status {
231
sub status {
219
    my ( $self, $newval) = @_;
232
    my ( $self, $new_status) = @_;
220
    if ($newval) {
233
221
        # This is hackery to enable us to undefine
234
    my $current_status = $self->SUPER::status;
222
        # status_alias, since we need to have an overloaded
235
223
        # status_alias method to get us around the problem described
236
    if ($new_status) {
224
        # here:
237
        # Keep a record of the previous status before we change it,
225
        # https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=20581#c156
238
        # we might need it
226
        # We need a way of passing implied undef to nullify status_alias
239
        $self->{previous_status} = $current_status;
227
        # so we pass -1, which is special cased in the overloaded setter
240
        my $ret = $self->SUPER::status($new_status)->store;
228
        $self->status_alias("-1");
241
        if ($ret) {
229
        return $self->SUPER::status($newval);
242
            # This is hackery to enable us to undefine
243
            # status_alias, since we need to have an overloaded
244
            # status_alias method to get us around the problem described
245
            # here:
246
            # https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=20581#c156
247
            # We need a way of passing implied undef to nullify status_alias
248
            # so we pass -1, which is special cased in the overloaded setter
249
            $self->status_alias("-1");
250
            my $logger = Koha::Illrequest::Logger->new;
251
            $logger->log_status_change(
252
                $self,
253
                $new_status
254
            );
255
        } else {
256
            delete $self->{previous_status};
257
        }
258
        return $ret;
259
    } else {
260
        return $current_status;
230
    }
261
    }
231
    return $self->SUPER::status;
232
}
262
}
233
263
234
=head3 load_backend
264
=head3 load_backend
Lines 252-258 sub load_backend { Link Here
252
    my $location = join "/", @raw, $backend_name, "Base.pm";    # File to load
282
    my $location = join "/", @raw, $backend_name, "Base.pm";    # File to load
253
    my $backend_class = join "::", @raw, $backend_name, "Base"; # Package name
283
    my $backend_class = join "::", @raw, $backend_name, "Base"; # Package name
254
    require $location;
284
    require $location;
255
    $self->{_my_backend} = $backend_class->new({ config => $self->_config });
285
    $self->{_my_backend} = $backend_class->new({
286
        config => $self->_config,
287
        logger => Koha::Illrequest::Logger->new
288
    });
256
    return $self;
289
    return $self;
257
}
290
}
258
291
Lines 1107-1112 sub _censor { Link Here
1107
    return $params;
1140
    return $params;
1108
}
1141
}
1109
1142
1143
=head3 store
1144
1145
    $Illrequest->store;
1146
1147
Overloaded I<store> method that, in addition to performing the 'store',
1148
possibly records the fact that something happened
1149
1150
=cut
1151
1152
sub store {
1153
    my ( $self, $attrs ) = @_;
1154
1155
    my $ret = $self->SUPER::store;
1156
1157
    $attrs->{log_origin} = 'core';
1158
1159
    if ($ret && defined $attrs) {
1160
        my $logger = Koha::Illrequest::Logger->new;
1161
        $logger->log_maybe($self, $attrs);
1162
    }
1163
1164
    return $ret;
1165
}
1166
1110
=head3 TO_JSON
1167
=head3 TO_JSON
1111
1168
1112
    $json = $illrequest->TO_JSON
1169
    $json = $illrequest->TO_JSON
(-)a/Koha/Illrequest/Logger.pm (+242 lines)
Line 0 Link Here
1
package Koha::Illrequest::Logger;
2
3
# Copyright 2018 PTFS Europe Ltd
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
use JSON qw( to_json from_json );
22
23
use C4::Context;
24
use C4::Templates;
25
use C4::Log qw( logaction GetLogs );
26
27
=head1 NAME
28
29
Koha::Illrequest::Logger - Koha ILL Action / Event logger
30
31
=head1 SYNOPSIS
32
33
Object-oriented class that provides event logging functionality for
34
ILL requests
35
36
=head1 DESCRIPTION
37
38
This class provides the ability to log arbitrary actions or events
39
relating to Illrequest to the action log.
40
41
=head1 API
42
43
=head2 Class Methods
44
45
=head3 new
46
47
    my $config = Koha::Illrequest::Logger->new();
48
49
Create a new Koha::Illrequest::Logger object, with skeleton logging data
50
We also set up data of what can be logged, how to do it and how to display
51
log entries we get back out
52
53
=cut
54
55
sub new {
56
    my ( $class ) = @_;
57
    my $self  = {};
58
59
    $self->{data} = {
60
        modulename => 'ILL'
61
    };
62
63
    $self->{loggers} = {
64
        status => sub {
65
            $self->log_status_change(@_);
66
        }
67
    };
68
69
    my ( $htdocs, $theme, $lang, $base ) =
70
        C4::Templates::_get_template_file('ill/log/', 'intranet');
71
72
    $self->{templates} = {
73
        STATUS_CHANGE => $base . 'status_change.tt'
74
    };
75
76
    bless $self, $class;
77
78
    return $self;
79
}
80
81
=head3 log_maybe
82
83
    Koha::IllRequest::Logger->log_maybe($attrs);
84
85
Receive request object and an attributes hashref (which may or may
86
not be defined) If the hashref contains a key matching our "loggers" hashref
87
then we want to log it
88
89
=cut
90
91
sub log_maybe {
92
    my ($self, $req, $attrs) = @_;
93
94
    if (defined $req && defined $attrs) {
95
        foreach my $key (keys %{ $attrs }) {
96
            if (defined($self->{loggers}->{$key})) {
97
                $self->{loggers}->{$key}($req, $attrs->{$key});
98
            }
99
        }
100
    }
101
}
102
103
=head3 log_status_change
104
105
    Koha::IllRequest::Logger->log_status_change();
106
107
Log a request's status change
108
109
=cut
110
111
sub log_status_change {
112
    my ( $self, $req, $new_status ) = @_;
113
114
    $self->set_data({
115
        actionname   => 'STATUS_CHANGE',
116
        objectnumber => $req->id,
117
        infos        => to_json({
118
            log_origin    => 'core',
119
            status_before => $req->{previous_status},
120
            status_after  => $new_status
121
        })
122
    });
123
124
    $self->log_something();
125
}
126
127
=head3 log_something
128
129
    Koha::IllRequest::Logger->log_something();
130
131
If we have the required data set, log an action
132
133
=cut
134
135
sub log_something {
136
    my ( $self ) = @_;
137
138
    if (
139
        defined $self->{data}->{modulename} &&
140
        defined $self->{data}->{actionname} &&
141
        defined $self->{data}->{objectnumber} &&
142
        defined $self->{data}->{infos} &&
143
        C4::Context->preference("IllLog")
144
    ) {
145
        logaction(
146
            $self->{data}->{modulename},
147
            $self->{data}->{actionname},
148
            $self->{data}->{objectnumber},
149
            $self->{data}->{infos}
150
        );
151
    }
152
}
153
154
=head3 set_data
155
156
    Koha::IllRequest::Logger->set_data({
157
        key  => 'value',
158
        key2 => 'value2'
159
    });
160
161
Set arbitrary data propert(ies) on the logger object
162
163
=cut
164
165
sub set_data {
166
    my ( $self, $data ) = @_;
167
168
    foreach my $key (keys %{ $data }) {
169
        $self->{data}->{$key} = $data->{$key};
170
    }
171
}
172
173
=head3 get_log_template
174
175
    $template_path = get_log_template($origin, $action);
176
177
Given a log's origin and action, get the appropriate display template
178
179
=cut
180
181
sub get_log_template {
182
    my ($self, $req, $params) = @_;
183
184
    my $origin = $params->{origin};
185
    my $action = $params->{action};
186
187
    if ($origin eq 'core') {
188
        # It's a core log, so we can just get the template path from
189
        # the hashref above
190
        return $self->{templates}->{$action};
191
    } else {
192
        # It's probably a backend log, so we need to get the path to the
193
        # template from the backend
194
        my $backend =$req->{_my_backend};
195
        return $backend->get_log_template_path($action);
196
    }
197
}
198
199
=head3 get_request_logs
200
201
    $requestlogs = Koha::IllRequest::Logger->get_request_logs($request_id);
202
203
Get all logged actions for a given request
204
205
=cut
206
207
sub get_request_logs {
208
    my ( $self, $request ) = @_;
209
210
    my $logs = GetLogs(
211
        undef,
212
        undef,
213
        undef,
214
        ['ILL'],
215
        undef,
216
        $request->id,
217
        undef,
218
        undef
219
    );
220
    foreach my $log(@{$logs}) {
221
        $log->{info} = from_json($log->{info});
222
        $log->{template} = $self->get_log_template(
223
        $request,
224
            {
225
                origin => $log->{info}->{log_origin},
226
                action => $log->{action}
227
            }
228
        );
229
    }
230
231
    my @sorted = sort {$$b{'timestamp'} <=> $$a{'timestamp'}} @{$logs};
232
233
    return \@sorted;
234
}
235
236
=head1 AUTHOR
237
238
Andrew Isherwood <andrew.isherwood@ptfs-europe.com>
239
240
=cut
241
242
1;
(-)a/installer/data/mysql/atomicupdate/bug_20750-add_illlog_preference.perl (+7 lines)
Line 0 Link Here
1
$DBversion = 'XXX';  # will be replaced by the RM
2
if( CheckVersion( $DBversion ) ) {
3
    $dbh->do( "INSERT IGNORE INTO systempreferences (variable, value, explanation, type) VALUES ('IllLog', 1, 'If ON, log information about ILL requests', 'YesNo')" );
4
5
    SetVersion( $DBversion );
6
    print "Upgrade to $DBversion done (Bug 20750 - Allow timestamped auditing of ILL request events)\n";
7
}
(-)a/installer/data/mysql/en/optional/ill_logging_pref.sql (+1 lines)
Line 0 Link Here
1
INSERT IGNORE INTO systempreferences (variable, value, explanation, type) VALUES ('IllLog', 1, 'If ON, log information about ILL requests', 'YesNo');
(-)a/installer/data/mysql/en/optional/ill_logging_pref.txt (+1 lines)
Line 0 Link Here
1
System preference to determine if logging of ILL requests should occur
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 216-221 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
216
('IDreamBooksResults','0','','Display IDreamBooks.com rating in search results','YesNo'),
216
('IDreamBooksResults','0','','Display IDreamBooks.com rating in search results','YesNo'),
217
('IDreamBooksReviews','0','','Display book review snippets from IDreamBooks.com','YesNo'),
217
('IDreamBooksReviews','0','','Display book review snippets from IDreamBooks.com','YesNo'),
218
('IdRef','0','','Disable/enable the IdRef webservice from the OPAC detail page.','YesNo'),
218
('IdRef','0','','Disable/enable the IdRef webservice from the OPAC detail page.','YesNo'),
219
('IllLog', 1, '', 'If ON, log information about ILL requests', 'YesNo'),
219
('ILLModule','0','If ON, enables the interlibrary loans module.','','YesNo'),
220
('ILLModule','0','If ON, enables the interlibrary loans module.','','YesNo'),
220
('ILLModuleCopyrightClearance','','70|10','Enter text to enable the copyright clearance stage of request creation. Text will be displayed','Textarea'),
221
('ILLModuleCopyrightClearance','','70|10','Enter text to enable the copyright clearance stage of request creation. Text will be displayed','Textarea'),
221
('ILS-DI','0','','Enables ILS-DI services at OPAC.','YesNo'),
222
('ILS-DI','0','','Enables ILS-DI services at OPAC.','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/logs.pref (+6 lines)
Lines 37-42 Logging: Link Here
37
                  off: "Don't log"
37
                  off: "Don't log"
38
            - any actions on holds (create, cancel, suspend, resume, etc).
38
            - any actions on holds (create, cancel, suspend, resume, etc).
39
        -
39
        -
40
            - pref: IllLog
41
              choices:
42
                  on: Log
43
                  off: "Don't log"
44
            - when changes to ILL requests take place
45
        -
40
            - pref: IssueLog
46
            - pref: IssueLog
41
              choices:
47
              choices:
42
                  on: Log
48
                  on: Log
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt (-1 / +35 lines)
Lines 319-324 Link Here
319
                            <span class="fa fa-eye"></span>
319
                            <span class="fa fa-eye"></span>
320
                            Display supplier metadata
320
                            Display supplier metadata
321
                        </a>
321
                        </a>
322
                        <a title="Display request log" id="ill-request-display-log" class="btn btn-sm btn-default pull-right" href="#">
323
                            <span class="fa fa-calendar"></span>
324
                            Display request log
325
                        </a>
322
                    </div>
326
                    </div>
323
                    <div class="ill-view-panel panel panel-default">
327
                    <div class="ill-view-panel panel panel-default">
324
                        <div class="panel-heading">
328
                        <div class="panel-heading">
Lines 429-434 Link Here
429
                        </div>
433
                        </div>
430
                    </div>
434
                    </div>
431
435
436
                    <div id="requestLog" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="dataPreviewLabel" aria-hidden="true">
437
                        <div class="modal-dialog">
438
                            <div class="modal-content">
439
                                <div class="modal-header">
440
                                    <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
441
                                    <h3 id="requestLogLabel"> Request log</h3>
442
                                </div>
443
                                <div class="modal-body">
444
                                [% IF request.logs.size > 0 %]
445
                                    [% FOREACH log IN request.logs %]
446
                                        [% tpl = log.template %]
447
                                        [% INCLUDE $tpl %]
448
                                    [% END %]
449
                                [% ELSE %]
450
                                    There are no recorded logs for this request
451
                                [% END %]
452
                                </div>
453
                                <div class="modal-footer">
454
                                    <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
455
                                </div>
456
                            </div>
457
                        </div>
458
                    </div>
459
432
                    <div class="ill-view-panel panel panel-default">
460
                    <div class="ill-view-panel panel panel-default">
433
                        <div class="panel-heading">
461
                        <div class="panel-heading">
434
                            <h3>[% request.illcomments.count | html %] comments</h3>
462
                            <h3>[% request.illcomments.count | html %] comments</h3>
Lines 467-473 Link Here
467
                                        </form>
495
                                        </form>
468
                                    </div>
496
                                    </div>
469
                                </div>
497
                                </div>
470
                            </div>
498
                        </div>
471
                    </div>
499
                    </div>
472
500
473
                [% ELSIF query_type == 'illlist' %]
501
                [% ELSIF query_type == 'illlist' %]
Lines 835-840 Link Here
835
                }
863
                }
836
            };
864
            };
837
865
866
            // Display the modal containing request supplier metadata
867
            $('#ill-request-display-log').on('click', function(e) {
868
                e.preventDefault();
869
                $('#requestLog').modal({show:true});
870
            });
871
838
            // Toggle request attributes in Illview
872
            // Toggle request attributes in Illview
839
            $('#toggle_requestattributes').on('click', function(e) {
873
            $('#toggle_requestattributes').on('click', function(e) {
840
                e.preventDefault();
874
                e.preventDefault();
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/log/status_change.tt (+7 lines)
Line 0 Link Here
1
<p>
2
[% log.timestamp | $KohaDates with_hours => 1 %] : <b>Status changed </b>
3
[% IF log.info.status_before %]
4
from &quot;[% request.capabilities(log.info.status_before).name %]&quot;
5
[% END %]
6
to &quot;[% request.capabilities(log.info.status_after).name %]&quot;
7
</p>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt (-2 / +4 lines)
Lines 28-33 Link Here
28
[%        CASE 'ACQUISITIONS' %]Acquisitions
28
[%        CASE 'ACQUISITIONS' %]Acquisitions
29
[%        CASE 'SERIAL'       %]Serials
29
[%        CASE 'SERIAL'       %]Serials
30
[%        CASE 'HOLDS'        %]Holds
30
[%        CASE 'HOLDS'        %]Holds
31
[%        CASE 'ILL'          %]Interlibrary loans
31
[%        CASE 'CIRCULATION'  %]Circulation
32
[%        CASE 'CIRCULATION'  %]Circulation
32
[%        CASE 'LETTER'       %]Letter
33
[%        CASE 'LETTER'       %]Letter
33
[%        CASE 'FINES'        %]Fines
34
[%        CASE 'FINES'        %]Fines
Lines 53-58 Link Here
53
[%        CASE 'CHANGE PASS' %]Change password
54
[%        CASE 'CHANGE PASS' %]Change password
54
[%        CASE 'ADDCIRCMESSAGE' %]Add circulation message
55
[%        CASE 'ADDCIRCMESSAGE' %]Add circulation message
55
[%        CASE 'DELCIRCMESSAGE' %]Delete circulation message
56
[%        CASE 'DELCIRCMESSAGE' %]Delete circulation message
57
[%        CASE 'STATUS_CHANGE'  %]Change ILL request status
58
[%        CASE 'BLDSS_STATUS_CHECK'  %]Check ILL request status with BLDSS
56
[%        CASE 'Run'    %]Run
59
[%        CASE 'Run'    %]Run
57
[%        CASE %][% action | html %]
60
[%        CASE %][% action | html %]
58
[%    END %]
61
[%    END %]
Lines 102-108 Link Here
102
                                    [% ELSE %]
105
                                    [% ELSE %]
103
                                        <option value="">All</option>
106
                                        <option value="">All</option>
104
                                    [% END %]
107
                                    [% END %]
105
                                    [% FOREACH modx IN [ 'CATALOGUING' 'AUTHORITIES' 'MEMBERS' 'ACQUISITIONS' 'SERIAL' 'HOLDS' 'CIRCULATION' 'LETTER' 'FINES' 'SYSTEMPREFERENCE' 'CRONJOBS', 'REPORTS' ] %]
108
                                    [% FOREACH modx IN [ 'CATALOGUING' 'AUTHORITIES' 'MEMBERS' 'ACQUISITIONS' 'SERIAL' 'HOLDS' 'ILL' 'CIRCULATION' 'LETTER' 'FINES' 'SYSTEMPREFERENCE' 'CRONJOBS', 'REPORTS' ] %]
106
                                        [% IF modules.grep(modx).size %]
109
                                        [% IF modules.grep(modx).size %]
107
                                            <option value="[% modx | html %]" selected="selected">[% PROCESS translate_log_module module=modx %]</option>
110
                                            <option value="[% modx | html %]" selected="selected">[% PROCESS translate_log_module module=modx %]</option>
108
                                        [% ELSE %]
111
                                        [% ELSE %]
109
- 

Return to bug 20750