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 778-783 sub CanBookBeIssued { Link Here
778
779
779
    # MANDATORY CHECKS - unless item exists, nothing else matters
780
    # MANDATORY CHECKS - unless item exists, nothing else matters
780
    unless ( $item_object ) {
781
    unless ( $item_object ) {
782
        Koha::Statistics->log_invalid_item( { item => $barcode } );
781
        $issuingimpossible{UNKNOWN_BARCODE} = 1;
783
        $issuingimpossible{UNKNOWN_BARCODE} = 1;
782
    }
784
    }
783
    return ( \%issuingimpossible, \%needsconfirmation ) if %issuingimpossible;
785
    return ( \%issuingimpossible, \%needsconfirmation ) if %issuingimpossible;
Lines 2122-2127 sub AddReturn { Link Here
2122
    # get information on item
2124
    # get information on item
2123
    my $item = Koha::Items->find({ barcode => $barcode });
2125
    my $item = Koha::Items->find({ barcode => $barcode });
2124
    unless ($item) {
2126
    unless ($item) {
2127
        Koha::Statistics->log_invalid_item( { item => $barcode } );
2125
        return ( 0, { BadBarcode => $barcode } );    # no barcode means no item or borrower.  bail out.
2128
        return ( 0, { BadBarcode => $barcode } );    # no barcode means no item or borrower.  bail out.
2126
    }
2129
    }
2127
2130
(-)a/Koha/Statistic.pm (-1 / +1 lines)
Lines 28-34 use Koha::PseudonymizedTransaction; Link Here
28
use base qw(Koha::Object);
28
use base qw(Koha::Object);
29
29
30
our @allowed_accounts_types     = qw( writeoff payment );
30
our @allowed_accounts_types     = qw( writeoff payment );
31
our @allowed_circulation_types  = qw( renew issue localuse return onsite_checkout recall item_found item_lost );
31
our @allowed_circulation_types  = qw( renew issue localuse return onsite_checkout recall item_found item_lost invalid_item invalid_patron);
32
our @mandatory_accounts_keys    = qw( type branch borrowernumber value );    # note that amount is mapped to value
32
our @mandatory_accounts_keys    = qw( type branch borrowernumber value );    # note that amount is mapped to value
33
our @mandatory_circulation_keys = qw( type branch borrowernumber itemnumber ccode itemtype );
33
our @mandatory_circulation_keys = qw( type branch borrowernumber itemnumber ccode itemtype );
34
34
(-)a/Koha/Statistics.pm (-1 / +72 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
            itemnumber     => "",
99
            ccode          => "",
100
            itemtype       => "",
101
            datetime       => $dt,
102
            branch         => $branch,
103
            borrowernumber => $borrowernumber
104
        }
105
    )->store();
106
}
107
108
=head3 _type
38
109
39
=cut
110
=cut
40
111
(-)a/circ/circulation.pl (+2 lines)
Lines 55-60 use Koha::SearchEngine; Link Here
55
use Koha::SearchEngine::Search;
55
use Koha::SearchEngine::Search;
56
use Koha::Patron::Modifications;
56
use Koha::Patron::Modifications;
57
use Koha::Token;
57
use Koha::Token;
58
use Koha::Statistics;
58
59
59
use List::MoreUtils qw( uniq );
60
use List::MoreUtils qw( uniq );
60
61
Lines 240-245 if ($findborrower) { Link Here
240
    if ( $patron ) {
241
    if ( $patron ) {
241
        $borrowernumber = $patron->borrowernumber;
242
        $borrowernumber = $patron->borrowernumber;
242
    } else {
243
    } else {
244
        Koha::Statistics->log_invalid_patron( { patron => $findborrower } );
243
        print $query->redirect( "/cgi-bin/koha/members/member.pl?quicksearch=1&circsearch=1&searchmember=" . uri_escape_utf8($findborrower) );
245
        print $query->redirect( "/cgi-bin/koha/members/member.pl?quicksearch=1&circsearch=1&searchmember=" . uri_escape_utf8($findborrower) );
244
        exit;
246
        exit;
245
    }
247
    }
(-)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 366-371 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
366
('LocalHoldsPriorityItemControl',  'holdingbranch',  'holdingbranch|homebranch',  'decides if the feature operates using the item''s home or holding library.',  'Choice'),
366
('LocalHoldsPriorityItemControl',  'holdingbranch',  'holdingbranch|homebranch',  'decides if the feature operates using the item''s home or holding library.',  'Choice'),
367
('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'),
367
('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'),
368
('LockExpiredDelay','','','Delay for locking expired patrons (empty means no locking)','Integer'),
368
('LockExpiredDelay','','','Delay for locking expired patrons (empty means no locking)','Integer'),
369
('LogInvalidItems','0','','Log scanned invalid item identifiers as statistics','YesNo'),
370
('LogInvalidPatrons','0','','Log scanned invalid patron identifiers as statistics','YesNo'),
369
('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'),
371
('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'),
370
('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'),
372
('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'),
371
('MARCAuthorityControlField008','|| aca||aabn           | a|a     d',NULL,'Define the contents of MARC21 authority control field 008 position 06-39','Textarea'),
373
('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/Koha/Statistics.t (-2 / +58 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 3;
22
use Test::More tests => 4;
23
use Test::Exception;
23
use Test::Exception;
24
24
25
use C4::Context;
25
use C4::Context;
Lines 27-32 use Koha::Database; Link Here
27
use Koha::Statistics;
27
use Koha::Statistics;
28
28
29
use t::lib::TestBuilder;
29
use t::lib::TestBuilder;
30
use t::lib::Mocks;
31
use Test::MockModule;
30
32
31
our $schema  = Koha::Database->new->schema;
33
our $schema  = Koha::Database->new->schema;
32
our $builder = t::lib::TestBuilder->new;
34
our $builder = t::lib::TestBuilder->new;
Lines 159-161 sub insert_and_fetch { Link Here
159
161
160
    # FIXME discard_changes would be nicer, but we dont have a PK (yet)
162
    # FIXME discard_changes would be nicer, but we dont have a PK (yet)
161
}
163
}
162
- 
164
165
subtest 'Log borrower cardnumbers and item barcodes which are not valid' => sub {
166
    plan tests => 10;
167
    $schema->storage->txn_begin;
168
169
    #my $builder    = t::lib::TestBuilder->new;
170
    my $library    = $builder->build( { source => 'Branch' } );
171
    my $branchcode = $library->{branchcode};
172
    my $context    = Test::MockModule->new('C4::Context');
173
    $context->mock(
174
        'userenv',
175
        sub {
176
            return {
177
                flags  => 1,
178
                id     => 'my_userid',
179
                branch => $branchcode,
180
                number => '-1',
181
            };
182
        }
183
    );
184
185
    # Test Koha::Statistic->log_invalid_patron
186
    my $dbh = $schema->storage->dbh;
187
    $dbh->do(q{DELETE FROM statistics});
188
    t::lib::Mocks::mock_preference( "LogInvalidPatrons", 0 );
189
    Koha::Statistics->log_invalid_patron( { patron => 'InvalidCardnumber' } );
190
    is(
191
        Koha::Statistics->search()->count(), 0,
192
        'No stat line added if system preference LogInvalidPatrons is disabled'
193
    );
194
195
    t::lib::Mocks::mock_preference( "LogInvalidPatrons", 1 );
196
    Koha::Statistics->log_invalid_patron( { patron => 'InvalidCardnumber' } );
197
    my $stat = Koha::Statistics->search()->next();
198
    is( $stat->type,           'invalid_patron',    'Type set to invalid_patron' );
199
    is( $stat->borrowernumber, '-1',                'Associated library id set correctly' );
200
    is( $stat->other,          'InvalidCardnumber', 'Invalid cardnumber is set correctly' );
201
    is( $stat->branch,         $branchcode,         'Branchcode is set correctly' );
202
203
    # Test Koha::Statistic->log_invalid_item
204
    $dbh->do(q{DELETE FROM statistics});
205
    t::lib::Mocks::mock_preference( "LogInvalidItems", 0 );
206
    Koha::Statistics->log_invalid_item( { item => 'InvalidBarcode' } );
207
    is( Koha::Statistics->search()->count(), 0, 'No stat line added if system preference LogInvalidItems is disabled' );
208
209
    t::lib::Mocks::mock_preference( "LogInvalidItems", 1 );
210
    Koha::Statistics->log_invalid_item( { item => 'InvalidBarcode' } );
211
    $stat = Koha::Statistics->search()->next();
212
    is( $stat->type,           'invalid_item',   'Type set to invalid_item' );
213
    is( $stat->borrowernumber, '-1',             'Associated library id set correctly' );
214
    is( $stat->other,          'InvalidBarcode', 'Invalid barcode is set correctly' );
215
    is( $stat->branch,         $branchcode,      'Branchcode is set correctly' );
216
217
    $schema->storage->txn_rollback;
218
};

Return to bug 16117