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

(-)a/C4/Barcodes.pm (+2 lines)
Lines 28-33 use C4::Dates; Link Here
28
use C4::Barcodes::hbyymmincr;
28
use C4::Barcodes::hbyymmincr;
29
use C4::Barcodes::annual;
29
use C4::Barcodes::annual;
30
use C4::Barcodes::incremental;
30
use C4::Barcodes::incremental;
31
use C4::Barcodes::prefix;
31
32
32
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
33
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
33
use vars qw($debug $cgi_debug);	# from C4::Debug, of course
34
use vars qw($debug $cgi_debug);	# from C4::Debug, of course
Lines 173-178 sub default_self { Link Here
173
}
174
}
174
175
175
our $types = {
176
our $types = {
177
        prefix_incr => sub {C4::Barcodes::prefix->new_object(@_);     },
176
	annual      => sub {C4::Barcodes::annual->new_object(@_);     },
178
	annual      => sub {C4::Barcodes::annual->new_object(@_);     },
177
	incremental => sub {C4::Barcodes::incremental->new_object(@_);},
179
	incremental => sub {C4::Barcodes::incremental->new_object(@_);},
178
	hbyymmincr  => sub {C4::Barcodes::hbyymmincr->new_object(@_); },
180
	hbyymmincr  => sub {C4::Barcodes::hbyymmincr->new_object(@_); },
(-)a/C4/Barcodes/prefix.pm (+126 lines)
Line 0 Link Here
1
package C4::Barcodes::prefix;
2
3
# Copyright 2011 ByWater Solutions
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 2 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 strict;
21
use warnings;
22
use Carp;
23
24
use C4::Context;
25
use C4::Branch;
26
use C4::Debug;
27
use C4::Dates;
28
29
use vars qw($VERSION @ISA);
30
use vars qw($debug $cgi_debug);        # from C4::Debug, of course
31
use vars qw($branch $width);
32
33
BEGIN {
34
    $VERSION = 0.01;
35
    @ISA = qw(C4::Barcodes);
36
    $width = C4::Context->preference('itembarcodelength');
37
    my $prefix = '';
38
}
39
40
41
# This package generates auto-incrementing barcodes where branch-specific prefixes are being used.
42
# For a library with 10-digit barcodes, and a prefix of T123, this should generate on a range of
43
# T123000000 and T123999999
44
#
45
# There are a couple of problems with treating barcodes as straight-numerics and just incrementing
46
# them.  The first, and most-obvious, is that barcodes need not be numeric, particularly in the prefix
47
# part!  The second, as noted in C4::Barcodes.pm, is that you might not actually be able to handle very
48
# large ints like that...
49
50
51
sub db_max ($;$) {
52
        my $self = shift;
53
        my $sth = C4::Context->dbh->prepare("SELECT MAX(barcode) AS biggest FROM items where barcode LIKE ? AND length(barcode) =?");
54
        my $prefix_search = $self->prefix . '%';
55
        $sth->execute($prefix_search, $self->width);
56
        return $self->initial unless ($sth->rows);
57
        my ($row) = $sth->fetchrow_hashref();
58
59
        my $max = $row->{biggest};
60
        return ($max || 0);
61
}
62
63
sub initial () {
64
        my $self = shift;
65
        my $increment_width = $self->width - length($self->prefix);
66
        return $self->prefix . sprintf("%"."$increment_width.$increment_width"."d",1);
67
}
68
69
sub parse ($;$) {   # return 3 parts of barcode: non-incrementing, incrementing, non-incrementing
70
        my $self = shift;
71
        my $barcode = (@_) ? shift : $self->value;
72
        my $prefix = $self->prefix;
73
        unless ($barcode =~ /($prefix)(.+)$/) {
74
           return($barcode,undef,undef);
75
        }
76
        return ($1,$2,'');  # the third part is in anticipation of barcodes that include checkdigits
77
}
78
79
sub prefix ($;$) {
80
        my $self = shift;
81
        (@_) and $self->{prefix} = shift;
82
        return C4::Branch::GetBranchDetail(C4::Context->userenv->{'branch'})->{'itembarcodeprefix'};
83
}
84
85
sub width ($;$) {
86
       my $self = shift;
87
       (@_) and $width = shift;        # hitting the class variable.
88
       return $width;
89
}
90
91
sub next_value ($;$) {
92
    my $self = shift;
93
    my $specific = (scalar @_) ? 1 : 0;
94
    my $max = $specific ? shift : $self->max;
95
    return $self->initial unless ($max);
96
    my ($head,$incr,$tail) = $self->parse($max);
97
    return undef unless (defined $incr);
98
    my $incremented = '';
99
100
    while ($incr =~ /([a-zA-Z]*[0-9]*)\z/ ){
101
       my $fragment = $1;
102
       $fragment++;   #yes, you can do that with strings.  Clever.
103
       if (length($fragment) > length($1)){   #uhoh.  got to carry something over.
104
          $incremented = substr($fragment,1) . $incremented;
105
          $incr = $`;    #prematch.  grab everything *before* $1 from above, and go back thru this.
106
       }
107
       else {   #we're okay now.
108
          $incr = $` . $fragment . $incremented;
109
          last;
110
       }
111
    }
112
113
    my $next_val = $head . $incr .$tail;
114
    return $next_val;
115
}
116
117
sub new_object {
118
        my $class_or_object = shift;
119
        my $type = ref($class_or_object) || $class_or_object;
120
        my $self = $type->default_self('prefix_incr');
121
        # take the prefix from argument, or the existing object, or get it from the userenv, in that order
122
        return bless $self, $type;
123
}
124
125
1;
126
__END__
(-)a/C4/Circulation.pm (+5 lines)
Lines 170-175 sub barcodedecode { Link Here
170
			}
170
			}
171
		}
171
		}
172
	}
172
	}
173
        if(C4::Context->preference('itembarcodelength') && (length($barcode) < C4::Context->preference('itembarcodelength'))) {
174
                my $prefix = GetBranchDetail(C4::Context->userenv->{'branch'})->{'itembarcodeprefix'} ;
175
                my $padding = C4::Context->preference('itembarcodelength') - length($prefix) - length($barcode) ;
176
                $barcode = $prefix . '0' x $padding . $barcode if($padding >= 0) ;
177
        }
173
    return $barcode;    # return barcode, modified or not
178
    return $barcode;    # return barcode, modified or not
174
}
179
}
175
180
(-)a/C4/ILSDI/Services.pm (-1 / +2 lines)
Lines 509-515 sub GetServices { Link Here
509
509
510
    # Issuing management
510
    # Issuing management
511
    my $barcode = $item->{'barcode'} || '';
511
    my $barcode = $item->{'barcode'} || '';
512
    $barcode = barcodedecode($barcode) if ( $barcode && C4::Context->preference('itemBarcodeInputFilter') );
512
    $barcode = barcodedecode($barcode) if ( $barcode && C4::Context->preference('itemBarcodeInputFilter')
513
                                            || C4::Context->preference('itembarcodelength') );
513
    if ($barcode) {
514
    if ($barcode) {
514
        my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $borrower, $barcode );
515
        my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $borrower, $barcode );
515
516
(-)a/C4/Items.pm (+28 lines)
Lines 257-262 sub AddItem { Link Here
257
    $sth->execute( $item->{'biblionumber'} );
257
    $sth->execute( $item->{'biblionumber'} );
258
    ($item->{'biblioitemnumber'}) = $sth->fetchrow;
258
    ($item->{'biblioitemnumber'}) = $sth->fetchrow;
259
259
260
    _check_itembarcode($item) if (C4::Context->preference('itembarcodelength'));
260
    _set_defaults_for_add($item);
261
    _set_defaults_for_add($item);
261
    _set_derived_columns_for_add($item);
262
    _set_derived_columns_for_add($item);
262
    $item->{'more_subfields_xml'} = _get_unlinked_subfields_xml($unlinked_item_subfields);
263
    $item->{'more_subfields_xml'} = _get_unlinked_subfields_xml($unlinked_item_subfields);
Lines 360-365 sub AddItemBatchFromMarc { Link Here
360
            next ITEMFIELD;
361
            next ITEMFIELD;
361
        }
362
        }
362
363
364
        _check_itembarcode($item) if (C4::Context->preference('itembarcodelength'));
363
        _set_defaults_for_add($item);
365
        _set_defaults_for_add($item);
364
        _set_derived_columns_for_add($item);
366
        _set_derived_columns_for_add($item);
365
        my ( $itemnumber, $error ) = _koha_new_item( $item, $item->{barcode} );
367
        my ( $itemnumber, $error ) = _koha_new_item( $item, $item->{barcode} );
Lines 2766-2769 sub PrepareItemrecordDisplay { Link Here
2766
    };
2768
    };
2767
}
2769
}
2768
2770
2771
=head2 _check_itembarcode
2772
2773
=over 4
2774
2775
&_check_itembarcode
2776
2777
=back
2778
2779
Modifies item barcode value to include prefix defined in branches.itembarcodeprefix
2780
if the length is less than the syspref itembarcodelength .
2781
2782
=cut
2783
sub _check_itembarcode($) {
2784
    my $item = shift;
2785
    return(0) unless $item->{'barcode'}; # only modify if we've been passed a barcode.
2786
    # check item barcode prefix
2787
    # note this doesn't enforce barcodelength.
2788
    my $branch_prefix = GetBranchDetail($item->{'homebranch'})->{'itembarcodeprefix'};
2789
    if(length($item->{'barcode'}) < C4::Context->preference('itembarcodelength')) {
2790
        my $padding = C4::Context->preference('itembarcodelength') - length($branch_prefix) - length($item->{'barcode'}) ;
2791
        $item->{'barcode'} = $branch_prefix .  '0' x $padding . $item->{'barcode'} if($padding >= 0) ;
2792
    } else {
2793
      #  $errors{'invalid_barcode'} = $item->{'barcode'};
2794
    }
2795
}
2796
2769
1;
2797
1;
(-)a/C4/Members.pm (-13 / +81 lines)
Lines 39-44 use DateTime; Link Here
39
use DateTime::Format::DateParse;
39
use DateTime::Format::DateParse;
40
use Koha::DateUtils;
40
use Koha::DateUtils;
41
use Text::Unaccent qw( unac_string );
41
use Text::Unaccent qw( unac_string );
42
use C4::Branch qw(GetBranchDetail);
42
43
43
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
44
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
44
45
Lines 178-187 sub _express_member_find { Link Here
178
    # so we can check an exact match first, if that works return, otherwise do the rest
179
    # so we can check an exact match first, if that works return, otherwise do the rest
179
    my $dbh   = C4::Context->dbh;
180
    my $dbh   = C4::Context->dbh;
180
    my $query = "SELECT borrowernumber FROM borrowers WHERE cardnumber = ?";
181
    my $query = "SELECT borrowernumber FROM borrowers WHERE cardnumber = ?";
181
    if ( my $borrowernumber = $dbh->selectrow_array($query, undef, $filter) ) {
182
    my $cardnum = _prefix_cardnum($filter);
183
    if ( my $borrowernumber = $dbh->selectrow_array($query, undef, $cardnum) ) {
182
        return( {"borrowernumber"=>$borrowernumber} );
184
        return( {"borrowernumber"=>$borrowernumber} );
183
    }
185
    }
184
185
    my ($search_on_fields, $searchtype);
186
    my ($search_on_fields, $searchtype);
186
    if ( length($filter) == 1 ) {
187
    if ( length($filter) == 1 ) {
187
        $search_on_fields = [ qw(surname) ];
188
        $search_on_fields = [ qw(surname) ];
Lines 720-725 sub ModMember { Link Here
720
            $data{password} = md5_base64($data{password});
721
            $data{password} = md5_base64($data{password});
721
        }
722
        }
722
    }
723
    }
724
725
    # modify cardnumber with prefix, if needed.
726
    if(C4::Context->preference('patronbarcodelength') && exists($data{'cardnumber'})){
727
        $data{'cardnumber'} = _prefix_cardnum($data{'cardnumber'});
728
    }
729
723
	my $execute_success=UpdateInTable("borrowers",\%data);
730
	my $execute_success=UpdateInTable("borrowers",\%data);
724
    if ($execute_success) { # only proceed if the update was a success
731
    if ($execute_success) { # only proceed if the update was a success
725
        # ok if its an adult (type) it may have borrowers that depend on it as a guarantor
732
        # ok if its an adult (type) it may have borrowers that depend on it as a guarantor
Lines 755-760 sub AddMember { Link Here
755
	$data{'userid'} = Generate_Userid($data{'borrowernumber'}, $data{'firstname'}, $data{'surname'}) if $data{'userid'} eq '';
762
	$data{'userid'} = Generate_Userid($data{'borrowernumber'}, $data{'firstname'}, $data{'surname'}) if $data{'userid'} eq '';
756
	# create a disabled account if no password provided
763
	# create a disabled account if no password provided
757
	$data{'password'} = ($data{'password'})? md5_base64($data{'password'}) : '!';
764
	$data{'password'} = ($data{'password'})? md5_base64($data{'password'}) : '!';
765
        $data{'cardnumber'} = _prefix_cardnum($data{'cardnumber'}) if(C4::Context->preference('patronbarcodelength'));
766
758
	$data{'borrowernumber'}=InsertInTable("borrowers",\%data);	
767
	$data{'borrowernumber'}=InsertInTable("borrowers",\%data);	
759
    # mysql_insertid is probably bad.  not necessarily accurate and mysql-specific at best.
768
    # mysql_insertid is probably bad.  not necessarily accurate and mysql-specific at best.
760
    logaction("MEMBERS", "CREATE", $data{'borrowernumber'}, "") if C4::Context->preference("BorrowersLog");
769
    logaction("MEMBERS", "CREATE", $data{'borrowernumber'}, "") if C4::Context->preference("BorrowersLog");
Lines 850-856 use vars qw( @weightings ); Link Here
850
my @weightings = ( 8, 4, 6, 3, 5, 2, 1 );
859
my @weightings = ( 8, 4, 6, 3, 5, 2, 1 );
851
860
852
sub fixup_cardnumber {
861
sub fixup_cardnumber {
853
    my ($cardnumber) = @_;
862
    my ($cardnumber,$branch) = @_;
854
    my $autonumber_members = C4::Context->boolean_preference('autoMemberNum') || 0;
863
    my $autonumber_members = C4::Context->boolean_preference('autoMemberNum') || 0;
855
864
856
    # Find out whether member numbers should be generated
865
    # Find out whether member numbers should be generated
Lines 898-914 sub fixup_cardnumber { Link Here
898
907
899
        return "V$cardnumber$rem";
908
        return "V$cardnumber$rem";
900
     } else {
909
     } else {
910
        my $cardlength = C4::Context->preference('patronbarcodelength');
911
        if (defined($cardnumber) && (length($cardnumber) == $cardlength) && $cardnumber =~ m/^$branch->{'patronbarcodeprefix'}/ ) {
912
           return $cardnumber;
913
        }
901
914
902
     # MODIFIED BY JF: mysql4.1 allows casting as an integer, which is probably
915
     # increment operator without cast(int) should be safe, and should properly increment
903
     # better. I'll leave the original in in case it needs to be changed for you
916
     # whether the string is numeric or not.
904
     # my $sth=$dbh->prepare("select max(borrowers.cardnumber) from borrowers");
917
     # FIXME : This needs to be pulled out into an ajax function, since the interface allows on-the-fly changing of patron home library.
905
        my $sth = $dbh->prepare(
918
     #
906
            "select max(cast(cardnumber as signed)) from borrowers"
919
         my $query =  "select max(borrowers.cardnumber) from borrowers ";
907
        );
920
         my @bind;
908
        $sth->execute;
921
         my $firstnumber = 0;
909
        my ($result) = $sth->fetchrow;
922
         if($branch->{'patronbarcodeprefix'} && $cardlength) {
910
        return $result + 1;
923
             my $cardnum_search = $branch->{'patronbarcodeprefix'} . '%';
911
    }
924
             $query .= " WHERE cardnumber LIKE ?";
925
             $query .= " AND length(cardnumber) = ?";
926
             @bind = ($cardnum_search,$cardlength ) ;
927
         }
928
         my $sth= $dbh->prepare($query);
929
         $sth->execute(@bind);
930
         my ($result) = $sth->fetchrow;
931
         $sth->finish;
932
         if($result) {
933
             my $cnt = 0;
934
             $result =~ s/^$branch->{'patronbarcodeprefix'}//;
935
             while ( $result =~ /([a-zA-Z]*[0-9]*)\z/ ) {   # use perl's magical stringcrement behavior (++).
936
                 my $incrementable = $1;
937
                 $incrementable++;
938
                 if ( length($incrementable) > length($1) ) { # carry a digit to next incrementable fragment
939
                     $cardnumber = substr($incrementable,1) . $cardnumber;
940
                     $result = $`;
941
                 } else {
942
                     $cardnumber = $branch->{'patronbarcodeprefix'} . $` . $incrementable . $cardnumber ;
943
                     last;
944
                 }
945
                 last if(++$cnt>10);
946
             }
947
         } else {
948
             $cardnumber =  ++$firstnumber ;
949
         }
950
     }
912
    return $cardnumber;     # just here as a fallback/reminder 
951
    return $cardnumber;     # just here as a fallback/reminder 
913
}
952
}
914
953
Lines 2368-2373 sub GetBorrowersWithEmail { Link Here
2368
    return @result;
2407
    return @result;
2369
}
2408
}
2370
2409
2410
=head2 _prefix_cardnum
2411
2412
=over 4
2413
2414
$cardnum = _prefix_cardnum($cardnum,$branchcode);
2415
2416
If a system-wide barcode length is defined, and a prefix defined for the passed branch or the user's branch,
2417
modify the barcode by prefixing and padding.
2418
2419
=back
2420
=cut
2421
2422
sub _prefix_cardnum{
2423
    my ($cardnum,$branchcode) = @_;
2424
2425
    if(C4::Context->preference('patronbarcodelength') && (length($cardnum) < C4::Context->preference('patronbarcodelength'))) {
2426
        #if we have a system-wide cardnum length and a branch prefix, prepend the prefix.
2427
        if( ! $branchcode && defined(C4::Context->userenv) ) {
2428
            $branchcode = C4::Context->userenv->{'branch'};
2429
        }
2430
        return $cardnum unless $branchcode;
2431
        my $branch = GetBranchDetail( $branchcode );
2432
        return $cardnum unless( defined($branch) && defined($branch->{'patronbarcodeprefix'}) );
2433
        my $prefix = $branch->{'patronbarcodeprefix'} ;
2434
        my $padding = C4::Context->preference('patronbarcodelength') - length($prefix) - length($cardnum) ;
2435
        $cardnum = $prefix . '0' x $padding . $cardnum if($padding >= 0) ;
2436
   }
2437
    return $cardnum;
2438
}
2371
2439
2372
END { }    # module clean-up code here (global destructor)
2440
END { }    # module clean-up code here (global destructor)
2373
2441
(-)a/admin/branches.pl (-2 / +6 lines)
Lines 68-75 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
68
    }
68
    }
69
);
69
);
70
$template->param(
70
$template->param(
71
     script_name => $script_name,
71
     script_name         => $script_name,
72
     action      => $script_name,
72
     action              => $script_name,
73
     itembarcodelength   => C4::Context->preference('itembarcodelength'),
74
     patronbarcodelength => C4::Context->preference('patronbarcodelength'),
73
);
75
);
74
$template->param( ($op || 'else') => 1 );
76
$template->param( ($op || 'else') => 1 );
75
77
Lines 410-415 sub _branch_to_template { Link Here
410
         opac_info      => $data->{'opac_info'},
412
         opac_info      => $data->{'opac_info'},
411
         branchip       => $data->{'branchip'},
413
         branchip       => $data->{'branchip'},
412
         branchnotes    => $data->{'branchnotes'}, 
414
         branchnotes    => $data->{'branchnotes'}, 
415
         itembarcodeprefix    => $data->{'itembarcodeprefix'},
416
         patronbarcodeprefix  => $data->{'patronbarcodeprefix'},
413
    );
417
    );
414
}
418
}
415
419
(-)a/admin/systempreferences.pl (+2 lines)
Lines 124-129 $tabsysprefs{soundon} = "Admin"; Link Here
124
$tabsysprefs{SpineLabelShowPrintOnBibDetails}   = "Admin";
124
$tabsysprefs{SpineLabelShowPrintOnBibDetails}   = "Admin";
125
$tabsysprefs{WebBasedSelfCheckHeader}           = "Admin";
125
$tabsysprefs{WebBasedSelfCheckHeader}           = "Admin";
126
$tabsysprefs{WebBasedSelfCheckTimeout}          = "Admin";
126
$tabsysprefs{WebBasedSelfCheckTimeout}          = "Admin";
127
$tabsysprefs{itembarcodelength}     = "Admin";
128
$tabsysprefs{patronbarcodelength}   = "Admin";
127
129
128
# Authorities
130
# Authorities
129
$tabsysprefs{authoritysep}          = "Authorities";
131
$tabsysprefs{authoritysep}          = "Authorities";
(-)a/cataloguing/additem.pl (+8 lines)
Lines 347-352 if ($op eq "additem") { Link Here
347
	push @errors,"barcode_not_unique" if($exist_itemnumber);
347
	push @errors,"barcode_not_unique" if($exist_itemnumber);
348
	# if barcode exists, don't create, but report The problem.
348
	# if barcode exists, don't create, but report The problem.
349
    unless ($exist_itemnumber) {
349
    unless ($exist_itemnumber) {
350
            unless ($addedolditem->{'barcode'}) {
351
               use C4::Barcodes;
352
               my $barcodeobj = C4::Barcodes->new();
353
               my $db_max = $barcodeobj->db_max();
354
               my $nextbarcode = $barcodeobj->next_value($db_max);
355
               my ($tagfield,$tagsubfield) = &GetMarcFromKohaField("items.barcode",$frameworkcode);
356
               $record->field($tagfield)->update($tagsubfield => "$nextbarcode") if ($nextbarcode);
357
            }
350
	    my ($oldbiblionumber,$oldbibnum,$oldbibitemnum) = AddItemFromMarc($record,$biblionumber);
358
	    my ($oldbiblionumber,$oldbibnum,$oldbibitemnum) = AddItemFromMarc($record,$biblionumber);
351
        set_item_default_location($oldbibitemnum);
359
        set_item_default_location($oldbibitemnum);
352
    }
360
    }
(-)a/circ/circulation.pl (-1 / +2 lines)
Lines 121-127 if (C4::Context->preference("UseTablesortForCirc")) { Link Here
121
my $barcode        = $query->param('barcode') || '';
121
my $barcode        = $query->param('barcode') || '';
122
$barcode =~  s/^\s*|\s*$//g; # remove leading/trailing whitespace
122
$barcode =~  s/^\s*|\s*$//g; # remove leading/trailing whitespace
123
123
124
$barcode = barcodedecode($barcode) if( $barcode && C4::Context->preference('itemBarcodeInputFilter'));
124
$barcode = barcodedecode($barcode) if( $barcode && (C4::Context->preference('itemBarcodeInputFilter')
125
                                      ||  C4::Context->preference('itembarcodelength')));
125
my $stickyduedate  = $query->param('stickyduedate') || $session->param('stickyduedate');
126
my $stickyduedate  = $query->param('stickyduedate') || $session->param('stickyduedate');
126
my $duedatespec    = $query->param('duedatespec')   || $session->param('stickyduedate');
127
my $duedatespec    = $query->param('duedatespec')   || $session->param('stickyduedate');
127
my $issueconfirmed = $query->param('issueconfirmed');
128
my $issueconfirmed = $query->param('issueconfirmed');
(-)a/circ/returns.pl (-2 / +4 lines)
Lines 108-114 foreach ( $query->param ) { Link Here
108
108
109
    # decode barcode    ## Didn't we already decode them before passing them back last time??
109
    # decode barcode    ## Didn't we already decode them before passing them back last time??
110
    $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace
110
    $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace
111
    $barcode = barcodedecode($barcode) if(C4::Context->preference('itemBarcodeInputFilter'));
111
    $barcode = barcodedecode($barcode) if(C4::Context->preference('itemBarcodeInputFilter')
112
                                          || C4::Context->preference('itembarcodelength'));
112
113
113
    ######################
114
    ######################
114
    #Are these lines still useful ?
115
    #Are these lines still useful ?
Lines 201-207 if ($canceltransfer){ Link Here
201
# actually return book and prepare item table.....
202
# actually return book and prepare item table.....
202
if ($barcode) {
203
if ($barcode) {
203
    $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace
204
    $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace
204
    $barcode = barcodedecode($barcode) if C4::Context->preference('itemBarcodeInputFilter');
205
    $barcode = barcodedecode($barcode) if (C4::Context->preference('itemBarcodeInputFilter')
206
                                           || C4::Context->preference('itembarcodelength'));
205
    $itemnumber = GetItemnumberFromBarcode($barcode);
207
    $itemnumber = GetItemnumberFromBarcode($barcode);
206
208
207
    if ( C4::Context->preference("InProcessingToShelvingCart") ) {
209
    if ( C4::Context->preference("InProcessingToShelvingCart") ) {
(-)a/installer/data/mysql/kohastructure.sql (+2 lines)
Lines 366-371 CREATE TABLE `branches` ( -- information about your libraries or branches are st Link Here
366
  `branchprinter` varchar(100) default NULL, -- unused in Koha
366
  `branchprinter` varchar(100) default NULL, -- unused in Koha
367
  `branchnotes` mediumtext, -- notes related to your library or branch
367
  `branchnotes` mediumtext, -- notes related to your library or branch
368
  opac_info text, -- HTML that displays in OPAC
368
  opac_info text, -- HTML that displays in OPAC
369
  itembarcodeprefix varchar(10) default NULL, -- branch's item barcode prefix
370
  patronbarcodeprefix varchar(10) default NULL, -- branch's patron barcode prefix
369
  PRIMARY KEY (`branchcode`)
371
  PRIMARY KEY (`branchcode`)
370
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
372
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
371
373
(-)a/installer/data/mysql/sysprefs.sql (+2 lines)
Lines 53-58 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES Link Here
53
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('IssuingInProcess',0,'If ON, disables fines if the patron is issuing item that accumulate debt',NULL,'YesNo');
53
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('IssuingInProcess',0,'If ON, disables fines if the patron is issuing item that accumulate debt',NULL,'YesNo');
54
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('item-level_itypes',1,'If ON, enables Item-level Itemtype / Issuing Rules','','YesNo');
54
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('item-level_itypes',1,'If ON, enables Item-level Itemtype / Issuing Rules','','YesNo');
55
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('itemcallnumber','082ab','The MARC field/subfield that is used to calculate the itemcallnumber (Dewey would be 082ab or 092ab; LOC would be 050ab or 090ab) could be 852hi from an item record',NULL,'free');
55
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('itemcallnumber','082ab','The MARC field/subfield that is used to calculate the itemcallnumber (Dewey would be 082ab or 092ab; LOC would be 050ab or 090ab) could be 852hi from an item record',NULL,'free');
56
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('itembarcodelength','','Number of characters in system-wide barcode schema (item barcodes).','','Integer');
56
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('DefaultClassificationSource','ddc','Default classification scheme used by the collection. E.g., Dewey, LCC, etc.', NULL,'ClassSources');
57
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('DefaultClassificationSource','ddc','Default classification scheme used by the collection. E.g., Dewey, LCC, etc.', NULL,'ClassSources');
57
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('KohaAdminEmailAddress','root@localhost','Define the email address where patron modification requests are sent','','free');
58
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('KohaAdminEmailAddress','root@localhost','Define the email address where patron modification requests are sent','','free');
58
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('LabelMARCView','standard','Define how a MARC record will display','standard|economical','Choice');
59
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('LabelMARCView','standard','Define how a MARC record will display','standard|economical','Choice');
Lines 97-102 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES Link Here
97
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('opacuserjs','','Define custom javascript for inclusion in OPAC','70|10','Textarea');
98
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('opacuserjs','','Define custom javascript for inclusion in OPAC','70|10','Textarea');
98
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('opacuserlogin',1,'Enable or disable display of user login features',NULL,'YesNo');
99
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('opacuserlogin',1,'Enable or disable display of user login features',NULL,'YesNo');
99
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('QuoteOfTheDay',0,'Enable or disable display of Quote of the Day on the OPAC home page',NULL,'YesNo');
100
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('QuoteOfTheDay',0,'Enable or disable display of Quote of the Day on the OPAC home page',NULL,'YesNo');
101
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('patronbarcodelength','','Number of characters in system-wide barcode schema (patron cardnumbers).','','Integer');
100
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('patronimages',0,'Enable patron images for the Staff Client',NULL,'YesNo');
102
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('patronimages',0,'Enable patron images for the Staff Client',NULL,'YesNo');
101
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OPACpatronimages',0,'Enable patron images in the OPAC',NULL,'YesNo');
103
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OPACpatronimages',0,'Enable patron images in the OPAC',NULL,'YesNo');
102
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('printcirculationslips',1,'If ON, enable printing circulation receipts','','YesNo');
104
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('printcirculationslips',1,'If ON, enable printing circulation receipts','','YesNo');
(-)a/installer/data/mysql/updatedatabase.pl (+11 lines)
Lines 5473-5478 if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { Link Here
5473
    SetVersion($DBversion);
5473
    SetVersion($DBversion);
5474
}
5474
}
5475
5475
5476
5477
$DBversion = "3.07.00.XXX";
5478
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
5479
    $dbh->do("ALTER TABLE `branches` ADD `itembarcodeprefix` VARCHAR( 10 ) NULL AFTER `branchnotes`");
5480
    $dbh->do("ALTER TABLE `branches` ADD `patronbarcodeprefix` VARCHAR( 10 ) NULL AFTER `itembarcodeprefix`");
5481
    $dbh->do("INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('itembarcodelength','','Number of characters in system-wide barcode schema (item barcodes).','','Integer')");
5482
    $dbh->do("INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('patronbarcodelength','','Number of characters in system-wide barcode schema (patron cardnumbers).','','Integer')");
5483
    print "Upgrade to $DBversion done (Add barcode prefix feature. Add fields itembarcodeprefix and patronbarcodeprefix to table branches, add sysprefs itembarcodelength and patronbarcodelength)\n";
5484
    SetVersion($DBversion);
5485
}
5486
5476
=head1 FUNCTIONS
5487
=head1 FUNCTIONS
5477
5488
5478
=head2 TableExists($table)
5489
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt (+6 lines)
Lines 143-148 tinyMCE.init({ Link Here
143
        <li><label for="branchurl">URL</label><input type="text" name="branchurl" id="branchurl" value="[% branchurl |html %]" /></li>
143
        <li><label for="branchurl">URL</label><input type="text" name="branchurl" id="branchurl" value="[% branchurl |html %]" /></li>
144
        <li><label for="opac_info">OPAC info</label><textarea name="opac_info" id="opac_info">[% opac_info |html %]</textarea></li>
144
        <li><label for="opac_info">OPAC info</label><textarea name="opac_info" id="opac_info">[% opac_info |html %]</textarea></li>
145
        <li><label for="branchip">IP</label><input type="text" name="branchip" id="branchip" value="[% branchip |html %]" /> <span class="hint">Can be entered as a single IP, or a subnet such as 192.168.1.*</span></li>
145
        <li><label for="branchip">IP</label><input type="text" name="branchip" id="branchip" value="[% branchip |html %]" /> <span class="hint">Can be entered as a single IP, or a subnet such as 192.168.1.*</span></li>
146
        [% IF ( itembarcodelength ) %]
147
           <li><label for="itembarcodeprefix">Item Barcode Prefix</label><input type="text" name="itembarcodeprefix" id="itembarcodeprefix" value="[% itembarcodeprefix |html %]" /></li>
148
        [% END %]
149
        [% IF ( patronbarcodelength ) %]
150
           <li><label for="patronbarcodeprefix">Patron Barcode Prefix</label><input type="text" name="patronbarcodeprefix" id="patronbarcodeprefix" value="[% patronbarcodeprefix |html %]" /></li>
151
        [% END %]
146
		<!--
152
		<!--
147
        <li><label for="branchprinter">Library Printer</label>
153
        <li><label for="branchprinter">Library Printer</label>
148
            <select id="branchprinter" name="branchprinter">
154
            <select id="branchprinter" name="branchprinter">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref (+10 lines)
Lines 40-45 Administration: Link Here
40
                  yes: Allow
40
                  yes: Allow
41
                  no: "Don't allow"
41
                  no: "Don't allow"
42
            - staff and patrons to create and view saved lists of books.
42
            - staff and patrons to create and view saved lists of books.
43
        -
44
            - Use branch prefixes to ensure that item barcodes are
45
            - pref: itembarcodelength
46
              class: integer
47
            - digits long
48
        -
49
            - Use branch prefixes to ensure that patron barcodes are
50
            - pref: patronbarcodelength
51
              class: integer
52
            - digits long
43
    Login options:
53
    Login options:
44
        -
54
        -
45
            - pref: insecure
55
            - pref: insecure
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref (+1 lines)
Lines 90-95 Cataloging: Link Here
90
            - Barcodes are
90
            - Barcodes are
91
            - pref: autoBarcode
91
            - pref: autoBarcode
92
              choices:
92
              choices:
93
                  prefix_incr: generated with the branch prefix, followed by a zero-padded form of 1, 2, 3.
93
                  incremental: generated in the form 1, 2, 3.
94
                  incremental: generated in the form 1, 2, 3.
94
                  annual: generated in the form &lt;year&gt;-0001, &lt;year&gt;-0002.
95
                  annual: generated in the form &lt;year&gt;-0001, &lt;year&gt;-0002.
95
                  hbyymmincr: generated in the form &lt;branchcode&gt;yymm0001.
96
                  hbyymmincr: generated in the form &lt;branchcode&gt;yymm0001.
(-)a/members/memberentry.pl (-7 / +8 lines)
Lines 433-439 if ( $op eq "duplicate" ) { Link Here
433
    $template->param( step_1 => 1, step_2 => 1, step_3 => 1, step_4 => 1, step_5 => 1, step_6 => 1 ) unless $step;
433
    $template->param( step_1 => 1, step_2 => 1, step_3 => 1, step_4 => 1, step_5 => 1, step_6 => 1 ) unless $step;
434
}
434
}
435
435
436
$data{'cardnumber'}=fixup_cardnumber($data{'cardnumber'}) if $op eq 'add';
436
my $onlymine=(C4::Context->preference('IndependantBranches') &&
437
              C4::Context->userenv &&
438
              C4::Context->userenv->{flags} % 2 !=1  &&
439
              C4::Context->userenv->{branch}?1:0);
440
441
my $branches=GetBranches($onlymine);
442
$data{'cardnumber'}=fixup_cardnumber( $data{'cardnumber'}, $branches->{C4::Context->userenv->{'branch'}} ) if $op eq 'add';
443
437
if(!defined($data{'sex'})){
444
if(!defined($data{'sex'})){
438
    $template->param( none => 1);
445
    $template->param( none => 1);
439
} elsif($data{'sex'} eq 'F'){
446
} elsif($data{'sex'} eq 'F'){
Lines 570-581 my @branches; Link Here
570
my @select_branch;
577
my @select_branch;
571
my %select_branches;
578
my %select_branches;
572
579
573
my $onlymine=(C4::Context->preference('IndependantBranches') && 
574
              C4::Context->userenv && 
575
              C4::Context->userenv->{flags} % 2 !=1  && 
576
              C4::Context->userenv->{branch}?1:0);
577
              
578
my $branches=GetBranches($onlymine);
579
my $default;
580
my $default;
580
my $CGIbranch;
581
my $CGIbranch;
581
for my $branch (sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} } keys %$branches) {
582
for my $branch (sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} } keys %$branches) {
(-)a/offline_circ/process_koc.pl (-2 / +2 lines)
Lines 241-247 sub arguments_for_command { Link Here
241
sub kocIssueItem {
241
sub kocIssueItem {
242
    my $circ = shift;
242
    my $circ = shift;
243
243
244
    $circ->{ 'barcode' } = barcodedecode($circ->{'barcode'}) if( $circ->{'barcode'} && C4::Context->preference('itemBarcodeInputFilter'));
244
    $circ->{ 'barcode' } = barcodedecode($circ->{'barcode'}) if( $circ->{'barcode'} && (C4::Context->preference('itemBarcodeInputFilter') || C4::Context->preference('itembarcodelength')));
245
    my $branchcode = C4::Context->userenv->{branch};
245
    my $branchcode = C4::Context->userenv->{branch};
246
    my $borrower = GetMember( 'cardnumber'=>$circ->{ 'cardnumber' } );
246
    my $borrower = GetMember( 'cardnumber'=>$circ->{ 'cardnumber' } );
247
    my $item = GetBiblioFromItemNumber( undef, $circ->{ 'barcode' } );
247
    my $item = GetBiblioFromItemNumber( undef, $circ->{ 'barcode' } );
Lines 319-325 sub kocIssueItem { Link Here
319
319
320
sub kocReturnItem {
320
sub kocReturnItem {
321
    my ( $circ ) = @_;
321
    my ( $circ ) = @_;
322
    $circ->{'barcode'} = barcodedecode($circ->{'barcode'}) if( $circ->{'barcode'} && C4::Context->preference('itemBarcodeInputFilter'));
322
    $circ->{'barcode'} = barcodedecode($circ->{'barcode'}) if( $circ->{'barcode'} && (C4::Context->preference('itemBarcodeInputFilter') || C4::Context->preference('itembarcodelength')));
323
    my $item = GetBiblioFromItemNumber( undef, $circ->{ 'barcode' } );
323
    my $item = GetBiblioFromItemNumber( undef, $circ->{ 'barcode' } );
324
    #warn( Data::Dumper->Dump( [ $circ, $item ], [ qw( circ item ) ] ) );
324
    #warn( Data::Dumper->Dump( [ $circ, $item ], [ qw( circ item ) ] ) );
325
    my $borrowernumber = _get_borrowernumber_from_barcode( $circ->{'barcode'} );
325
    my $borrowernumber = _get_borrowernumber_from_barcode( $circ->{'barcode'} );
(-)a/tools/import_borrowers.pl (-2 / +8 lines)
Lines 41-47 use C4::Auth; Link Here
41
use C4::Output;
41
use C4::Output;
42
use C4::Dates qw(format_date_in_iso);
42
use C4::Dates qw(format_date_in_iso);
43
use C4::Context;
43
use C4::Context;
44
use C4::Branch qw(GetBranchName);
44
use C4::Branch qw(GetBranchName GetBranches);
45
use C4::Members;
45
use C4::Members;
46
use C4::Members::Attributes qw(:all);
46
use C4::Members::Attributes qw(:all);
47
use C4::Members::AttributeTypes;
47
use C4::Members::AttributeTypes;
Lines 271-277 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
271
            # FIXME: fixup_cardnumber says to lock table, but the web interface doesn't so this doesn't either.
271
            # FIXME: fixup_cardnumber says to lock table, but the web interface doesn't so this doesn't either.
272
            # At least this is closer to AddMember than in members/memberentry.pl
272
            # At least this is closer to AddMember than in members/memberentry.pl
273
            if (!$borrower{'cardnumber'}) {
273
            if (!$borrower{'cardnumber'}) {
274
                $borrower{'cardnumber'} = fixup_cardnumber(undef);
274
              my $onlymine=(C4::Context->preference('IndependantBranches') &&
275
              C4::Context->userenv &&
276
              C4::Context->userenv->{flags} % 2 !=1  &&
277
              C4::Context->userenv->{branch}?1:0);
278
279
              my $branches=GetBranches($onlymine);
280
              $borrower{'cardnumber'} = fixup_cardnumber(undef,$branches->{$borrower{'branchcode'}});
275
            }
281
            }
276
            if ($borrowernumber = AddMember(%borrower)) {
282
            if ($borrowernumber = AddMember(%borrower)) {
277
                if ($extended) {
283
                if ($extended) {
(-)a/tools/inventory.pl (-1 / +6 lines)
Lines 150-155 if ($uploadbarcodes && length($uploadbarcodes)>0){ Link Here
150
    my $count=0;
150
    my $count=0;
151
    while (my $barcode=<$uploadbarcodes>){
151
    while (my $barcode=<$uploadbarcodes>){
152
        $barcode =~ s/\r?\n$//;
152
        $barcode =~ s/\r?\n$//;
153
        if(C4::Context->preference('itembarcodelength') && (length($barcode) < C4::Context->preference('itembarcodelength'))) {
154
                my $prefix = GetBranchDetail(C4::Context->userenv->{'branch'})->{'itembarcodeprefix'} ;
155
                my $padding = C4::Context->preference('itembarcodelength') - length($prefix) - length($barcode) ;
156
                $barcode = $prefix . '0' x $padding . $barcode if($padding >= 0) ;
157
        }
158
153
        if ($qwthdrawn->execute($barcode) &&$qwthdrawn->rows){
159
        if ($qwthdrawn->execute($barcode) &&$qwthdrawn->rows){
154
            push @errorloop, {'barcode'=>$barcode,'ERR_WTHDRAWN'=>1};
160
            push @errorloop, {'barcode'=>$barcode,'ERR_WTHDRAWN'=>1};
155
        }else{
161
        }else{
156
- 

Return to bug 7676