Bug 15572: Follow-up to fix error on authority creation
[koha.git] / C4 / Biblio.pm
index 60e0069..ef263e4 100644 (file)
@@ -6,24 +6,24 @@ package C4::Biblio;
 #
 # 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;
@@ -31,13 +31,16 @@ use POSIX qw(strftime);
 use Module::Load::Conditional qw(can_load);
 
 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 Koha::Authority::Types;
+
 use vars qw($VERSION @ISA @EXPORT);
 
 BEGIN {
@@ -54,13 +57,14 @@ BEGIN {
 
     # to get something
     push @EXPORT, qw(
-      &GetBiblio
-      &GetBiblioData
-      &GetBiblioItemData
-      &GetBiblioItemInfosOf
-      &GetBiblioItemByBiblioNumber
-      &GetBiblioFromItemNumber
-      &GetBiblionumberFromItemnumber
+      GetBiblio
+      GetBiblioData
+      GetMarcBiblio
+      GetBiblioItemData
+      GetBiblioItemInfosOf
+      GetBiblioItemByBiblioNumber
+      GetBiblioFromItemNumber
+      GetBiblionumberFromItemnumber
 
       &GetRecordValue
       &GetFieldMapping
@@ -74,7 +78,6 @@ BEGIN {
       &GetMarcISBN
       &GetMarcISSN
       &GetMarcSubjects
-      &GetMarcBiblio
       &GetMarcAuthors
       &GetMarcSeries
       &GetMarcHosts
@@ -123,8 +126,8 @@ BEGIN {
 
     # Internal functions
     # those functions are exported but should not be used
-    # they are usefull is few circumstances, so are exported.
-    # but don't use them unless you're a core developer ;-)
+    # they are useful in a few circumstances, so they are exported,
+    # but don't use them unless you are a core developer ;-)
     push @EXPORT, qw(
       &ModBiblioMarc
     );
@@ -138,16 +141,6 @@ 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
@@ -410,9 +403,9 @@ sub ModBiblioframework {
   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
 
@@ -580,8 +573,7 @@ sub LinkBibHeadingsToAuthorities {
                     $results{'linked'}->{ $heading->display_form() }++;
                 }
                 else {
-                    my $authtypedata =
-                      C4::AuthoritiesMarc::GetAuthType( $heading->auth_type() );
+                    my $authority_type = Koha::Authority::Types->find( $heading->auth_type() );
                     my $marcrecordauth = MARC::Record->new();
                     if ( C4::Context->preference('marcflavour') eq 'MARC21' ) {
                         $marcrecordauth->leader('     nz  a22     o  4500');
@@ -590,7 +582,7 @@ sub LinkBibHeadingsToAuthorities {
                     $field->delete_subfield( code => '9' )
                       if defined $current_link;
                     my $authfield =
-                      MARC::Field->new( $authtypedata->{auth_tag_to_report},
+                      MARC::Field->new( $authority_type->auth_tag_to_report,
                         '', '', "a" => "" . $field->subfield('a') );
                     map {
                         $authfield->add_subfields( $_->[0] => $_->[1] )
@@ -634,6 +626,7 @@ sub LinkBibHeadingsToAuthorities {
                         $heading->auth_type() );
                     $field->add_subfields( '9', $authid );
                     $num_headings_changed++;
+                    $linker->update_cache($heading, $authid);
                     $results{'added'}->{ $heading->display_form() }++;
                 }
             }
@@ -663,7 +656,7 @@ sub LinkBibHeadingsToAuthorities {
     }
 
 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.
 
@@ -1073,13 +1066,15 @@ sub GetBiblio {
 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' );
 }
 
@@ -1095,24 +1090,17 @@ $frameworkcode : the framework code to read
 
 =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 
@@ -1174,8 +1162,7 @@ sub GetMarcStructure {
         $res->{$tag}->{$subfield}->{maxlength}        = $maxlength;
     }
 
-    $marc_structure_cache->{$forlibrarian}->{$frameworkcode} = $res;
-
+    $cache->set_in_cache($cache_key, $res);
     return $res;
 }
 
@@ -1261,36 +1248,66 @@ sub GetMarcSubfieldStructureFromKohaField {
 
 =head2 GetMarcBiblio
 
-  my $record = GetMarcBiblio($biblionumber, [$embeditems]);
+  my $record = GetMarcBiblio($biblionumber, [$embeditems], [$opac]);
+
+Returns MARC::Record representing a biblio record, or C<undef> if the
+biblionumber doesn't exist.
+
+=over 4
+
+=item C<$biblionumber>
+
+the biblionumber
 
-Returns MARC::Record representing bib identified by
-C<$biblionumber>.  If no bib exists, returns undef.
-C<$embeditems>.  If set to true, items data are included.
-The MARC record contains biblio data, and items data if $embeditems is set to true.
+=item C<$embeditems>
+
+set to true to include item information.
+
+=item C<$opac>
+
+set to true to make the result suited for OPAC view. This causes things like
+OpacHiddenItems to be applied.
+
+=back
 
 =cut
 
 sub GetMarcBiblio {
     my $biblionumber = shift;
     my $embeditems   = shift || 0;
+    my $opac         = 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=? ");
+    my $sth          = $dbh->prepare("SELECT biblioitemnumber, marcxml FROM biblioitems WHERE biblionumber=? ");
     $sth->execute($biblionumber);
     my $row     = $sth->fetchrow_hashref;
+    my $biblioitemnumber = $row->{'biblioitemnumber'};
     my $marcxml = StripNonXmlChars( $row->{'marcxml'} );
+    my $frameworkcode = GetFrameworkCode($biblionumber);
     MARC::File::XML->default_record_format( C4::Context->preference('marcflavour') );
     my $record = MARC::Record->new();
 
     if ($marcxml) {
-        $record = eval { MARC::Record::new_from_xml( $marcxml, "utf8", C4::Context->preference('marcflavour') ) };
+        $record = eval {
+            MARC::Record::new_from_xml( $marcxml, "utf8",
+                C4::Context->preference('marcflavour') );
+        };
         if ($@) { warn " problem with :$biblionumber : $@ \n$marcxml"; }
         return unless $record;
 
-        C4::Biblio::_koha_marc_update_bib_ids($record, '', $biblionumber, $biblionumber);
-       C4::Biblio::EmbedItemsInMarcBiblio($record, $biblionumber) if ($embeditems);
+        C4::Biblio::_koha_marc_update_bib_ids( $record, $frameworkcode, $biblionumber,
+            $biblioitemnumber );
+        C4::Biblio::EmbedItemsInMarcBiblio( $record, $biblionumber, undef, $opac )
+          if ($embeditems);
 
         return $record;
-    } else {
+    }
+    else {
         return;
     }
 }
@@ -1485,7 +1502,7 @@ sub GetMarcPrice {
     my @listtags;
     my $subfield;
     
-    if ( $marcflavour eq "MARC21" ) {
+    if ( $marcflavour eq "MARC21" || $marcflavour eq "NORMARC" ) {
         @listtags = ('345', '020');
         $subfield="c";
     } elsif ( $marcflavour eq "UNIMARC" ) {
@@ -1525,7 +1542,7 @@ sub MungeMarcPrice {
             (                          # 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'
+            |(?:\d+[\p{P}\s]?){1,4}    # or else at least one digit followed or not by a punctuation sign or whitespace,                                             all these 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'
             (?:
@@ -1641,7 +1658,7 @@ sub GetAuthorisedValueDesc {
 
         #---- itemtypes
         if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "itemtypes" ) {
-            return getitemtypeinfo($value)->{description};
+            return getitemtypeinfo($value)->{translated_description};
         }
 
         #---- "true" authorized value
@@ -1708,7 +1725,7 @@ sub GetMarcISBN {
 
     my @marcisbns;
     foreach my $field ( $record->field($scope) ) {
-        my $isbn = $field->as_string();
+        my $isbn = $field->subfield( 'a' );
         if ( $isbn ne "" ) {
             push @marcisbns, $isbn;
         }
@@ -1742,7 +1759,8 @@ sub GetMarcISSN {
     }
     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
@@ -1933,9 +1951,14 @@ sub GetMarcAuthors {
         }
 
         # 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/ ) );
 
@@ -1971,6 +1994,7 @@ sub GetMarcAuthors {
         push @marcauthors, {
             MARCAUTHOR_SUBFIELDS_LOOP => \@subfields_loop,
             authoritylink => $subfield9,
+            unimarc3 => $unimarc3
         };
     }
     return \@marcauthors;
@@ -2190,20 +2214,25 @@ sub TransformKohaToMarc {
     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;
 }
@@ -2309,6 +2338,8 @@ $auth_type contains :
 
 sub TransformHtmlToXml {
     my ( $tags, $subfields, $values, $indicator, $ind_tag, $auth_type ) = @_;
+    # NOTE: The parameter $ind_tag is NOT USED -- BZ 11247
+
     my $xml = MARC::File::XML::header('UTF-8');
     $xml .= "<record>\n";
     $auth_type = C4::Context->preference('marcflavour') unless $auth_type;
@@ -2342,9 +2373,6 @@ sub TransformHtmlToXml {
         @$values[$i] =~ s/"/&quot;/g;
         @$values[$i] =~ s/'/&apos;/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 ) };
@@ -2468,7 +2496,7 @@ sub _default_ind_to_space {
 =cut
 
 sub TransformHtmlToMarc {
-    my $cgi    = shift;
+    my ($cgi, $isbiblio) = @_;
 
     my @params = $cgi->param();
 
@@ -2479,26 +2507,25 @@ sub TransformHtmlToMarc {
     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
         }
     }
 
     # creating a new record
     my $record = MARC::Record->new();
-    my $i      = 0;
     my @fields;
+    my ($biblionumbertagfield, $biblionumbertagsubfield) = (-1, -1);
+    ($biblionumbertagfield, $biblionumbertagsubfield) =
+        &GetMarcFromKohaField( "biblio.biblionumber", '' ) if $isbiblio;
 #FIXME This code assumes that the CGI params will be in the same order as the fields in the template; this is no absolute guarantee!
-    while ( $params[$i] ) {    # browse all CGI params
+    for (my $i = 0; $params[$i]; $i++ ) {    # browse all CGI params
         my $param    = $params[$i];
         my $newfield = 0;
 
         # if we are on biblionumber, store it in the MARC::Record (it may not be in the edited fields)
         if ( $param eq 'biblionumber' ) {
-            my ( $biblionumbertagfield, $biblionumbertagsubfield ) = &GetMarcFromKohaField( "biblio.biblionumber", '' );
             if ( $biblionumbertagfield < 10 ) {
                 $newfield = MARC::Field->new( $biblionumbertagfield, $cgi->param($param), );
             } else {
@@ -2515,7 +2542,10 @@ sub TransformHtmlToMarc {
 
             if ( $tag < 10 ) {                              # no code for theses fields
                                                             # in MARC editor, 000 contains the leader.
-                if ( $tag eq '000' ) {
+                if ( $tag == $biblionumbertagfield ) {
+                    # We do nothing and let $i be incremented
+                }
+                elsif ( $tag eq '000' ) {
                     # Force a fake leader even if not provided to avoid crashing
                     # during decoding MARC record containing UTF-8 characters
                     $record->leader(
@@ -2534,6 +2564,9 @@ sub TransformHtmlToMarc {
                 # browse subfields for this tag (reason for _code_ match)
                 while(defined $params[$j] && $params[$j] =~ /_code_/) {
                     last unless defined $params[$j+1];
+                    $j += 2 and next
+                        if $tag == $biblionumbertagfield and
+                           $cgi->param($params[$j]) eq $biblionumbertagsubfield;
                     #if next param ne subfield, then it was probably empty
                     #try next param by incrementing j
                     if($params[$j+1]!~/_subfield_/) {$j++; next; }
@@ -2551,7 +2584,6 @@ sub TransformHtmlToMarc {
             }
             push @fields, $newfield if ($newfield);
         }
-        $i++;
     }
 
     $record->append_fields(@fields);
@@ -2882,17 +2914,19 @@ sub ModZebra {
 
 =head2 EmbedItemsInMarcBiblio
 
-    EmbedItemsInMarcBiblio($marc, $biblionumber, $itemnumbers);
+    EmbedItemsInMarcBiblio($marc, $biblionumber, $itemnumbers, $opac);
 
 Given a MARC::Record object containing a bib record,
 modify it to include the items attached to it as 9XX
 per the bib's MARC framework.
-if $itemnumbers is defined, only specified itemnumbers are embedded
+if $itemnumbers is defined, only specified itemnumbers are embedded.
+
+If $opac is true, then opac-relevant suppressions are included.
 
 =cut
 
 sub EmbedItemsInMarcBiblio {
-    my ($marc, $biblionumber, $itemnumbers) = @_;
+    my ($marc, $biblionumber, $itemnumbers, $opac) = @_;
     if ( !$marc ) {
         carp 'EmbedItemsInMarcBiblio: No MARC record passed';
         return;
@@ -2909,10 +2943,24 @@ sub EmbedItemsInMarcBiblio {
     $sth->execute($biblionumber);
     my @item_fields;
     my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
-    while (my ($itemnumber) = $sth->fetchrow_array) {
+    my @items;
+    my $opachiddenitems = $opac
+      && ( C4::Context->preference('OpacHiddenItems') !~ /^\s*$/ );
+    require C4::Items;
+    while ( my ($itemnumber) = $sth->fetchrow_array ) {
         next if @$itemnumbers and not grep { $_ == $itemnumber } @$itemnumbers;
-        require C4::Items;
-        my $item_marc = C4::Items::GetMarcItem($biblionumber, $itemnumber);
+        my $i = $opachiddenitems ? C4::Items::GetItem($itemnumber) : undef;
+        push @items, { itemnumber => $itemnumber, item => $i };
+    }
+    my @hiddenitems =
+      $opachiddenitems
+      ? C4::Items::GetHiddenItemnumbers( map { $_->{item} } @items )
+      : ();
+    # Convert to a hash for quick searching
+    my %hiddenitems = map { $_ => 1 } @hiddenitems;
+    foreach my $itemnumber ( map { $_->{itemnumber} } @items ) {
+        next if $hiddenitems{$itemnumber};
+        my $item_marc = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
         push @item_fields, $item_marc->field($itemtag);
     }
     $marc->append_fields(@item_fields);
@@ -3475,10 +3523,7 @@ sub get_biblio_authorised_values {
 
 =head2 CountBiblioInOrders
 
-=over 4
-$count = &CountBiblioInOrders( $biblionumber);
-
-=back
+    $count = &CountBiblioInOrders( $biblionumber);
 
 This function return count of biblios in orders with $biblionumber 
 
@@ -3498,10 +3543,7 @@ sub CountBiblioInOrders {
 
 =head2 GetSubscriptionsId
 
-=over 4
-$subscriptions = &GetSubscriptionsId($biblionumber);
-
-=back
+    $subscriptions = &GetSubscriptionsId($biblionumber);
 
 This function return an array of subscriptionid with $biblionumber
 
@@ -3521,10 +3563,7 @@ sub GetSubscriptionsId {
 
 =head2 GetHolds
 
-=over 4
-$holds = &GetHolds($biblionumber);
-
-=back
+    $holds = &GetHolds($biblionumber);
 
 This function return the count of holds with $biblionumber
 
@@ -3690,16 +3729,26 @@ sub UpdateTotalIssues {
     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) {
@@ -3710,8 +3759,7 @@ sub UpdateTotalIssues {
          $record->insert_grouped_field($field);
      }
 
-     ModBiblio($record, $biblionumber, $data->{'frameworkcode'});
-     return;
+     return ModBiblio($record, $biblionumber, $data->{'frameworkcode'});
 }
 
 =head2 RemoveAllNsb