From 9091335d68dda39ce86e9cdb560edf1fa833598e Mon Sep 17 00:00:00 2001 From: Emmi Takkinen Date: Tue, 22 Mar 2022 13:17:19 +0200 Subject: [PATCH] Bug 30328: Add ability to generate barcode with branch specific prefix We should add more flexibility to generating barcodes by letting libraries define branch specific prefix for their barcodes. This patch adds new option "preyyyymmincr" in systempreference "autoBarcode" and new systempreference "BarcodePrefix" to define branch specific prefix Test plan: 1. Apply patch and update database 2. Set syspref "autoBarcode" as 3. Add some values to syspref "Barcodeprefix" e.g.: Default: DEF CPL: CPL FFL: FFL 4. Now change your library to CPL (if needed) and add an item 5. Click barcode input field => barcode should be CPL00001 6. Add another item and click barcode field => barcode should be CPL00002 7. Change your library to FFL and add an item => barcode should now be FFL00001 8. Change your library to e.g. FPL (or another as long as it doesn't have prefix value in "Barcodeprefix"), add an item and click barcode field => barcode should now be DEF00001 9. Try to add multiple items => barcodes incremental value should increase in order (no skipping values, no errors) Also prove t/db_dependent/Barcodes_ValueBuilder.t and t/Barcodes_preyyyymmincr.t Sponsored-by: Koha-Suomi Oy --- C4/Barcodes.pm | 12 +++-- C4/Barcodes/ValueBuilder.pm | 54 +++++++++++++++++++ C4/Barcodes/preyyyymmincr.pm | 30 +++++++++++ cataloguing/value_builder/barcode.pl | 4 ++ cataloguing/value_builder/barcode_manual.pl | 4 ++ .../data/mysql/atomicupdate/bug_30328.pl | 15 ++++++ installer/data/mysql/mandatory/sysprefs.sql | 3 +- .../admin/preferences/cataloguing.pref | 7 +++ t/Barcodes_preyyyymmincr.t | 10 ++++ t/db_dependent/Barcodes_ValueBuilder.t | 30 ++++++++++- 10 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 C4/Barcodes/preyyyymmincr.pm create mode 100755 installer/data/mysql/atomicupdate/bug_30328.pl create mode 100755 t/Barcodes_preyyyymmincr.t diff --git a/C4/Barcodes.pm b/C4/Barcodes.pm index 957d60f283..8342ae1c68 100644 --- a/C4/Barcodes.pm +++ b/C4/Barcodes.pm @@ -27,6 +27,7 @@ use C4::Barcodes::hbyymmincr; use C4::Barcodes::annual; use C4::Barcodes::incremental; use C4::Barcodes::EAN13; +use C4::Barcodes::preyyyymmincr; use vars qw($max $prefformat); @@ -154,11 +155,12 @@ sub default_self { } our $types = { - annual => sub {C4::Barcodes::annual->new_object(@_); }, - 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(@_); }, + annual => sub {C4::Barcodes::annual->new_object(@_); }, + 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(@_); }, + preyyyymmincr => sub {C4::Barcodes::preyyyymmincr->new_object(@_);}, }; sub new { diff --git a/C4/Barcodes/ValueBuilder.pm b/C4/Barcodes/ValueBuilder.pm index 76464ccd4b..abfdaf8bdb 100644 --- a/C4/Barcodes/ValueBuilder.pm +++ b/C4/Barcodes/ValueBuilder.pm @@ -89,6 +89,60 @@ sub get_barcode { return $nextnum; } +package C4::Barcodes::ValueBuilder::preyyyymmincr; +use C4::Context; +use YAML::XS; +my $DEBUG = 0; + +sub get_barcode { + my ($args) = @_; + my $nextnum; + my $barcode; + my $branchcode = $args->{branchcode}; + my $query; + my $sth; + + # Getting the barcodePrefixes + my $branchPrefixes = C4::Context->preference("BarcodePrefix"); + my $yaml = YAML::XS::Load( + Encode::encode( + 'UTF-8', + $branchPrefixes, + Encode::FB_CROAK + ) + ); + + my $prefix = $yaml->{$branchcode} || $yaml->{'Default'}; + + $query = "SELECT MAX(CAST(SUBSTRING(barcode,-4) AS signed)) from items where barcode REGEXP ?"; + $sth=C4::Context->dbh->prepare($query); + $sth->execute("^$prefix$args->{year}$args->{mon}"); + + while (my ($count)= $sth->fetchrow_array) { + $nextnum = $count if $count; + $nextnum = 0 if $nextnum && $nextnum == 9999; + } + + $nextnum++; + $nextnum = sprintf("%0*d", "5",$nextnum); + + $barcode = $prefix; + $barcode .= $args->{year}.$args->{mon}.$nextnum; + + my $scr = qq~ + let elt = \$("#"+id); + let branchcode = elt.parents('fieldset.rows:first') + .find('input[name="kohafield"][value="items.homebranch"]') + .siblings("select") + .val(); + if ( \$(elt).val() == '' ) { + \$(elt).val('$barcode'); + } + ~; + + return $barcode, $scr; +} + 1; diff --git a/C4/Barcodes/preyyyymmincr.pm b/C4/Barcodes/preyyyymmincr.pm new file mode 100644 index 0000000000..5498f9a24d --- /dev/null +++ b/C4/Barcodes/preyyyymmincr.pm @@ -0,0 +1,30 @@ +package C4::Barcodes::preyyyymmincr; + +# Copyright 2022 Koha Development team +# +# 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 3 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, see . + +use strict; +use warnings; + +use vars qw(@ISA); + +BEGIN { + @ISA = qw(C4::Barcodes); +} + +1; +__END__ \ No newline at end of file diff --git a/cataloguing/value_builder/barcode.pl b/cataloguing/value_builder/barcode.pl index 8fcd45beae..5f8756d476 100755 --- a/cataloguing/value_builder/barcode.pl +++ b/cataloguing/value_builder/barcode.pl @@ -37,6 +37,7 @@ my $builder = sub { # find today's date ($args{year}, $args{mon}, $args{day}) = split('-', output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 })); ($args{tag},$args{subfield}) = GetMarcFromKohaField( "items.barcode" ); + ($args{branchcode}) = C4::Context->userenv->{'branch'}; my $nextnum; my $scr; @@ -73,6 +74,9 @@ my $builder = sub { $nextnum++; } } + elsif ($autoBarcodeType eq 'preyyyymmincr') { # Generates a barcode where pre = branch specific prefix set on systempreference BarcodePrefix, yyyymm = year/month catalogued, incr = incremental number + ($nextnum, $scr) = C4::Barcodes::ValueBuilder::preyyyymmincr::get_barcode(\%args); + } else { warn "ERROR: unknown autoBarcode: $autoBarcodeType"; } diff --git a/cataloguing/value_builder/barcode_manual.pl b/cataloguing/value_builder/barcode_manual.pl index d2b7f7a414..d667fc2573 100755 --- a/cataloguing/value_builder/barcode_manual.pl +++ b/cataloguing/value_builder/barcode_manual.pl @@ -38,6 +38,7 @@ my $builder = sub { # find today's date ($args{year}, $args{mon}, $args{day}) = split('-', output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 })); ($args{tag},$args{subfield}) = GetMarcFromKohaField( "items.barcode" ); + ($args{branchcode}) = C4::Context->userenv->{'branch'}; my $nextnum; my $scr; @@ -55,6 +56,9 @@ my $builder = sub { 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); } + elsif ($autoBarcodeType eq 'preyyyymmincr') { # Generates a barcode where pre = branch specific prefix set on systempreference BarcodePrefix, yyyymm = year/month catalogued, incr = incremental number + ($nextnum, $scr) = C4::Barcodes::ValueBuilder::preyyyymmincr::get_barcode(\%args); + } # default js body (if not filled by hbyymmincr) $scr or $scr = < "30328", + description => "Add option to create barcode with branch specific prefix", + up => sub { + my ($args) = @_; + my ($dbh, $out) = @$args{qw(dbh out)}; + # Do you stuffs here + $dbh->do(q{ UPDATE IGNORE systempreferences SET options = 'incremental|annual|hbyymmincr|EAN13|preyyyymmincr|OFF' , explanation = 'Used to autogenerate a barcode: incremental will be of the form 1, 2, 3; annual of the form 2007-0001, 2007-0002; hbyymmincr of the form HB08010001 where HB=Home Branch; preyyyymmincr of the form PRE2021030001 where PRE = branch specific prefix set on systempreference BarcodePrefix' WHERE variable = 'autoBarcode'}); + $dbh->do(q{ INSERT IGNORE INTO systempreferences ( variable, value, options, explanation, type ) VALUES ('BarcodePrefix','','','Defines the barcode prefixes when the autoBarcode value is set as preyyyymmincr','Free')}); + # Print useful stuff here + say $out "Update is going well so far"; + }, +}; diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql index 9a4cdbf72f..3b4d72a105 100644 --- a/installer/data/mysql/mandatory/sysprefs.sql +++ b/installer/data/mysql/mandatory/sysprefs.sql @@ -70,7 +70,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('AuthorityMergeMode','loose','loose|strict','Authority merge mode','Choice'), ('AuthoritySeparator','--','10','Used to separate a list of authorities in a display. Usually --','free'), ('AuthSuccessLog','0',NULL,'If enabled, log successful authentications','YesNo'), -('autoBarcode','OFF','incremental|annual|hbyymmincr|EAN13|OFF','Used to autogenerate a barcode: incremental will be of the form 1, 2, 3; annual of the form 2007-0001, 2007-0002; hbyymmincr of the form HB08010001 where HB=Home Branch','Choice'), +('autoBarcode','OFF','incremental|annual|hbyymmincr|EAN13|preyyyymmincr|OFF','Used to autogenerate a barcode: incremental will be of the form 1, 2, 3; annual of the form 2007-0001, 2007-0002; hbyymmincr of the form HB08010001 where HB=Home Branch; preyyyymmincr of the form PRE2021030001 where PRE = branch specific prefix set on systempreference BarcodePrefix','Choice'), ('AutoCreateAuthorities','0',NULL,'Automatically create authorities that do not exist when cataloging records.','YesNo'), ('AutoCreditNumber', '', '', 'Automatically generate a number for account credits', 'Choice'), ('AutoEmailOpacUser','0',NULL,'Sends notification emails containing new account details to patrons - when account is created.','YesNo'), @@ -94,6 +94,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('BakerTaylorEnabled','0','','Enable or disable all Baker & Taylor features.','YesNo'), ('BakerTaylorPassword','','','Baker & Taylor Password for Content Cafe (external content)','Free'), ('BakerTaylorUsername','','','Baker & Taylor Username for Content Cafe (external content)','Free'), +('BarcodePrefix','','','Defines the barcode prefixes when the autoBarcode value is set as preyyyymmincr','Free'), ('BarcodeSeparators','\\s\\r\\n','','Splitting characters for barcodes','Free'), ('BasketConfirmations','1','always ask for confirmation.|do not ask for confirmation.','When closing or reopening a basket,','Choice'), ('BatchCheckouts','0','','Enable or disable batch checkouts','YesNo'), 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 86840eff5a..a6f7b5b780 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 @@ -123,6 +123,7 @@ Cataloging: annual: generated in the form -0001, -0002. hbyymmincr: generated in the form yymm0001. EAN13: incremental EAN-13 barcodes. + preyyyymmincr: generated in the from yyyymm0001. "OFF": not generated automatically. - - When a new item is added, @@ -165,6 +166,12 @@ Cataloging: - and record's last modifier name in MARC subfield - pref: MarcFieldForModifierName - ".
NOTE: Use a dollar sign between field and subfield like 123$a." + - + - "Define branch specific barcode prefix:" + - "This is a YAML config." + - pref: BarcodePrefix + type: textarea + class: code Display: - - 'Separate main entry and subdivisions with ' diff --git a/t/Barcodes_preyyyymmincr.t b/t/Barcodes_preyyyymmincr.t new file mode 100755 index 0000000000..c3ab5d8e9a --- /dev/null +++ b/t/Barcodes_preyyyymmincr.t @@ -0,0 +1,10 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 1; + +BEGIN { + use_ok('C4::Barcodes::preyyyymmincr'); +} \ No newline at end of file diff --git a/t/db_dependent/Barcodes_ValueBuilder.t b/t/db_dependent/Barcodes_ValueBuilder.t index 84fcce1983..1879e341f8 100755 --- a/t/db_dependent/Barcodes_ValueBuilder.t +++ b/t/db_dependent/Barcodes_ValueBuilder.t @@ -16,12 +16,14 @@ use Modern::Perl; -use Test::More tests => 9; +use Test::More tests => 12; use Test::MockModule; use t::lib::TestBuilder; use Koha::Database; +use t::lib::Mocks; + BEGIN { use_ok('C4::Barcodes::ValueBuilder', qw( get_barcode )); }; @@ -85,4 +87,30 @@ my $item_5 = $builder->build_sample_item( is($nextnum, '979', 'incremental barcode'); is($scr, undef, 'incremental javascript'); +$dbh->do(q|DELETE FROM items|); +my $library_1 = $builder->build_object( { class => 'Koha::Libraries' } ); + +my $prefix_yaml = 'Default: DEF +'.$library_1->branchcode.': TEST'; +t::lib::Mocks::mock_preference( 'BarcodePrefix', $prefix_yaml ); + +my $item_6 = $builder->build_sample_item( + { + barcode => 'TEST20120700001', + homebranch => $library_1->branchcode + } +); + +($args{branchcode}) = $library_1->branchcode; +($nextnum, $scr) = C4::Barcodes::ValueBuilder::preyyyymmincr::get_barcode(\%args); +is($nextnum, 'TEST20120700002', 'preyyyymmincr barcode test branch specific prefix'); +ok(length($scr) > 0, 'preyyyymmincr javascript'); + +$dbh->do(q|DELETE FROM items|); +my $library_2 = $builder->build_object( { class => 'Koha::Libraries' } ); + +($args{branchcode}) = $library_2->branchcode; +($nextnum, $scr) = C4::Barcodes::ValueBuilder::preyyyymmincr::get_barcode(\%args); +is($nextnum, 'DEF20120700001', 'preyyyymmincr barcode test default prefix'); + $schema->storage->txn_rollback; -- 2.25.1