EAN13 support
authorDobrica Pavlinusic <dpavlin@rot13.org>
Tue, 21 Jun 2011 21:45:37 +0000 (23:45 +0200)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Tue, 21 Jun 2011 21:45:37 +0000 (23:45 +0200)
koha-patches/ean13-barcodes.diff [new file with mode: 0644]

diff --git a/koha-patches/ean13-barcodes.diff b/koha-patches/ean13-barcodes.diff
new file mode 100644 (file)
index 0000000..da7b14b
--- /dev/null
@@ -0,0 +1,357 @@
+diff --git a/C4/Barcodes.pm b/C4/Barcodes.pm
+index a528bd9..44e906a 100644
+--- a/C4/Barcodes.pm
++++ b/C4/Barcodes.pm
+@@ -28,6 +28,7 @@ use C4::Dates;
+ use C4::Barcodes::hbyymmincr;
+ use C4::Barcodes::annual;
+ use C4::Barcodes::incremental;
++use C4::Barcodes::EAN13;
+ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ use vars qw($debug $cgi_debug);       # from C4::Debug, of course
+@@ -137,8 +138,8 @@ sub next_value ($;$) {
+       $incr++;
+       $debug and warn "$incr";
+-      $head = $self->process_head($head,$max,$specific);
+-      $tail = $self->process_tail($tail,$max,$specific);
++      $head = $self->process_head($head,$incr,$specific);
++      $tail = $self->process_tail($tail,$incr,$specific); # XXX use $incr and not $max!
+       my $next_value = $head . $incr . $tail;
+       $debug and print STDERR "(  next ) max barcode found: $next_value\n";
+       return $next_value;
+@@ -177,6 +178,7 @@ our $types = {
+       incremental => sub {C4::Barcodes::incremental->new_object(@_);},
+       hbyymmincr  => sub {C4::Barcodes::hbyymmincr->new_object(@_); },
+       OFF         => sub {C4::Barcodes::OFF->new_object(@_);        },
++      EAN13       => sub {C4::Barcodes::EAN13->new_object(@_);        },
+ };
+ sub new {
+diff --git a/C4/Barcodes/EAN13.pm b/C4/Barcodes/EAN13.pm
+new file mode 100644
+index 0000000..2168ae6
+--- /dev/null
++++ b/C4/Barcodes/EAN13.pm
+@@ -0,0 +1,59 @@
++package C4::Barcodes::EAN13;
++
++# This file is part of Koha.
++#
++# Koha is free software; you can redistribute it and/or modify it under the
++# terms of the GNU General Public License as published by the Free Software
++# Foundation; either version 2 of the License, or (at your option) any later
++# version.
++#
++# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
++# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License along
++# with Koha; if not, write to the Free Software Foundation, Inc.,
++# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++
++use strict;
++use warnings;
++
++use Carp;
++
++use C4::Context;
++use C4::Debug;
++use C4::Dates;
++
++use Algorithm::CheckDigits;
++
++use vars qw($VERSION @ISA);
++use vars qw($debug $cgi_debug);       # from C4::Debug, of course
++use vars qw($width);
++
++BEGIN {
++    $VERSION = 0.01;
++    @ISA = qw(C4::Barcodes);
++}
++
++sub parse ($;$) {
++      my $self = shift;
++      my $barcode = (@_) ? shift : $self->value;
++      my $ean = CheckDigits('ean');
++      if ( $ean->is_valid($barcode) ) {
++              return ( '', $ean->basenumber($barcode), $ean->checkdigit($barcode) );
++      } else {
++              carp "$barcode not valid EAN-13 barcode";
++      }
++}
++
++sub process_tail($$;$$) {
++      my ( $self,$tail,$whole,$specific ) = @_;
++      my $ean = CheckDigits('ean');
++      my $full = $ean->complete($whole);
++      my $chk  = $ean->checkdigit($full);
++      $debug && warn "# process_tail $tail -> $chk [$whole -> $full] $specific";
++      return $chk;
++}
++
++1;
++__END__
+diff --git a/C4/Circulation.pm b/C4/Circulation.pm
+index 2869fc6..f2addd8 100644
+--- a/C4/Circulation.pm
++++ b/C4/Circulation.pm
+@@ -46,6 +46,7 @@ use Date::Calc qw(
+ use POSIX qw(strftime);
+ use C4::Branch; # GetBranches
+ use C4::Log; # logaction
++use Algorithm::CheckDigits;
+ use Data::Dumper;
+@@ -156,6 +157,12 @@ sub barcodedecode {
+         # FIXME: $barcode could be "T1", causing warning: substr outside of string
+         # Why drop the nonzero digit after the T?
+         # Why pass non-digits (or empty string) to "T%07d"?
++      } elsif ($filter eq 'EAN13') {
++              $barcode = sprintf('%013d',$barcode);
++              my $ean = CheckDigits('ean');
++              if ( ! $ean->is_valid($barcode) ) {
++                      warn "[$barcode] not valid EAN-13/UPC-A";
++              }
+       }
+     return $barcode;    # return barcode, modified or not
+ }
+diff --git a/C4/Creators/Lib.pm b/C4/Creators/Lib.pm
+index 8fd25fd..b26949e 100644
+--- a/C4/Creators/Lib.pm
++++ b/C4/Creators/Lib.pm
+@@ -90,7 +90,7 @@ my $barcode_types = [
+     {type => 'CODE39MOD',       name => 'Code 39 + Modulo43',   desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 43 checksum.',         selected => 0},
+     {type => 'CODE39MOD10',     name => 'Code 39 + Modulo10',   desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 10 checksum.',         selected => 0},
+     {type => 'COOP2OF5',        name => 'COOP2of5',             desc => 'Creates COOP2of5 barcodes from a string consisting of the numeric characters 0-9',                                                                     selected => 0},
+-#    {type => 'EAN13',           name => 'EAN13',                desc => 'Creates EAN13 barcodes from a string of 12 or 13 digits. The check number (the 13:th digit) is calculated if not supplied.',                           selected => 0},
++    {type => 'EAN13',           name => 'EAN13',                desc => 'Creates EAN13 barcodes from a string of 12 or 13 digits. The check number (the 13:th digit) is calculated if not supplied.',                           selected => 0},
+ #    {type => 'EAN8',            name => 'EAN8',                 desc => 'Translates a string of 7 or 8 digits to EAN8 barcodes. The check number (the 8:th digit) is calculated if not supplied.',                              selected => 0},
+ #    {type => 'IATA2of5',        name => 'IATA2of5',             desc => 'Creates IATA2of5 barcodes from a string consisting of the numeric characters 0-9',                                                                     selected => 0},
+     {type => 'INDUSTRIAL2OF5',  name => 'Industrial2of5',       desc => 'Creates Industrial2of5 barcodes from a string consisting of the numeric characters 0-9',                                                               selected => 0},
+diff --git a/C4/Labels/Label.pm b/C4/Labels/Label.pm
+index 0c98d6f..0abf308 100644
+--- a/C4/Labels/Label.pm
++++ b/C4/Labels/Label.pm
+@@ -550,6 +550,28 @@ sub barcode {
+             warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
+         }
+     }
++    elsif ($params{'barcode_type'} eq 'EAN13') {
++        $bar_length = 4; # FIXME
++      $num_of_bars = 13;
++        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
++        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
++        eval {
++            PDF::Reuse::Barcode::EAN13(
++                x                   => $params{'llx'},
++                y                   => $params{'lly'},
++                value               => sprintf('%013d',$params{barcode_data}),
++#                xSize               => $x_scale_factor,
++#                ySize               => $params{'y_scale_factor'},
++                mode                    => 'graphic',
++            );
++        };
++        if ($@) {
++            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
++        }
++    }
++    else {
++      warn "unknown barcode_type: $params{barcode_type}";
++    }
+ }
+ sub csv_data {
+@@ -605,6 +627,9 @@ This module provides methods for creating, and otherwise manipulating single lab
+ =item .
+             INDUSTRIAL2OF5  = The standard 2 of 5 barcode (a binary level bar code developed by Identicon Corp. and Computer Identics Corp. in 1970)
++=item .
++            EAN13           = The standard EAN-13 barcode
++
+ =back
+         C<printing_type>        Defines the general layout to be used on labels. NOTE: At present there are only five printing types supported in the label creator code:
+diff --git a/cataloguing/value_builder/barcode.pl b/cataloguing/value_builder/barcode.pl
+index c05ec48..9b25bc5 100755
+--- a/cataloguing/value_builder/barcode.pl
++++ b/cataloguing/value_builder/barcode.pl
+@@ -24,6 +24,8 @@ no warnings 'redefine'; # otherwise loading up multiple plugins fills the log wi
+ use C4::Context;
+ require C4::Dates;
++use Algorithm::CheckDigits;
++
+ my $DEBUG = 0;
+ =head1
+@@ -123,6 +125,26 @@ sub plugin_javascript {
+         }
+         ";
+     }
++      elsif ($autoBarcodeType eq 'EAN13') {
++              # not the best, two catalogers could add the same barcode easily this way :/
++              $query = "select max(abs(barcode)) from items";
++              my $sth = $dbh->prepare($query);
++              $sth->execute();
++              while (my ($count)= $sth->fetchrow_array) {
++                      $nextnum = $count;
++              }
++              my $ean = CheckDigits('ean');
++              if ( $ean->is_valid($nextnum) ) {
++                      my $next = $ean->basenumber( $nextnum ) + 1;
++                      $nextnum = sprintf('%013d',$ean->complete( $next ));
++              } else {
++                      warn "ERROR: invalid EAN-13 $nextnum, using increment";
++                      $nextnum++;
++              }
++      }
++      else {
++              warn "ERROR: unknown autoBarcode: $autoBarcodeType";
++      }
+     # default js body (if not filled by hbyymmincr)
+     $scr or $scr = <<END_OF_JS;
+diff --git a/installer/data/mysql/en/mandatory/sysprefs.sql b/installer/data/mysql/en/mandatory/sysprefs.sql
+index 0aebcb5..a0111a1 100644
+--- a/installer/data/mysql/en/mandatory/sysprefs.sql
++++ b/installer/data/mysql/en/mandatory/sysprefs.sql
+@@ -146,7 +146,7 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
+ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('finesMode','test','Choose the fines mode, \'off\', \'test\' (emails admin report) or \'production\' (accrue overdue fines).  Requires accruefines cronjob.','off|test|production','Choice');
+ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('globalDueDate','','If set, allows a global static due date for all checkouts','10','free');
+ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('ceilingDueDate','','If set, date due will not be past this date.  Enter date according to the dateformat System Preference',NULL,'free');
+-INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('itemBarcodeInputFilter','','If set, allows specification of a item barcode input filter','whitespace|T-prefix|cuecat','Choice');
++INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('itemBarcodeInputFilter','','If set, allows specification of a item barcode input filter','whitespace|T-prefix|cuecat|EAN13','Choice');
+ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('singleBranchMode',0,'Operate in Single-branch mode, hide branch selection in the OPAC',NULL,'YesNo');
+ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('URLLinkText','','Text to display as the link anchor in the OPAC',NULL,'free');
+ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OPACViewOthersSuggestions',0,'If ON, allows all suggestions to be displayed in the OPAC',NULL,'YesNo');
+diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl
+index 6888b72..0fc6a71 100755
+--- a/installer/data/mysql/updatedatabase.pl
++++ b/installer/data/mysql/updatedatabase.pl
+@@ -4074,6 +4074,16 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
+     SetVersion ($DBversion);
+ }
++$DBversion = "3.02.09.001"; # FIXME
++if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
++    $dbh->do("UPDATE `systempreferences` SET options='whitespace|t-prefix|cuecat|libsuite8|ean13' WHERE variable='itembarcodeinputfilter'");
++    print "Upgrade to $DBversion done (Add itemBarcodeInputFilter choice EAN13)\n";
++
++    $dbh->do("UPDATE systempreferences SET options = concat(options,'|EAN13'), explanation = concat(explanation,'; EAN13 - incremental') WHERE variable = 'autoBarcode';");
++    print "Upgrade to $DBversion done ( Added EAN13 barcode autogeneration sequence )\n";
++    SetVersion($DBversion);
++}
++
+ =head1 FUNCTIONS
+ =head2 DropAllForeignKeys($table)
+diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref
+index c8dad2c..7466d54 100644
+--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref
++++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref
+@@ -77,6 +77,7 @@ Cataloging:
+                   incremental: generated in the form 1, 2, 3.
+                   annual: generated in the form &lt;year&gt;-0001, &lt;year&gt;-0002.
+                   hbyymmincr: generated in the form &lt;branchcode&gt;yymm0001.
++                  EAN13: incremental EAN-13 barcodes
+                   "OFF": not generated automatically.
+     Display:
+         -
+diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+index b948495..4daa2ef 100644
+--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
++++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+@@ -14,6 +14,7 @@ Circulation:
+                   whitespace: Remove spaces from
+                   cuecat: Convert from CueCat form
+                   T-prefix: Remove the first number from T-prefix style
++                  EAN13: upgrade 12-digit UPC-A to EAN13 and check validity
+             - scanned patron barcodes.
+         -
+             - Sort previous checkouts on the circulation page from
+diff --git a/kohaversion.pl b/kohaversion.pl
+index 97617db..2c9321f 100644
+--- a/kohaversion.pl
++++ b/kohaversion.pl
+@@ -16,7 +16,7 @@ the kohaversion is divided in 4 parts :
+ use strict;
+ sub kohaversion {
+-    our $VERSION = '3.02.09.000';
++    our $VERSION = '3.02.09.001';
+     # version needs to be set this way
+     # so that it can be picked up by Makefile.PL
+     # during install
+diff --git a/t/Barcodes_EAN13.t b/t/Barcodes_EAN13.t
+new file mode 100755
+index 0000000..a859ade
+--- /dev/null
++++ b/t/Barcodes_EAN13.t
+@@ -0,0 +1,14 @@
++#!/usr/bin/perl
++#
++# This Koha test module is a stub!  
++# Add more tests here!!!
++
++use strict;
++use warnings;
++
++use Test::More tests => 1;
++
++BEGIN {
++        use_ok('C4::Barcodes::EAN13');
++}
++
+diff --git a/t/Circulation_barcodedecode.t b/t/Circulation_barcodedecode.t
+index 5f2edc2..df007a2 100644
+--- a/t/Circulation_barcodedecode.t
++++ b/t/Circulation_barcodedecode.t
+@@ -4,7 +4,7 @@
+ use strict;
+ use warnings;
+-use Test::More tests => 16;
++use Test::More tests => 18;
+ BEGIN {
+     use_ok('C4::Circulation');
+@@ -15,12 +15,14 @@ our %inputs = (
+                     'q.C3nZC3nZC3nWDNzYDxf2CNnY.fHmc.C3DWC3nZCNjXD3nW.', '.C3nZC3nZC3nWCxjWE3D1C3nX.cGf2.ENr7C3v7D3T3ENj3C3zYDNnZ.' ],
+     whitespace => [" 26002315", "26002315 ", "\n\t26002315\n"],
+     'T-prefix' => [qw(T0031472 T32)],
++    EAN13      => [qw(892685001928 000000695152)],
+     other      => [qw(26002315 T0031472 T32 Alphanum123), "Alpha Num 345"],
+ );
+ our %outputs = (
+     cuecat     => ["26002315", "046675000808", "046675000808", "043000112403", "978068484914051500"],
+     whitespace => [qw(26002315 26002315 26002315)],
+     'T-prefix' => [qw(T0031472 T0000002         )],
++    EAN13      => [qw(0892685001928 0000000695152)],
+     other      => [qw(26002315 T0031472 T32 Alphanum123), "Alpha Num 345"],
+ );
+     
+diff --git a/t/db_dependent/Barcodes.t b/t/db_dependent/Barcodes.t
+index cd50178..3a78452 100755
+--- a/t/db_dependent/Barcodes.t
++++ b/t/db_dependent/Barcodes.t
+@@ -3,7 +3,7 @@
+ use strict;
+ use warnings;
+-use Test::More tests => 49;
++use Test::More tests => 66;
+ BEGIN {
+       use FindBin;
+       use lib $FindBin::Bin;
+@@ -14,6 +14,7 @@ my %thash = (
+       incremental => [],
+       annual => [],
+       hbyymmincr => ['MAIN'],
++      EAN13 => ['0000000695152','892685001928'],
+ );
+ print "\n";