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

(-)a/C4/Log.pm (+1 lines)
Lines 142-147 sub GetLogStatus { Link Here
142
    $hash{CataloguingLog}  = C4::Context->preference("CataloguingLog");
142
    $hash{CataloguingLog}  = C4::Context->preference("CataloguingLog");
143
    $hash{HoldsLog}        = C4::Context->preference("HoldsLog");
143
    $hash{HoldsLog}        = C4::Context->preference("HoldsLog");
144
    $hash{IssueLog}        = C4::Context->preference("IssueLog");
144
    $hash{IssueLog}        = C4::Context->preference("IssueLog");
145
    $hash{IllLog}          = C4::Context->preference("IllLog");
145
    $hash{ReturnLog}       = C4::Context->preference("ReturnLog");
146
    $hash{ReturnLog}       = C4::Context->preference("ReturnLog");
146
    $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog");
147
    $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog");
147
    $hash{LetterLog}       = C4::Context->preference("LetterLog");
148
    $hash{LetterLog}       = C4::Context->preference("LetterLog");
(-)a/Koha/Illrequest.pm (-7 / +64 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
37
37
use base qw(Koha::Object);
38
use base qw(Koha::Object);
Lines 149-154 sub illcomments { Link Here
149
    );
150
    );
150
}
151
}
151
152
153
=head3 logs
154
155
=cut
156
157
sub logs {
158
    my ( $self ) = @_;
159
    my $logger = Koha::Illrequest::Logger->new;
160
    return $logger->get_request_logs($self);
161
}
162
152
=head3 patron
163
=head3 patron
153
164
154
=cut
165
=cut
Lines 162-179 sub patron { Link Here
162
173
163
=head3 status
174
=head3 status
164
175
176
    $Illrequest->status('CANREQ');
177
165
Overloaded getter/setter for request status,
178
Overloaded getter/setter for request status,
166
also nullifies status_alias
179
also nullifies status_alias and records the fact that the status has changed
167
180
168
=cut
181
=cut
169
182
170
sub status {
183
sub status {
171
    my ( $self, $newval) = @_;
184
    my ( $self, $new_status) = @_;
172
    if ($newval) {
185
173
        $self->status_alias(undef);
186
    my $current_status = $self->SUPER::status;
174
        return $self->SUPER::status($newval);
187
188
    if ($new_status) {
189
        # Keep a record of the previous status before we change it,
190
        # we might need it
191
        $self->{previous_status} = $current_status;
192
        my $ret = $self->SUPER::status($new_status)->store;
193
        if ($ret) {
194
            $self->status_alias(undef);
195
            my $logger = Koha::Illrequest::Logger->new;
196
            $logger->log_status_change(
197
                $self,
198
                $new_status
199
            );
200
        } else {
201
            delete $self->{previous_status};
202
        }
203
        return $ret;
204
    } else {
205
        return $current_status;
175
    }
206
    }
176
    return $self->SUPER::status;
177
}
207
}
178
208
179
=head3 load_backend
209
=head3 load_backend
Lines 197-203 sub load_backend { Link Here
197
    my $location = join "/", @raw, $backend_name, "Base.pm";    # File to load
227
    my $location = join "/", @raw, $backend_name, "Base.pm";    # File to load
198
    my $backend_class = join "::", @raw, $backend_name, "Base"; # Package name
228
    my $backend_class = join "::", @raw, $backend_name, "Base"; # Package name
199
    require $location;
229
    require $location;
200
    $self->{_my_backend} = $backend_class->new({ config => $self->_config });
230
    $self->{_my_backend} = $backend_class->new({
231
        config => $self->_config,
232
        logger => Koha::Illrequest::Logger->new
233
    });
201
    return $self;
234
    return $self;
202
}
235
}
203
236
Lines 1052-1057 sub _censor { Link Here
1052
    return $params;
1085
    return $params;
1053
}
1086
}
1054
1087
1088
=head3 store
1089
1090
    $Illrequest->store;
1091
1092
Overloaded I<store> method that, in addition to performing the 'store',
1093
possibly records the fact that something happened
1094
1095
=cut
1096
1097
sub store {
1098
    my ( $self, $attrs ) = @_;
1099
1100
    my $ret = $self->SUPER::store;
1101
1102
    $attrs->{log_origin} = 'core';
1103
1104
    if ($ret && defined $attrs) {
1105
        my $logger = Koha::Illrequest::Logger->new;
1106
        $logger->log_maybe($self, $attrs);
1107
    }
1108
1109
    return $ret;
1110
}
1111
1055
=head3 TO_JSON
1112
=head3 TO_JSON
1056
1113
1057
    $json = $illrequest->TO_JSON
1114
    $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 213-218 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
213
('IDreamBooksResults','0','','Display IDreamBooks.com rating in search results','YesNo'),
213
('IDreamBooksResults','0','','Display IDreamBooks.com rating in search results','YesNo'),
214
('IDreamBooksReviews','0','','Display book review snippets from IDreamBooks.com','YesNo'),
214
('IDreamBooksReviews','0','','Display book review snippets from IDreamBooks.com','YesNo'),
215
('IdRef','0','','Disable/enable the IdRef webservice from the OPAC detail page.','YesNo'),
215
('IdRef','0','','Disable/enable the IdRef webservice from the OPAC detail page.','YesNo'),
216
('IllLog', 1, '', 'If ON, log information about ILL requests', 'YesNo'),
216
('ILLModule','0','If ON, enables the interlibrary loans module.','','YesNo'),
217
('ILLModule','0','If ON, enables the interlibrary loans module.','','YesNo'),
217
('ILLModuleCopyrightClearance','','70|10','Enter text to enable the copyright clearance stage of request creation. Text will be displayed','Textarea'),
218
('ILLModuleCopyrightClearance','','70|10','Enter text to enable the copyright clearance stage of request creation. Text will be displayed','Textarea'),
218
('ILLOpacbackends',NULL,NULL,'ILL backends to enabled for OPAC initiated requests','multiple'),
219
('ILLOpacbackends',NULL,NULL,'ILL backends to enabled for OPAC initiated requests','multiple'),
(-)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 311-316 Link Here
311
                            <span class="fa fa-eye"></span>
311
                            <span class="fa fa-eye"></span>
312
                            Display supplier metadata
312
                            Display supplier metadata
313
                        </a>
313
                        </a>
314
                        <a title="Display request log" id="ill-request-display-log" class="btn btn-sm btn-default pull-right" href="#">
315
                            <span class="fa fa-calendar"></span>
316
                            Display request log
317
                        </a>
314
                    </div>
318
                    </div>
315
                    <div class="ill-view-panel panel panel-default">
319
                    <div class="ill-view-panel panel panel-default">
316
                        <div class="panel-heading">
320
                        <div class="panel-heading">
Lines 421-426 Link Here
421
                        </div>
425
                        </div>
422
                    </div>
426
                    </div>
423
427
428
                    <div id="requestLog" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="dataPreviewLabel" aria-hidden="true">
429
                        <div class="modal-dialog">
430
                            <div class="modal-content">
431
                                <div class="modal-header">
432
                                    <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
433
                                    <h3 id="requestLogLabel"> Request log</h3>
434
                                </div>
435
                                <div class="modal-body">
436
                                [% IF request.logs.size > 0 %]
437
                                    [% FOREACH log IN request.logs %]
438
                                        [% tpl = log.template %]
439
                                        [% INCLUDE $tpl %]
440
                                    [% END %]
441
                                [% ELSE %]
442
                                    There are no recorded logs for this request
443
                                [% END %]
444
                                </div>
445
                                <div class="modal-footer">
446
                                    <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
447
                                </div>
448
                            </div>
449
                        </div>
450
                    </div>
451
424
                    <div class="ill-view-panel panel panel-default">
452
                    <div class="ill-view-panel panel panel-default">
425
                        <div class="panel-heading">
453
                        <div class="panel-heading">
426
                            <h3>[% request.illcomments.count | html %] comments</h3>
454
                            <h3>[% request.illcomments.count | html %] comments</h3>
Lines 459-465 Link Here
459
                                        </form>
487
                                        </form>
460
                                    </div>
488
                                    </div>
461
                                </div>
489
                                </div>
462
                            </div>
490
                        </div>
463
                    </div>
491
                    </div>
464
492
465
                [% ELSIF query_type == 'illlist' %]
493
                [% ELSIF query_type == 'illlist' %]
Lines 822-827 Link Here
822
                }
850
                }
823
            };
851
            };
824
852
853
            // Display the modal containing request supplier metadata
854
            $('#ill-request-display-log').on('click', function(e) {
855
                e.preventDefault();
856
                $('#requestLog').modal({show:true});
857
            });
858
825
            // Toggle request attributes in Illview
859
            // Toggle request attributes in Illview
826
            $('#toggle_requestattributes').on('click', function(e) {
860
            $('#toggle_requestattributes').on('click', function(e) {
827
                e.preventDefault();
861
                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 101-107 Link Here
101
                                    [% ELSE %]
104
                                    [% ELSE %]
102
                                        <option value="">All</option>
105
                                        <option value="">All</option>
103
                                    [% END %]
106
                                    [% END %]
104
                                    [% FOREACH modx IN [ 'CATALOGUING' 'AUTHORITIES' 'MEMBERS' 'ACQUISITIONS' 'SERIAL' 'HOLDS' 'CIRCULATION' 'LETTER' 'FINES' 'SYSTEMPREFERENCE' 'CRONJOBS', 'REPORTS' ] %]
107
                                    [% FOREACH modx IN [ 'CATALOGUING' 'AUTHORITIES' 'MEMBERS' 'ACQUISITIONS' 'SERIAL' 'HOLDS' 'ILL' 'CIRCULATION' 'LETTER' 'FINES' 'SYSTEMPREFERENCE' 'CRONJOBS', 'REPORTS' ] %]
105
                                        [% IF modules.grep(modx).size %]
108
                                        [% IF modules.grep(modx).size %]
106
                                            <option value="[% modx | html %]" selected="selected">[% PROCESS translate_log_module module=modx %]</option>
109
                                            <option value="[% modx | html %]" selected="selected">[% PROCESS translate_log_module module=modx %]</option>
107
                                        [% ELSE %]
110
                                        [% ELSE %]
108
- 

Return to bug 20750