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

(-)a/C4/Circulation.pm (+3 lines)
Lines 63-68 use Koha::SearchEngine::Indexer; Link Here
63
use Koha::Exceptions::Checkout;
63
use Koha::Exceptions::Checkout;
64
use Koha::Plugins;
64
use Koha::Plugins;
65
use Koha::Recalls;
65
use Koha::Recalls;
66
use Koha::Statistics;
66
use Carp qw( carp );
67
use Carp qw( carp );
67
use List::MoreUtils qw( any );
68
use List::MoreUtils qw( any );
68
use Scalar::Util qw( looks_like_number blessed );
69
use Scalar::Util qw( looks_like_number blessed );
Lines 782-787 sub CanBookBeIssued { Link Here
782
783
783
    # MANDATORY CHECKS - unless item exists, nothing else matters
784
    # MANDATORY CHECKS - unless item exists, nothing else matters
784
    unless ( $item_object ) {
785
    unless ( $item_object ) {
786
        Koha::Statistics->log_invalid_item( { item => $barcode } );
785
        $issuingimpossible{UNKNOWN_BARCODE} = 1;
787
        $issuingimpossible{UNKNOWN_BARCODE} = 1;
786
    }
788
    }
787
    return ( \%issuingimpossible, \%needsconfirmation ) if %issuingimpossible;
789
    return ( \%issuingimpossible, \%needsconfirmation ) if %issuingimpossible;
Lines 2095-2100 sub AddReturn { Link Here
2095
    # get information on item
2097
    # get information on item
2096
    my $item = Koha::Items->find({ barcode => $barcode });
2098
    my $item = Koha::Items->find({ barcode => $barcode });
2097
    unless ($item) {
2099
    unless ($item) {
2100
        Koha::Statistics->log_invalid_item( { item => $barcode } );
2098
        return ( 0, { BadBarcode => $barcode } );    # no barcode means no item or borrower.  bail out.
2101
        return ( 0, { BadBarcode => $barcode } );    # no barcode means no item or borrower.  bail out.
2099
    }
2102
    }
2100
2103
(-)a/Koha/Statistics.pm (-1 / +69 lines)
Lines 21-26 use Modern::Perl; Link Here
21
use Koha::Database;
21
use Koha::Database;
22
22
23
use Koha::Statistic;
23
use Koha::Statistic;
24
use Koha::DateUtils qw(dt_from_string);
24
25
25
use base qw(Koha::Objects);
26
use base qw(Koha::Objects);
26
27
Lines 32-40 Koha::Statistics - Koha Statistic Object set class Link Here
32
33
33
=head2 Class Methods
34
=head2 Class Methods
34
35
36
=head3 log_invalid_patron
37
38
Koha::Statistics->log_invalid_patron( { patron => $cardnumber } );
39
40
=cut
41
42
sub log_invalid_patron {
43
    return unless C4::Context->preference('LogInvalidPatrons');
44
45
    my ( $class, $params ) = @_;
46
47
    my $patron = $params->{patron};
48
49
    return $class->_log_invalid_value(
50
        {
51
            type  => 'patron',
52
            value => $patron
53
        }
54
    );
55
}
56
57
=head3 log_invalid_item
58
59
Koha::Statistics->log_invalid_item( { item => $barcode } );
60
35
=cut
61
=cut
36
62
37
=head3 type
63
sub log_invalid_item {
64
    return unless C4::Context->preference('LogInvalidItems');
65
66
    my ( $class, $params ) = @_;
67
68
    my $item = $params->{item};
69
70
    return $class->_log_invalid_value(
71
        {
72
            type  => 'item',
73
            value => $item
74
        }
75
    );
76
}
77
78
=head3 invalid_value
79
80
Koha::Statistics->invalid_value( { type => 'patron', value => $patron } );
81
82
=cut
83
84
sub _log_invalid_value {
85
    my ( $class, $params ) = @_;
86
87
    my $type  = $params->{type};
88
    my $value = $params->{value};
89
90
    my $branch = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
91
    my $dt     = dt_from_string();
92
    my $borrowernumber = C4::Context->userenv->{'number'};
93
94
    return Koha::Statistic->new(
95
        {
96
            type           => "invalid_$type",
97
            other          => $value,
98
            datetime       => $dt,
99
            branch         => $branch,
100
            borrowernumber => $borrowernumber
101
        }
102
    )->store();
103
}
104
105
=head3 _type
38
106
39
=cut
107
=cut
40
108
(-)a/circ/circulation.pl (+2 lines)
Lines 54-59 use Koha::SearchEngine; Link Here
54
use Koha::SearchEngine::Search;
54
use Koha::SearchEngine::Search;
55
use Koha::Patron::Modifications;
55
use Koha::Patron::Modifications;
56
use Koha::Token;
56
use Koha::Token;
57
use Koha::Statistics;
57
58
58
use List::MoreUtils qw( uniq );
59
use List::MoreUtils qw( uniq );
59
60
Lines 221-226 if ($findborrower) { Link Here
221
    if ( $patron ) {
222
    if ( $patron ) {
222
        $borrowernumber = $patron->borrowernumber;
223
        $borrowernumber = $patron->borrowernumber;
223
    } else {
224
    } else {
225
        Koha::Statistics->log_invalid_patron( { patron => $findborrower } );
224
        print $query->redirect( "/cgi-bin/koha/members/member.pl?quicksearch=1&circsearch=1&searchmember=" . uri_escape_utf8($findborrower) );
226
        print $query->redirect( "/cgi-bin/koha/members/member.pl?quicksearch=1&circsearch=1&searchmember=" . uri_escape_utf8($findborrower) );
225
        exit;
227
        exit;
226
    }
228
    }
(-)a/installer/data/mysql/atomicupdate/bug_16117.pl (+19 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
return {
4
    bug_number => "16117",
5
    description => "Log invalid borrower cardnumbers and item barcodes",
6
    up => sub {
7
        my ($args) = @_;
8
        my ($dbh, $out) = @$args{qw(dbh out)};
9
10
        $dbh->do(q{
11
            INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES
12
            ('LogInvalidItems','0','','Log scanned invalid item identifiers as statistics','YesNo'),
13
            ('LogInvalidPatrons','0','','Log scanned invalid patron identifiers as statistics','YesNo');
14
        });
15
        # sysprefs
16
        say $out "Added new system preference 'LogInvalidItems'";
17
        say $out "Added new system preference 'LogInvalidPatrons'";
18
    },
19
};
(-)a/installer/data/mysql/mandatory/sysprefs.sql (+2 lines)
Lines 357-362 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
357
('LocalHoldsPriorityItemControl',  'holdingbranch',  'holdingbranch|homebranch',  'decides if the feature operates using the item''s home or holding library.',  'Choice'),
357
('LocalHoldsPriorityItemControl',  'holdingbranch',  'holdingbranch|homebranch',  'decides if the feature operates using the item''s home or holding library.',  'Choice'),
358
('LocalHoldsPriorityPatronControl',  'PickupLibrary',  'HomeLibrary|PickupLibrary',  'decides if the feature operates using the library set as the patron''s home library, or the library set as the pickup library for the given hold.',  'Choice'),
358
('LocalHoldsPriorityPatronControl',  'PickupLibrary',  'HomeLibrary|PickupLibrary',  'decides if the feature operates using the library set as the patron''s home library, or the library set as the pickup library for the given hold.',  'Choice'),
359
('LockExpiredDelay','','','Delay for locking expired patrons (empty means no locking)','Integer'),
359
('LockExpiredDelay','','','Delay for locking expired patrons (empty means no locking)','Integer'),
360
('LogInvalidItems','0','','Log scanned invalid item identifiers as statistics','YesNo'),
361
('LogInvalidPatrons','0','','Log scanned invalid patron identifiers as statistics','YesNo'),
360
('makePreviousSerialAvailable','0','','make previous serial automatically available when collecting a new serial. Please note that the item-level_itypes syspref must be set to specific item.','YesNo'),
362
('makePreviousSerialAvailable','0','','make previous serial automatically available when collecting a new serial. Please note that the item-level_itypes syspref must be set to specific item.','YesNo'),
361
('Mana','2',NULL,'request to Mana Webservice. Mana centralize common information between other Koha to facilitate the creation of new subscriptions, vendors, report queries etc... You can search, share, import and comment the content of Mana.','Choice'),
363
('Mana','2',NULL,'request to Mana Webservice. Mana centralize common information between other Koha to facilitate the creation of new subscriptions, vendors, report queries etc... You can search, share, import and comment the content of Mana.','Choice'),
362
('MARCAuthorityControlField008','|| aca||aabn           | a|a     d',NULL,'Define the contents of MARC21 authority control field 008 position 06-39','Textarea'),
364
('MARCAuthorityControlField008','|| aca||aabn           | a|a     d',NULL,'Define the contents of MARC21 authority control field 008 position 06-39','Textarea'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (+12 lines)
Lines 19-24 Circulation: Link Here
19
                  0: "Don't enable"
19
                  0: "Don't enable"
20
            - the automatic redirection to another patron when a patron barcode is scanned instead of a book.
20
            - the automatic redirection to another patron when a patron barcode is scanned instead of a book.
21
            - This should not be enabled if you have overlapping patron and book barcodes.
21
            - This should not be enabled if you have overlapping patron and book barcodes.
22
        -
23
            - pref: LogInvalidPatrons
24
              choices:
25
                  yes: Log
26
                  no: Do not log
27
            - scanned invalid patron identifiers as statistics.
28
        -
29
            - pref: LogInvalidItems
30
              choices:
31
                  yes: Log
32
                  no: Do not log
33
            - scanned invalid item identifiers as statistics.
22
        -
34
        -
23
            - pref: PatronAutoComplete
35
            - pref: PatronAutoComplete
24
              choices:
36
              choices:
(-)a/opac/sco/sco-main.pl (-1 / +5 lines)
Lines 131-136 my $patron; Link Here
131
if ( $patronid ) {
131
if ( $patronid ) {
132
    Koha::Plugins->call( 'patron_barcode_transform', \$patronid );
132
    Koha::Plugins->call( 'patron_barcode_transform', \$patronid );
133
    $patron = Koha::Patrons->find( { cardnumber => $patronid } );
133
    $patron = Koha::Patrons->find( { cardnumber => $patronid } );
134
    Koha::Statistics->log_invalid_patron( { patron => $patronid } ) unless $patron;
134
}
135
}
135
136
136
undef $jwt unless $patron;
137
undef $jwt unless $patron;
Lines 142-149 my $return_only = 0; Link Here
142
if ( $patron && $op eq "returnbook" && $allowselfcheckreturns ) {
143
if ( $patron && $op eq "returnbook" && $allowselfcheckreturns ) {
143
    my $success = 1;
144
    my $success = 1;
144
145
145
146
    my $item = Koha::Items->find( { barcode => $barcode } );
146
    my $item = Koha::Items->find( { barcode => $barcode } );
147
    Koha::Statistics->log_invalid_item( { item => $barcode } ) unless $item;
148
147
    if ( $success && C4::Context->preference("CircConfirmItemParts") ) {
149
    if ( $success && C4::Context->preference("CircConfirmItemParts") ) {
148
        if ( defined($item)
150
        if ( defined($item)
149
            && $item->materials )
151
            && $item->materials )
Lines 167-172 if ( $patron && $op eq "returnbook" && $allowselfcheckreturns ) { Link Here
167
elsif ( $patron && ( $op eq 'checkout' ) ) {
169
elsif ( $patron && ( $op eq 'checkout' ) ) {
168
170
169
    my $item = Koha::Items->find( { barcode => $barcode } );
171
    my $item = Koha::Items->find( { barcode => $barcode } );
172
    Koha::Statistics->log_invalid_item( { item => $barcode } ) unless $item;
170
    my $impossible  = {};
173
    my $impossible  = {};
171
    my $needconfirm = {};
174
    my $needconfirm = {};
172
    ( $impossible, $needconfirm ) = CanBookBeIssued(
175
    ( $impossible, $needconfirm ) = CanBookBeIssued(
Lines 277-282 elsif ( $patron && ( $op eq 'checkout' ) ) { Link Here
277
280
278
if ( $patron && ( $op eq 'renew' ) ) {
281
if ( $patron && ( $op eq 'renew' ) ) {
279
    my $item = Koha::Items->find({ barcode => $barcode });
282
    my $item = Koha::Items->find({ barcode => $barcode });
283
    Koha::Statistics->log_invalid_item( { item => $barcode } ) unless $item;
280
284
281
    if ( $patron->checkouts->find( { itemnumber => $item->itemnumber } ) ) {
285
    if ( $patron->checkouts->find( { itemnumber => $item->itemnumber } ) ) {
282
        my ($status,$renewerror) = CanBookBeRenewed( $patron, $item->checkout );
286
        my ($status,$renewerror) = CanBookBeRenewed( $patron, $item->checkout );
(-)a/t/db_dependent/Stats.t (-3 / +52 lines)
Lines 4-13 use Modern::Perl; Link Here
4
use C4::Stats qw( UpdateStats );
4
use C4::Stats qw( UpdateStats );
5
use Koha::Database;
5
use Koha::Database;
6
6
7
use Test::More tests => 19;
7
use Test::More tests => 31;
8
use Test::MockModule;
9
use t::lib::TestBuilder;
10
use t::lib::Mocks;
8
11
9
BEGIN {
12
BEGIN {
10
    use_ok('C4::Stats', qw( UpdateStats ));
13
    use_ok('C4::Stats', qw( UpdateStats ));
14
    use_ok('Koha::Statistic');
15
    use_ok('Koha::Statistics');
11
}
16
}
12
can_ok(
17
can_ok(
13
    'C4::Stats',
18
    'C4::Stats',
Lines 162-165 $line = ${ $sth->fetchall_arrayref( {} ) }[0]; Link Here
162
is( $line->{location}, undef,
167
is( $line->{location}, undef,
163
    "UpdateStats sets location to NULL if undef is passed in." );
168
    "UpdateStats sets location to NULL if undef is passed in." );
164
169
165
# More tests to write!
170
my $builder = t::lib::TestBuilder->new;
171
my $library = $builder->build( { source => 'Branch' } );
172
my $branchcode = $library->{branchcode};
173
my $context = Test::MockModule->new('C4::Context');
174
$context->mock(
175
    'userenv',
176
    sub {
177
        return {
178
            flags  => 1,
179
            id     => 'my_userid',
180
            branch => $branchcode,
181
            number => '-1',
182
        };
183
    }
184
);
185
# Test Koha::Statistic->log_invalid_patron
186
$dbh->do(q{DELETE FROM statistics});
187
t::lib::Mocks::mock_preference( "LogInvalidPatrons", 0 );
188
Koha::Statistics->log_invalid_patron( { patron => 'InvalidCardnumber' } );
189
is( Koha::Statistics->search()->count(), 0, 'No stat line added if system preference LogInvalidPatrons is disabled' );
190
191
t::lib::Mocks::mock_preference( "LogInvalidPatrons", 1 );
192
Koha::Statistics->log_invalid_patron( { patron => 'InvalidCardnumber' } );
193
my $stat = Koha::Statistics->search()->next();
194
is( $stat->type, 'invalid_patron', 'Type set to invalid_patron' );
195
is( $stat->borrowernumber, '-1', 'Associated library id set correctly' );
196
is( $stat->other, 'InvalidCardnumber', 'Invalid cardnumber is set correctly' );
197
is( $stat->branch, $branchcode, 'Branchcode is set correctly' );
198
199
# Test Koha::Statistic->log_invalid_item
200
$dbh->do(q{DELETE FROM statistics});
201
t::lib::Mocks::mock_preference( "LogInvalidItems", 0 );
202
Koha::Statistics->log_invalid_item( { item => 'InvalidBarcode' } );
203
is( Koha::Statistics->search()->count(), 0, 'No stat line added if system preference LogInvalidItems is disabled' );
204
205
t::lib::Mocks::mock_preference( "LogInvalidItems", 1 );
206
Koha::Statistics->log_invalid_item( { item => 'InvalidBarcode' } );
207
$stat = Koha::Statistics->search()->next();
208
is( $stat->type, 'invalid_item', 'Type set to invalid_item' );
209
is( $stat->borrowernumber, '-1', 'Associated library id set correctly' );
210
is( $stat->other, 'InvalidBarcode', 'Invalid barcode is set correctly' );
211
is( $stat->branch, $branchcode, 'Branchcode is set correctly' );
212
213
214
#End transaction
215
$dbh->rollback;
166
- 

Return to bug 16117