[Koha-patches] [PATCH] Bug 8524: Add a non-automatic barcode plugin

Jared Camins-Esakov jcamins at cpbibliography.com
Wed Aug 1 18:27:09 CEST 2012


In addition to adding a new barcode plugin, this commit begins
refactoring the barcode generation code using a new module,
C4::Barcodes::ValueBuilder. From the POD:
    This module is intended as a shim to ease the eventual transition
    from having all barcode-related code in the value builder plugin
    barcode.pl file to using C4::Barcodes. Since the shift will require
    a rather significant amount of refactoring, this module will return
    value builder-formatted results, at first by merely running the
    code that was formerly in the barcodes.pl value builder, but later
    by using C4::Barcodes.
---
 C4/Barcodes/ValueBuilder.pm                 |  109 ++++++++++++++++++++++
 cataloguing/value_builder/barcode.pl        |   53 ++---------
 cataloguing/value_builder/barcode_manual.pl |  132 +++++++++++++++++++++++++++
 t/Barcodes_ValueBuilder.t                   |   78 ++++++++++++++++
 4 files changed, 327 insertions(+), 45 deletions(-)
 create mode 100644 C4/Barcodes/ValueBuilder.pm
 create mode 100755 cataloguing/value_builder/barcode_manual.pl
 create mode 100644 t/Barcodes_ValueBuilder.t

diff --git a/C4/Barcodes/ValueBuilder.pm b/C4/Barcodes/ValueBuilder.pm
new file mode 100644
index 0000000..10cd504
--- /dev/null
+++ b/C4/Barcodes/ValueBuilder.pm
@@ -0,0 +1,109 @@
+#!/usr/bin/perl
+#
+# Copyright 2008-2010 Foundations Bible College
+# Parts copyright 2012 C & P Bibliography Services
+#
+# 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.
+
+package C4::Barcodes::ValueBuilder::incremental;
+use C4::Context;
+my $DEBUG = 0;
+
+sub get_barcode {
+    my ($args) = @_;
+    my $nextnum;
+    # not the best, two catalogers could add the same barcode easily this way :/
+    my $query = "select max(abs(barcode)) from items";
+    my $sth = C4::Context->dbh->prepare($query);
+    $sth->execute();
+    while (my ($count)= $sth->fetchrow_array) {
+        $nextnum = $count;
+    }
+    $nextnum++;
+    return $nextnum;
+}
+
+1;
+
+package C4::Barcodes::ValueBuilder::hbyymmincr;
+use C4::Context;
+my $DEBUG = 0;
+
+sub get_barcode {
+    my ($args) = @_;
+    my $nextnum;
+    my $year = substr($args->{year}, -2);
+    my $query = "SELECT MAX(CAST(SUBSTRING(barcode,-4) AS signed)) AS number FROM items WHERE barcode REGEXP ?";
+    my $sth = C4::Context->dbh->prepare($query);
+    $sth->execute("^[-a-zA-Z]{1,}$year");
+    while (my ($count)= $sth->fetchrow_array) {
+        $nextnum = $count if $count;
+        $nextnum = 0 if $nextnum == 9999; # this sequence only allows for cataloging 10000 books per month
+            warn "Existing incremental number = $nextnum" if $DEBUG;
+    }
+    $nextnum++;
+    $nextnum = sprintf("%0*d", "4",$nextnum);
+    $nextnum = $year . $args->{mon} . $nextnum;
+    warn "New hbyymmincr Barcode = $nextnum" if $DEBUG;
+    my $scr = " 
+        for (i=0 ; i<document.f.field_value.length ; i++) {
+            if (document.f.tag[i].value == '$args->{loctag}' && document.f.subfield[i].value == '$args->{locsubfield}') {
+                fnum = i;
+            }
+        }
+    if (\$('#' + id).val() == '' || force) {
+        \$('#' + id).val(document.f.field_value[fnum].value + '$nextnum');
+    }
+    ";
+    return $nextnum, $scr;
+}
+
+
+package C4::Barcodes::ValueBuilder::annual;
+use C4::Context;
+my $DEBUG = 0;
+
+sub get_barcode {
+    my ($args) = @_;
+    my $nextnum;
+    my $query = "select max(cast( substring_index(barcode, '-',-1) as signed)) from items where barcode like ?";
+    my $sth=C4::Context->dbh->prepare($query);
+    $sth->execute("$args->{year}%");
+    while (my ($count)= $sth->fetchrow_array) {
+        warn "Examining Record: $count" if $DEBUG;
+        $nextnum = $count if $count;
+    }
+    $nextnum++;
+    $nextnum = sprintf("%0*d", "4",$nextnum);
+    $nextnum = "$args->{year}-$nextnum";
+    return $nextnum;
+}
+
+1;
+
+
+=head1 Barcodes::ValueBuilder
+
+This module is intended as a shim to ease the eventual transition from
+having all barcode-related code in the value builder plugin .pl file
+to using C4::Barcodes. Since the shift will require a rather significant
+amount of refactoring, this module will return value builder-formatted
+results, at first by merely running the code that was formerly in the
+barcodes.pl value builder, but later by using C4::Barcodes.
+
+=cut
+
+1;
diff --git a/cataloguing/value_builder/barcode.pl b/cataloguing/value_builder/barcode.pl
index c5e1fd3..cb89a32 100755
--- a/cataloguing/value_builder/barcode.pl
+++ b/cataloguing/value_builder/barcode.pl
@@ -22,6 +22,7 @@ use warnings;
 no warnings 'redefine'; # otherwise loading up multiple plugins fills the log with subroutine redefine warnings
 
 use C4::Context;
+require C4::Barcodes::ValueBuilder;
 require C4::Dates;
 
 my $DEBUG = 0;
@@ -55,14 +56,14 @@ the 3 scripts are inserted after the <input> in the html code
 sub plugin_javascript {
 	my ($dbh,$record,$tagslib,$field_number,$tabloop) = @_;
 	my $function_name= "barcode".(int(rand(100000))+1);
+    my %args;
 
 	# find today's date
-	my ($year, $mon, $day) = split('-', C4::Dates->today('iso'));
-	my ($tag,$subfield)       =  GetMarcFromKohaField("items.barcode", '');
-	my ($loctag,$locsubfield) =  GetMarcFromKohaField("items.homebranch", '');
+    ($args{year}, $args{mon}, $args{day}) = split('-', C4::Dates->today('iso'));
+    ($args{tag},$args{subfield})       =  GetMarcFromKohaField("items.barcode", '');
+    ($args{loctag},$args{locsubfield}) =  GetMarcFromKohaField("items.homebranch", '');
 
 	my $nextnum;
-	my $query;
     my $scr;
 	my $autoBarcodeType = C4::Context->preference("autoBarcode");
     warn "Barcode type = $autoBarcodeType" if $DEBUG;
@@ -77,51 +78,13 @@ sub plugin_javascript {
         </script>");
     }
 	if ($autoBarcodeType eq 'annual') {
-		$query = "select max(cast( substring_index(barcode, '-',-1) as signed)) from items where barcode like ?";
-		my $sth=$dbh->prepare($query);
-		$sth->execute("$year%");
-		while (my ($count)= $sth->fetchrow_array) {
-            warn "Examining Record: $count" if $DEBUG;
-    		$nextnum = $count if $count;
-		}
-		$nextnum++;
-		$nextnum = sprintf("%0*d", "4",$nextnum);
-		$nextnum = "$year-$nextnum";
+        ($nextnum, $scr) = C4::Barcodes::ValueBuilder::annual::get_barcode(\%args);
 	}
 	elsif ($autoBarcodeType eq 'incremental') {
-		# 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;
-		}
-		$nextnum++;
+        ($nextnum, $scr) = C4::Barcodes::ValueBuilder::incremental::get_barcode(\%args);
     }
     elsif ($autoBarcodeType eq 'hbyymmincr') {      # Generates a barcode where hb = home branch Code, yymm = year/month catalogued, incr = incremental number, reset yearly -fbcit
-        $year = substr($year, -2);
-        $query = "SELECT MAX(CAST(SUBSTRING(barcode,-4) AS signed)) AS number FROM items WHERE barcode REGEXP ?";
-        my $sth = $dbh->prepare($query);
-        $sth->execute("^[-a-zA-Z]{1,}$year");
-        while (my ($count)= $sth->fetchrow_array) {
-            $nextnum = $count if $count;
-            $nextnum = 0 if $nextnum == 9999; # this sequence only allows for cataloging 10000 books per month
-            warn "Existing incremental number = $nextnum" if $DEBUG;
-        }
-        $nextnum++;
-        $nextnum = sprintf("%0*d", "4",$nextnum);
-        $nextnum = $year . $mon . $nextnum;
-        warn "New hbyymmincr Barcode = $nextnum" if $DEBUG;
-        $scr = " 
-        for (i=0 ; i<document.f.field_value.length ; i++) {
-            if (document.f.tag[i].value == '$loctag' && document.f.subfield[i].value == '$locsubfield') {
-                fnum = i;
-            }
-        }
-        if (\$('#' + id).val() == '' || force) {
-            \$('#' + id).val(document.f.field_value[fnum].value + '$nextnum');
-        }
-        ";
+        ($nextnum, $scr) = C4::Barcodes::ValueBuilder::hbyymmincr::get_barcode(\%args);
     }
 
     # default js body (if not filled by hbyymmincr)
diff --git a/cataloguing/value_builder/barcode_manual.pl b/cataloguing/value_builder/barcode_manual.pl
new file mode 100755
index 0000000..b2f4105
--- /dev/null
+++ b/cataloguing/value_builder/barcode_manual.pl
@@ -0,0 +1,132 @@
+#!/usr/bin/perl
+# Copyright 2000-2002 Katipo Communications
+# Parts copyright 2008-2010 Foundations Bible College
+#
+# 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;
+no warnings 'redefine'; # otherwise loading up multiple plugins fills the log with subroutine redefine warnings
+
+use C4::Context;
+require C4::Barcodes::ValueBuilder;
+require C4::Dates;
+
+my $DEBUG = 0;
+
+=head1
+
+plugin_parameters : other parameters added when the plugin is called by the dopop function
+
+=cut
+
+sub plugin_parameters {
+#   my ($dbh,$record,$tagslib,$i,$tabloop) = @_;
+    return "";
+}
+
+=head1
+
+plugin_javascript : the javascript function called when the user enters the subfield.
+contain 3 javascript functions :
+* one called when the field is entered (OnFocus). Named FocusXXX
+* one called when the field is leaved (onBlur). Named BlurXXX
+* one called when the ... link is clicked (<a href="javascript:function">) named ClicXXX
+
+returns :
+* XXX
+* a variable containing the 3 scripts.
+the 3 scripts are inserted after the <input> in the html code
+
+=cut
+
+sub plugin_javascript {
+    my ($dbh,$record,$tagslib,$field_number,$tabloop) = @_;
+    my $function_name= "barcode".(int(rand(100000))+1);
+    my %args;
+
+    $args{dbh} = $dbh;
+
+# find today's date
+    ($args{year}, $args{mon}, $args{day}) = split('-', C4::Dates->today('iso'));
+    ($args{tag},$args{subfield})       =  GetMarcFromKohaField("items.barcode", '');
+    ($args{loctag},$args{locsubfield}) =  GetMarcFromKohaField("items.homebranch", '');
+
+    my $nextnum;
+    my $scr;
+    my $autoBarcodeType = C4::Context->preference("autoBarcode");
+    warn "Barcode type = $autoBarcodeType" if $DEBUG;
+    if ((not $autoBarcodeType) or $autoBarcodeType eq 'OFF') {
+# don't return a value unless we have the appropriate syspref set
+        return ($function_name, 
+                "<script type=\"text/javascript\">
+                // autoBarcodeType OFF (or not defined)
+                function Focus$function_name() { return 0;}
+                function  Clic$function_name() { return 0;}
+                function  Blur$function_name() { return 0;}
+                </script>");
+    }
+    if ($autoBarcodeType eq 'annual') {
+        ($nextnum, $scr) = C4::Barcodes::ValueBuilder::annual::get_barcode(\%args);
+    }
+    elsif ($autoBarcodeType eq 'incremental') {
+        ($nextnum, $scr) = C4::Barcodes::ValueBuilder::incremental::get_barcode(\%args);
+    }
+    elsif ($autoBarcodeType eq 'hbyymmincr') {      # Generates a barcode where hb = home branch Code, yymm = year/month catalogued, incr = incremental number, reset yearly -fbcit
+        ($nextnum, $scr) = C4::Barcodes::ValueBuilder::hbyymmincr::get_barcode(\%args);
+    }
+
+# default js body (if not filled by hbyymmincr)
+    $scr or $scr = <<END_OF_JS;
+    if (\$('#' + id).val() == '' || force) {
+        \$('#' + id).val('$nextnum');
+    }
+END_OF_JS
+
+        my $js  = <<END_OF_JS;
+    <script type="text/javascript">
+        //<![CDATA[
+
+        function Blur$function_name(index) {
+            //barcode validation might go here
+        }
+
+    function Focus$function_name(subfield_managed, id, force) {
+        return 0;
+    }
+
+    function Clic$function_name(id) {
+        $scr
+            return 0;
+    }
+    //]]>
+    </script>
+END_OF_JS
+        return ($function_name, $js);
+}
+
+=head1
+
+plugin: useless here
+
+=cut
+
+sub plugin {
+# my ($input) = @_;
+    return "";
+}
+
+1;
diff --git a/t/Barcodes_ValueBuilder.t b/t/Barcodes_ValueBuilder.t
new file mode 100644
index 0000000..c3d816e
--- /dev/null
+++ b/t/Barcodes_ValueBuilder.t
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use DBI;
+use Test::More tests => 15;
+use Test::MockModule;
+
+BEGIN {
+    use_ok('C4::Barcodes::ValueBuilder');
+}
+               
+
+my $module = new Test::MockModule('C4::Context');
+$module->mock('_new_dbh', sub {
+                             my $dbh = DBI->connect( 'DBI:Mock:', '', '' )
+                             || die "Cannot create handle: $DBI::errstr\n";
+                             return $dbh });
+
+# Mock data
+my $incrementaldata = [
+    ['max(abs(barcode))'],
+    ['33333074344563'],
+];
+
+
+my $dbh = C4::Context->dbh();
+
+my %args = (
+    year        => '2012',
+    mon         => '07',
+    day         => '30',
+    tag         => '952',
+    subfield    => 'p',
+    loctag      => '952',
+    locsubfield => 'a'
+);
+
+$dbh->{mock_add_resultset} = $incrementaldata;
+my ($nextnum, $scr, $history);
+
+($nextnum, $scr) = C4::Barcodes::ValueBuilder::incremental::get_barcode(\%args);
+is($nextnum, 33333074344564, 'incremental barcode');
+ok(length($scr) == 0, 'incremental javascript');
+
+# This should run exactly one query so we can test
+$history = $dbh->{mock_all_history};
+is(scalar(@{$history}), 1, 'Correct number of statements executed for incremental barcode') ;
+
+my $hbyymmincrdata = [
+    ['number'],
+    ['890'],
+];
+
+$dbh->{mock_add_resultset} = $hbyymmincrdata;
+$dbh->{mock_clear_history} = 1;
+($nextnum, $scr) = C4::Barcodes::ValueBuilder::hbyymmincr::get_barcode(\%args);
+is($nextnum, '12070891', 'hbyymmincr barcode');
+ok(length($scr) > 0, 'hbyymmincr javascript');
+
+# This should run exactly one query so we can test
+$history = $dbh->{mock_all_history};
+is(scalar(@{$history}), 1, 'Correct number of statements executed for hbyymmincr barcode') ;
+
+my $annualdata = [
+    ['max(cast( substring_index(barcode, \'-\',-1) as signed))'],
+    ['34'],
+];
+
+$dbh->{mock_add_resultset} = $annualdata;
+$dbh->{mock_clear_history} = 1;
+($nextnum, $scr) = C4::Barcodes::ValueBuilder::annual::get_barcode(\%args);
+is($nextnum, '2012-0035', 'annual barcode');
+ok(length($scr) == 0, 'annual javascript');
+
+# This should run exactly one query so we can test
+$history = $dbh->{mock_all_history};
+is(scalar(@{$history}), 1, 'Correct number of statements executed for hbyymmincr barcode') ;
+
-- 
1.7.2.5



More information about the Koha-patches mailing list