#
# 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 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.
+# 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.
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
use strict;
use warnings;
use Carp;
-# use utf8;
+use Encode qw( decode is_utf8 );
use MARC::Record;
use MARC::File::USMARC;
use MARC::File::XML;
use C4::Koha;
use C4::Dates qw/format_date/;
use C4::Log; # logaction
+use C4::Budgets;
use C4::ClassSource;
use C4::Charset;
use C4::Linker;
use C4::OAI::Sets;
+use Koha::Cache;
+
use vars qw($VERSION @ISA @EXPORT);
BEGIN {
);
}
-eval {
- if (C4::Context->ismemcached) {
- require Memoize::Memcached;
- import Memoize::Memcached qw(memoize_memcached);
-
- memoize_memcached( 'GetMarcStructure',
- memcached => C4::Context->memcached);
- }
-};
-
=head1 NAME
C4::Biblio - cataloging management functions
my $frameworkcode = shift;
my $options = @_ ? shift : undef;
my $defer_marc_save = 0;
+ if (!$record) {
+ carp('AddBiblio called with undefined record');
+ return;
+ }
if ( defined $options and exists $options->{'defer_marc_save'} and $options->{'defer_marc_save'} ) {
$defer_marc_save = 1;
}
which fields are used to store embedded item, biblioitem,
and biblionumber data for indexing.
+Returns 1 on success 0 on failure
+
=cut
sub ModBiblio {
my ( $record, $biblionumber, $frameworkcode ) = @_;
- croak "No record" unless $record;
+ if (!$record) {
+ carp 'No record passed to ModBiblio';
+ return 0;
+ }
if ( C4::Context->preference("CataloguingLog") ) {
my $newrecord = GetMarcBiblio($biblionumber);
- logaction( "CATALOGUING", "MODIFY", $biblionumber, "BEFORE=>" . $newrecord->as_formatted );
+ logaction( "CATALOGUING", "MODIFY", $biblionumber, "biblio BEFORE=>" . $newrecord->as_formatted );
}
# Cleaning up invalid fields must be done early or SetUTF8Flag is liable to
my $error = &DelBiblio($biblionumber);
Exported function (core API) for deleting a biblio in koha.
-Deletes biblio record from Zebra and Koha tables (biblio,biblioitems,items)
-Also backs it up to deleted* tables
-Checks to make sure there are not issues on any of the items
+Deletes biblio record from Zebra and Koha tables (biblio & biblioitems)
+Also backs it up to deleted* tables.
+Checks to make sure that the biblio has no items attached.
return:
C<$error> : undef unless an error occurs
# We delete any existing holds
require C4::Reserves;
- my ($count, $reserves) = C4::Reserves::GetReservesFromBiblionumber($biblionumber);
+ my $reserves = C4::Reserves::GetReservesFromBiblionumber({ biblionumber => $biblionumber });
foreach my $res ( @$reserves ) {
C4::Reserves::CancelReserve({ reserve_id => $res->{'reserve_id'} });
}
# from being generated by _koha_delete_biblioitems
$error = _koha_delete_biblio( $dbh, $biblionumber );
- logaction( "CATALOGUING", "DELETE", $biblionumber, "" ) if C4::Context->preference("CataloguingLog");
+ logaction( "CATALOGUING", "DELETE", $biblionumber, "biblio" ) if C4::Context->preference("CataloguingLog");
return;
}
Automatically links headings in a bib record to authorities.
+Returns the number of headings changed
+
=cut
sub BiblioAutoLink {
my $record = shift;
my $frameworkcode = shift;
+ if (!$record) {
+ carp('Undefined record passed to BiblioAutoLink');
+ return 0;
+ }
my ( $num_headings_changed, %results );
my $linker_module =
unless ( can_load( modules => { $linker_module => undef } ) ) {
$linker_module = 'C4::Linker::Default';
unless ( can_load( modules => { $linker_module => undef } ) ) {
- return 0, 0;
+ return 0;
}
}
my $frameworkcode = shift;
my $allowrelink = shift;
my %results;
+ if (!$bib) {
+ carp 'LinkBibHeadingsToAuthorities called on undefined bib record';
+ return ( 0, {});
+ }
require C4::Heading;
require C4::AuthoritiesMarc;
$heading->auth_type() );
$field->add_subfields( '9', $authid );
$num_headings_changed++;
+ $linker->update_cache($heading, $authid);
$results{'added'}->{ $heading->display_form() }++;
}
}
}
Check whether the specified heading-auth link is valid without reference
-to Zebra/Solr. Ideally this code would be in C4::Heading, but that won't be
+to Zebra. Ideally this code would be in C4::Heading, but that won't be
possible until we have de-cycled C4::AuthoritiesMarc, so this is the
safest place.
sub GetRecordValue {
my ( $field, $record, $frameworkcode ) = @_;
+
+ if (!$record) {
+ carp 'GetRecordValue called with undefined record';
+ return;
+ }
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare('SELECT fieldcode, subfieldcode FROM fieldmapping WHERE frameworkcode = ? AND field = ?');
sub GetBiblioItemInfosOf {
my @biblioitemnumbers = @_;
- my $query = '
+ my $biblioitemnumber_values = @biblioitemnumbers ? join( ',', @biblioitemnumbers ) : "''";
+
+ my $query = "
SELECT biblioitemnumber,
publicationyear,
itemtype
FROM biblioitems
- WHERE biblioitemnumber IN (' . join( ',', @biblioitemnumbers ) . ')
- ';
+ WHERE biblioitemnumber IN ($biblioitemnumber_values)
+ ";
return get_infos_of( $query, 'biblioitemnumber' );
}
=cut
-# cache for results of GetMarcStructure -- needed
-# for batch jobs
-our $marc_structure_cache;
-
sub GetMarcStructure {
my ( $forlibrarian, $frameworkcode ) = @_;
my $dbh = C4::Context->dbh;
$frameworkcode = "" unless $frameworkcode;
- if ( defined $marc_structure_cache and exists $marc_structure_cache->{$forlibrarian}->{$frameworkcode} ) {
- return $marc_structure_cache->{$forlibrarian}->{$frameworkcode};
- }
+ $forlibrarian = $forlibrarian ? 1 : 0;
+ my $cache = Koha::Cache->get_instance();
+ my $cache_key = "MarcStructure-$forlibrarian-$frameworkcode";
+ my $cached = $cache->get_from_cache($cache_key);
+ return $cached if $cached;
- # my $sth = $dbh->prepare(
- # "SELECT COUNT(*) FROM marc_tag_structure WHERE frameworkcode=?");
- # $sth->execute($frameworkcode);
- # my ($total) = $sth->fetchrow;
- # $frameworkcode = "" unless ( $total > 0 );
my $sth = $dbh->prepare(
"SELECT tagfield,liblibrarian,libopac,mandatory,repeatable
FROM marc_tag_structure
$res->{$tag}->{$subfield}->{maxlength} = $maxlength;
}
- $marc_structure_cache->{$forlibrarian}->{$frameworkcode} = $res;
-
+ $cache->set_in_cache($cache_key, $res);
return $res;
}
sub GetMarcBiblio {
my $biblionumber = shift;
my $embeditems = shift || 0;
+
+ if (not defined $biblionumber) {
+ carp 'GetMarcBiblio called with undefined biblionumber';
+ return;
+ }
+
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT marcxml FROM biblioitems WHERE biblionumber=? ");
$sth->execute($biblionumber);
# get the coin format
if ( ! $record ) {
- return;
+ carp 'GetCOinSBiblio called with undefined record';
+ return;
}
my $pos7 = substr $record->leader(), 7, 1;
my $pos6 = substr $record->leader(), 6, 1;
=head2 GetMarcPrice
return the prices in accordance with the Marc format.
+
+returns 0 if no price found
+returns undef if called without a marc record or with
+an unrecognized marc format
+
=cut
sub GetMarcPrice {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcPrice called on undefined record';
+ return;
+ }
+
my @listtags;
my $subfield;
- if ( $marcflavour eq "MARC21" ) {
+ if ( $marcflavour eq "MARC21" || $marcflavour eq "NORMARC" ) {
@listtags = ('345', '020');
$subfield="c";
} elsif ( $marcflavour eq "UNIMARC" ) {
sub MungeMarcPrice {
my ( $price ) = @_;
-
return unless ( $price =~ m/\d/ ); ## No digits means no price.
-
- ## Look for the currency symbol of the active currency, if it's there,
- ## start the price string right after the symbol. This allows us to prefer
- ## this native currency price over other currency prices, if possible.
- my $active_currency = C4::Context->dbh->selectrow_hashref( 'SELECT * FROM currency WHERE active = 1', {} );
- my $symbol = quotemeta( $active_currency->{'symbol'} );
- if ( $price =~ m/$symbol/ ) {
- my @parts = split(/$symbol/, $price );
- $price = $parts[1];
- }
-
- ## Grab the first number in the string ( can use commas or periods for thousands separator and/or decimal separator )
- ( $price ) = $price =~ m/([\d\,\.]+[[\,\.]\d\d]?)/;
-
- ## Split price into array on periods and commas
- my @parts = split(/[\,\.]/, $price);
-
- ## If the last grouping of digits is more than 2 characters, assume there is no decimal value and put it back.
- my $decimal = pop( @parts );
- if ( length( $decimal ) > 2 ) {
- push( @parts, $decimal );
- $decimal = '';
- }
-
- $price = join('', @parts );
-
- if ( $decimal ) {
- $price .= ".$decimal";
+ # Look for the currency symbol and the normalized code of the active currency, if it's there,
+ my $active_currency = C4::Budgets->GetCurrency();
+ my $symbol = $active_currency->{'symbol'};
+ my $isocode = $active_currency->{'isocode'};
+ $isocode = $active_currency->{'currency'} unless defined $isocode;
+ my $localprice;
+ if ( $symbol ) {
+ my @matches =($price=~ /
+ \s?
+ ( # start of capturing parenthesis
+ (?:
+ (?:[\p{Sc}\p{L}\/.]){1,4} # any character from Currency signs or Letter Unicode categories or slash or dot within 1 to 4 occurrences : call this whole block 'symbol block'
+ |(?:\d+[\p{P}\s]?){1,4} # or else at least one digit followed or not by a punctuation sign or whitespace, all theese within 1 to 4 occurrences : call this whole block 'digits block'
+ )
+ \s?\p{Sc}?\s? # followed or not by a whitespace. \p{Sc}?\s? are for cases like '25$ USD'
+ (?:
+ (?:[\p{Sc}\p{L}\/.]){1,4} # followed by same block as symbol block
+ |(?:\d+[\p{P}\s]?){1,4} # or by same block as digits block
+ )
+ \s?\p{L}{0,4}\s? # followed or not by a whitespace. \p{L}{0,4}\s? are for cases like '$9.50 USD'
+ ) # end of capturing parenthesis
+ (?:\p{P}|\z) # followed by a punctuation sign or by the end of the string
+ /gx);
+
+ if ( @matches ) {
+ foreach ( @matches ) {
+ $localprice = $_ and last if index($_, $isocode)>=0;
+ }
+ if ( !$localprice ) {
+ foreach ( @matches ) {
+ $localprice = $_ and last if $_=~ /(^|[^\p{Sc}\p{L}\/])\Q$symbol\E([^\p{Sc}\p{L}\/]+\z|\z)/;
+ }
+ }
+ }
}
-
+ if ( $localprice ) {
+ $price = $localprice;
+ } else {
+ ## Grab the first number in the string ( can use commas or periods for thousands separator and/or decimal separator )
+ ( $price ) = $price =~ m/([\d\,\.]+[[\,\.]\d\d]?)/;
+ }
+ # eliminate symbol/isocode, space and any final dot from the string
+ $price =~ s/[\p{Sc}\p{L}\/ ]|\.$//g;
+ # remove comma,dot when used as separators from hundreds
+ $price =~s/[\,\.](\d{3})/$1/g;
+ # convert comma to dot to ensure correct display of decimals if existing
+ $price =~s/,/./;
return $price;
}
return the quantity of a book. Used in acquisition only, when importing a file an iso2709 from a bookseller
Warning : this is not really in the marc standard. In Unimarc, Electre (the most widely used bookseller) use the 969$a
+returns 0 if no quantity found
+returns undef if called without a marc record or with
+an unrecognized marc format
+
=cut
sub GetMarcQuantity {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcQuantity called on undefined record';
+ return;
+ }
+
my @listtags;
my $subfield;
sub GetMarcControlnumber {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcControlnumber called on undefined record';
+ return;
+ }
my $controlnumber = "";
# Control number or Record identifier are the same field in MARC21, UNIMARC and NORMARC
# Keep $marcflavour for possible later use
sub GetMarcISBN {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcISBN called on undefined record';
+ return;
+ }
my $scope;
if ( $marcflavour eq "UNIMARC" ) {
$scope = '010';
} else { # assume marc21 if not unimarc
$scope = '020';
}
+
my @marcisbns;
- my $isbn = "";
- my $tag = "";
- my $marcisbn;
foreach my $field ( $record->field($scope) ) {
- my $value = $field->as_string();
+ my $isbn = $field->subfield( 'a' );
if ( $isbn ne "" ) {
- $marcisbn = { marcisbn => $isbn, };
- push @marcisbns, $marcisbn;
- $isbn = $value;
- }
- if ( $isbn ne $value ) {
- $isbn = $isbn . " " . $value;
+ push @marcisbns, $isbn;
}
}
- if ($isbn) {
- $marcisbn = { marcisbn => $isbn };
- push @marcisbns, $marcisbn; #load last tag into array
- }
return \@marcisbns;
} # end GetMarcISBN
sub GetMarcISSN {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcISSN called on undefined record';
+ return;
+ }
my $scope;
if ( $marcflavour eq "UNIMARC" ) {
$scope = '011';
}
my @marcissns;
foreach my $field ( $record->field($scope) ) {
- push @marcissns, $field->subfield( 'a' );
+ push @marcissns, $field->subfield( 'a' )
+ if ( $field->subfield( 'a' ) ne "" );
}
return \@marcissns;
} # end GetMarcISSN
sub GetMarcNotes {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcNotes called on undefined record';
+ return;
+ }
my $scope;
if ( $marcflavour eq "UNIMARC" ) {
$scope = '3..';
sub GetMarcSubjects {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcSubjects called on undefined record';
+ return;
+ }
my ( $mintag, $maxtag, $fields_filter );
if ( $marcflavour eq "UNIMARC" ) {
$mintag = "600";
my @marcsubjects;
my $subject_limit = C4::Context->preference("TraceCompleteSubfields") ? 'su,complete-subfield' : 'su';
- my $authoritysep = C4::Context->preference('authoritysep');
+ my $AuthoritySeparator = C4::Context->preference('AuthoritySeparator');
foreach my $field ( $record->field($fields_filter) ) {
next unless ($field->tag() >= $mintag && $field->tag() <= $maxtag);
code => $code,
value => $value,
link_loop => \@this_link_loop,
- separator => (scalar @subfields_loop) ? $authoritysep : ''
+ separator => (scalar @subfields_loop) ? $AuthoritySeparator : ''
};
}
}
sub GetMarcAuthors {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcAuthors called on undefined record';
+ return;
+ }
my ( $mintag, $maxtag, $fields_filter );
# tagslib useful for UNIMARC author reponsabilities
}
my @marcauthors;
- my $authoritysep = C4::Context->preference('authoritysep');
+ my $AuthoritySeparator = C4::Context->preference('AuthoritySeparator');
foreach my $field ( $record->field($fields_filter) ) {
next unless $field->tag() >= $mintag && $field->tag() <= $maxtag;
}
# other subfields
+ my $unimarc3;
for my $authors_subfield (@subfields) {
next if ( $authors_subfield->[0] eq '9' );
+ # unimarc3 contains the $3 of the author for UNIMARC.
+ # For french academic libraries, it's the "ppn", and it's required for idref webservice
+ $unimarc3 = $authors_subfield->[1] if $marcflavour eq 'UNIMARC' and $authors_subfield->[0] =~ /3/;
+
# don't load unimarc subfields 3, 5
next if ( $marcflavour eq 'UNIMARC' and ( $authors_subfield->[0] =~ /3|5/ ) );
code => $code,
value => $value,
link_loop => \@this_link_loop,
- separator => (scalar @subfields_loop) ? $authoritysep : ''
+ separator => (scalar @subfields_loop) ? $AuthoritySeparator : ''
};
}
}
push @marcauthors, {
MARCAUTHOR_SUBFIELDS_LOOP => \@subfields_loop,
authoritylink => $subfield9,
+ unimarc3 => $unimarc3
};
}
return \@marcauthors;
sub GetMarcUrls {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcUrls called on undefined record';
+ return;
+ }
my @marcurls;
for my $field ( $record->field('856') ) {
sub GetMarcSeries {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcSeries called on undefined record';
+ return;
+ }
+
my ( $mintag, $maxtag, $fields_filter );
if ( $marcflavour eq "UNIMARC" ) {
$mintag = "225";
}
my @marcseries;
- my $authoritysep = C4::Context->preference('authoritysep');
+ my $AuthoritySeparator = C4::Context->preference('AuthoritySeparator');
foreach my $field ( $record->field($fields_filter) ) {
next unless $field->tag() >= $mintag && $field->tag() <= $maxtag;
code => $code,
value => $value,
link_loop => \@link_loop,
- separator => (scalar @subfields_loop) ? $authoritysep : '',
+ separator => (scalar @subfields_loop) ? $AuthoritySeparator : '',
volumenum => $volume_number,
}
}
sub GetMarcHosts {
my ( $record, $marcflavour ) = @_;
+ if (!$record) {
+ carp 'GetMarcHosts called on undefined record';
+ return;
+ }
+
my ( $tag,$title_subf,$bibnumber_subf,$itemnumber_subf);
$marcflavour ||="MARC21";
if ( $marcflavour eq "MARC21" || $marcflavour eq "NORMARC" ) {
my $record = MARC::Record->new();
SetMarcUnicodeFlag( $record, C4::Context->preference("marcflavour") );
my $db_to_marc = C4::Context->marcfromkohafield;
+ my $tag_hr = {};
while ( my ($name, $value) = each %$hash ) {
next unless my $dtm = $db_to_marc->{''}->{$name};
next unless ( scalar( @$dtm ) );
my ($tag, $letter) = @$dtm;
+ $tag .= '';
foreach my $value ( split(/\s?\|\s?/, $value, -1) ) {
- if ( my $field = $record->field($tag) ) {
- $field->add_subfields( $letter => $value );
- }
- else {
- $record->insert_fields_ordered( MARC::Field->new(
- $tag, " ", " ", $letter => $value ) );
- }
+ next if $value eq '';
+ $tag_hr->{$tag} //= [];
+ push @{$tag_hr->{$tag}}, [($letter, $value)];
}
-
+ }
+ foreach my $tag (sort keys %$tag_hr) {
+ my @sfl = @{$tag_hr->{$tag}};
+ @sfl = sort { $a->[0] cmp $b->[0]; } @sfl;
+ @sfl = map { @{$_}; } @sfl;
+ $record->insert_fields_ordered(
+ MARC::Field->new($tag, " ", " ", @sfl)
+ );
}
return $record;
}
@$values[$i] =~ s/"/"/g;
@$values[$i] =~ s/'/'/g;
- # if ( !utf8::is_utf8( @$values[$i] ) ) {
- # utf8::decode( @$values[$i] );
- # }
if ( ( @$tags[$i] ne $prevtag ) ) {
$j++ unless ( @$tags[$i] eq "" );
my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) };
foreach my $param_name ( keys %$cgi_params ) {
if ( $param_name =~ /^tag_/ ) {
my $param_value = $cgi_params->{$param_name};
- if ( utf8::decode($param_value) ) {
- $cgi_params->{$param_name} = $param_value;
+ unless ( Encode::is_utf8( $param_value ) ) {
+ $cgi_params->{$param_name} = Encode::decode('UTF-8', $param_value );
}
-
- # FIXME - need to do something if string is not valid UTF-8
}
}
Extract data from a MARC bib record into a hashref representing
Koha biblio, biblioitems, and items fields.
+If passed an undefined record will log the error and return an empty
+hash_ref
+
=cut
sub TransformMarcToKoha {
my ( $dbh, $record, $frameworkcode, $limit_table ) = @_;
- my $result;
+ my $result = {};
+ if (!defined $record) {
+ carp('TransformMarcToKoha called with undefined record');
+ return $result;
+ }
$limit_table = $limit_table || 0;
$frameworkcode = '' unless defined $frameworkcode;
sub EmbedItemsInMarcBiblio {
my ($marc, $biblionumber, $itemnumbers) = @_;
- croak "No MARC record" unless $marc;
+ if ( !$marc ) {
+ carp 'EmbedItemsInMarcBiblio: No MARC record passed';
+ return;
+ }
$itemnumbers = [] unless defined $itemnumbers;
# pass the MARC::Record to this function, and it will create the records in
# the marc field
my ( $record, $biblionumber, $frameworkcode ) = @_;
+ if ( !$record ) {
+ carp 'ModBiblioMarc passed an undefined record';
+ return;
+ }
# Clone record as it gets modified
$record = $record->clone();
=head2 CountBiblioInOrders
-=over 4
-$count = &CountBiblioInOrders( $biblionumber);
-
-=back
+ $count = &CountBiblioInOrders( $biblionumber);
This function return count of biblios in orders with $biblionumber
=head2 GetSubscriptionsId
-=over 4
-$subscriptions = &GetSubscriptionsId($biblionumber);
-
-=back
+ $subscriptions = &GetSubscriptionsId($biblionumber);
This function return an array of subscriptionid with $biblionumber
=head2 GetHolds
-=over 4
-$holds = &GetHolds($biblionumber);
-
-=back
+ $holds = &GetHolds($biblionumber);
This function return the count of holds with $biblionumber
my ($biblionumber, $increase, $value) = @_;
my $totalissues;
+ my $record = GetMarcBiblio($biblionumber);
+ unless ($record) {
+ carp "UpdateTotalIssues could not get biblio record";
+ return;
+ }
my $data = GetBiblioData($biblionumber);
+ unless ($data) {
+ carp "UpdateTotalIssues could not get datas of biblio";
+ return;
+ }
+ my ($totalissuestag, $totalissuessubfield) = GetMarcFromKohaField('biblioitems.totalissues', $data->{'frameworkcode'});
+ unless ($totalissuestag) {
+ return 1; # There is nothing to do
+ }
if (defined $value) {
$totalissues = $value;
} else {
$totalissues = $data->{'totalissues'} + $increase;
}
- my ($totalissuestag, $totalissuessubfield) = GetMarcFromKohaField('biblioitems.totalissues', $data->{'frameworkcode'});
-
- my $record = GetMarcBiblio($biblionumber);
my $field = $record->field($totalissuestag);
if (defined $field) {
$record->insert_grouped_field($field);
}
- ModBiblio($record, $biblionumber, $data->{'frameworkcode'});
- return;
+ return ModBiblio($record, $biblionumber, $data->{'frameworkcode'});
}
=head2 RemoveAllNsb
sub RemoveAllNsb {
my $record = shift;
+ if (!$record) {
+ carp 'RemoveAllNsb called with undefined record';
+ return;
+ }
SetUTF8Flag($record);