From 8b502c488a3bce03c7260da9794b65ab2b286e9b Mon Sep 17 00:00:00 2001 From: Jared Camins-Esakov Date: Wed, 1 Aug 2012 11:54:55 -0400 Subject: [PATCH] Bug 8524: Add a non-automatic barcode plugin 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. Signed-off-by: Kyle M Hall --- 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{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 0ec6b62..ac10289 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; use Algorithm::CheckDigits; @@ -57,14 +58,14 @@ the 3 scripts are inserted after the 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; @@ -79,51 +80,13 @@ sub plugin_javascript { "); } 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) named ClicXXX + +returns : +* XXX +* a variable containing the 3 scripts. +the 3 scripts are inserted after the 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, + ""); + } + 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 + 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