X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FBiblio.pm;h=52119ea990c7a7584d31650a445be3b739df5863;hb=f21577986f8ff5da5fde88deaae2302a8b40dbe7;hp=135dd9163048e9c2c8eaa5ccba47645752872b4b;hpb=36efd0d4d0cfe5bbdcd9a4b48e0e417a59aaa63a;p=koha_fer diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 135dd91630..52119ea990 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -2,6 +2,7 @@ package C4::Biblio; # Copyright 2000-2002 Katipo Communications # Copyright 2010 BibLibre +# Copyright 2011 Equinox Software, Inc. # # This file is part of Koha. # @@ -20,6 +21,7 @@ package C4::Biblio; use strict; use warnings; +use Carp; # use utf8; use MARC::Record; @@ -35,6 +37,7 @@ use C4::ClassSource; use C4::Charset; require C4::Heading; require C4::Serials; +require C4::Items; use vars qw($VERSION @ISA @EXPORT); @@ -75,18 +78,25 @@ BEGIN { &GetMarcBiblio &GetMarcAuthors &GetMarcSeries + &GetMarcHosts GetMarcUrls &GetUsedMarcStructure &GetXmlBiblio &GetCOinSBiblio + &GetMarcPrice + &GetMarcQuantity &GetAuthorisedValueDesc &GetMarcStructure &GetMarcFromKohaField &GetFrameworkCode &TransformKohaToMarc + &PrepHostMarcField &CountItemsIssued + &CountBiblioInOrders + &GetSubscriptionsId + &GetHolds ); # To modify something @@ -290,58 +300,30 @@ and biblionumber data for indexing. sub ModBiblio { my ( $record, $biblionumber, $frameworkcode ) = @_; + croak "No record" unless $record; + if ( C4::Context->preference("CataloguingLog") ) { my $newrecord = GetMarcBiblio($biblionumber); logaction( "CATALOGUING", "MODIFY", $biblionumber, "BEFORE=>" . $newrecord->as_formatted ); } - SetUTF8Flag($record); - my $dbh = C4::Context->dbh; - - $frameworkcode = "" unless $frameworkcode; - - # get the items before and append them to the biblio before updating the record, atm we just have the biblio - my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode ); - my $oldRecord = GetMarcBiblio($biblionumber); - - # delete any item fields from incoming record to avoid - # duplication or incorrect data - use AddItem() or ModItem() - # to change items - foreach my $field ( $record->field($itemtag) ) { - $record->delete_field($field); - } - - # parse each item, and, for an unknown reason, re-encode each subfield - # if you don't do that, the record will have encoding mixed - # and the biblio will be re-encoded. - # strange, I (Paul P.) searched more than 1 day to understand what happends - # but could only solve the problem this way... - my @fields = $oldRecord->field($itemtag); - foreach my $fielditem (@fields) { - my $field; - foreach ( $fielditem->subfields() ) { - # re-encode the subfield only if it isn't already in utf-8. - my ($tag, $value) = @$_; - $tag = Encode::encode('utf-8', $tag) unless utf8::is_utf8($tag); - $value = Encode::encode('utf-8', $value) unless utf8::is_utf8($value); - - if ($field) { - $field->add_subfields( $tag => $value ); - } else { - $field = MARC::Field->new( "$itemtag", '', '', $tag => $value ); - } - } - $record->append_fields($field); - } - + # Cleaning up invalid fields must be done early or SetUTF8Flag is liable to + # throw an exception which probably won't be handled. foreach my $field ($record->fields()) { if (! $field->is_control_field()) { - if (scalar($field->subfields()) == 0) { - $record->delete_fields($field); + if (scalar($field->subfields()) == 0 || (scalar($field->subfields()) == 1 && $field->subfield('9'))) { + $record->delete_field($field); } } } + SetUTF8Flag($record); + my $dbh = C4::Context->dbh; + + $frameworkcode = "" unless $frameworkcode; + + _strip_item_fields($record, $frameworkcode); + # update biblionumber and biblioitemnumber in MARC # FIXME - this is assuming a 1 to 1 relationship between # biblios and biblioitems @@ -366,6 +348,29 @@ sub ModBiblio { return 1; } +=head2 _strip_item_fields + + _strip_item_fields($record, $frameworkcode) + +Utility routine to remove item tags from a +MARC bib. + +=cut + +sub _strip_item_fields { + my $record = shift; + my $frameworkcode = shift; + # get the items before and append them to the biblio before updating the record, atm we just have the biblio + my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode ); + + # delete any item fields from incoming record to avoid + # duplication or incorrect data - use AddItem() or ModItem() + # to change items + foreach my $field ( $record->field($itemtag) ) { + $record->delete_field($field); + } +} + =head2 ModBiblioframework ModBiblioframework($biblionumber,$frameworkcode); @@ -384,7 +389,7 @@ sub ModBiblioframework { =head2 DelBiblio - my $error = &DelBiblio($dbh,$biblionumber); + 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) @@ -758,7 +763,8 @@ Return the ISBD view which can be included in opac and intranet sub GetISBDView { my ( $biblionumber, $template ) = @_; - my $record = GetMarcBiblio($biblionumber); + my $record = GetMarcBiblio($biblionumber, 1); + return undef unless defined $record; my $itemtype = &GetFrameworkCode($biblionumber); my ( $holdingbrtagf, $holdingbrtagsubf ) = &GetMarcFromKohaField( "items.holdingbranch", $itemtype ); my $tagslib = &GetMarcStructure( 1, $itemtype ); @@ -1044,16 +1050,18 @@ sub GetMarcFromKohaField { =head2 GetMarcBiblio - my $record = GetMarcBiblio($biblionumber); + my $record = GetMarcBiblio($biblionumber, [$embeditems]); Returns MARC::Record representing bib identified by C<$biblionumber>. If no bib exists, returns undef. -The MARC record contains both biblio & item data. +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. =cut sub GetMarcBiblio { my $biblionumber = shift; + my $embeditems = shift || 0; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare("SELECT marcxml FROM biblioitems WHERE biblionumber=? "); $sth->execute($biblionumber); @@ -1065,8 +1073,11 @@ sub GetMarcBiblio { if ($marcxml) { $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); - # $record = MARC::Record::new_from_usmarc( $marc) if $marc; return $record; } else { return undef; @@ -1093,20 +1104,17 @@ sub GetXmlBiblio { =head2 GetCOinSBiblio - my $coins = GetCOinSBiblio($biblionumber); + my $coins = GetCOinSBiblio($record); -Returns the COinS(a span) which can be included in a biblio record +Returns the COinS (a span) which can be included in a biblio record =cut sub GetCOinSBiblio { - my ($biblionumber) = @_; - my $record = GetMarcBiblio($biblionumber); + my $record = shift; # get the coin format if ( ! $record ) { - # can't get a valid MARC::Record object, bail out at this point - warn "We called GetMarcBiblio with a biblionumber that doesn't exist biblionumber=$biblionumber"; return; } my $pos7 = substr $record->leader(), 7, 1; @@ -1174,8 +1182,8 @@ sub GetCOinSBiblio { if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) { # Setting datas - $aulast = $record->subfield( '700', 'a' ); - $aufirst = $record->subfield( '700', 'b' ); + $aulast = $record->subfield( '700', 'a' ) || ''; + $aufirst = $record->subfield( '700', 'b' ) || ''; $oauthors = "&rft.au=$aufirst $aulast"; # others authors @@ -1188,10 +1196,10 @@ sub GetCOinSBiblio { ( $mtx eq 'dc' ) ? "&rft.title=" . $record->subfield( '200', 'a' ) : "&rft.title=" . $record->subfield( '200', 'a' ) . "&rft.btitle=" . $record->subfield( '200', 'a' ); - $pubyear = $record->subfield( '210', 'd' ); - $publisher = $record->subfield( '210', 'c' ); - $isbn = $record->subfield( '010', 'a' ); - $issn = $record->subfield( '011', 'a' ); + $pubyear = $record->subfield( '210', 'd' ) || ''; + $publisher = $record->subfield( '210', 'c' ) || ''; + $isbn = $record->subfield( '010', 'a' ) || ''; + $issn = $record->subfield( '011', 'a' ) || ''; } else { # MARC21 need some improve @@ -1211,7 +1219,8 @@ sub GetCOinSBiblio { $subtitle = $record->subfield( '245', 'b' ) || ''; $title .= $subtitle; if ($titletype eq 'a') { - $pubyear = substr $record->field('008')->data(), 7, 4; + $pubyear = $record->field('008') || ''; + $pubyear = substr($pubyear->data(), 7, 4) if $pubyear; $isbn = $record->subfield( '773', 'z' ) || ''; $issn = $record->subfield( '773', 'x' ) || ''; if ($mtx eq 'journal') { @@ -1243,6 +1252,72 @@ sub GetCOinSBiblio { return $coins_value; } + +=head2 GetMarcPrice + +return the prices in accordance with the Marc format. +=cut + +sub GetMarcPrice { + my ( $record, $marcflavour ) = @_; + my @listtags; + my $subfield; + + if ( $marcflavour eq "MARC21" ) { + @listtags = ('345', '020'); + $subfield="c"; + } elsif ( $marcflavour eq "UNIMARC" ) { + @listtags = ('345', '010'); + $subfield="d"; + } else { + return; + } + + for my $field ( $record->field(@listtags) ) { + for my $subfield_value ($field->subfield($subfield)){ + #check value + return $subfield_value if ($subfield_value); + } + } + return 0; # no price found +} + +=head2 GetMarcQuantity + +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 + +=cut + +sub GetMarcQuantity { + my ( $record, $marcflavour ) = @_; + my @listtags; + my $subfield; + + if ( $marcflavour eq "MARC21" ) { + return 0 + } elsif ( $marcflavour eq "UNIMARC" ) { + @listtags = ('969'); + $subfield="a"; + } else { + return; + } + + for my $field ( $record->field(@listtags) ) { + for my $subfield_value ($field->subfield($subfield)){ + #check value + if ($subfield_value) { + # in France, the cents separator is the , but sometimes, ppl use a . + # in this case, the price will be x100 when unformatted ! Replace the . by a , to get a proper price calculation + $subfield_value =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR"; + return $subfield_value; + } + } + } + return 0; # no price found +} + + =head2 GetAuthorisedValueDesc my $subfieldvalue =get_authorised_value_desc( @@ -1326,10 +1401,10 @@ ISBNs stored in differents places depending on MARC flavour sub GetMarcISBN { my ( $record, $marcflavour ) = @_; my $scope; - if ( $marcflavour eq "MARC21" ) { - $scope = '020'; - } else { # assume unimarc if not marc21 + if ( $marcflavour eq "UNIMARC" ) { $scope = '010'; + } else { # assume marc21 if not unimarc + $scope = '020'; } my @marcisbns; my $isbn = ""; @@ -1366,10 +1441,10 @@ The note are stored in differents places depending on MARC flavour sub GetMarcNotes { my ( $record, $marcflavour ) = @_; my $scope; - if ( $marcflavour eq "MARC21" ) { - $scope = '5..'; - } else { # assume unimarc if not marc21 + if ( $marcflavour eq "UNIMARC" ) { $scope = '3..'; + } else { # assume marc21 if not unimarc + $scope = '5..'; } my @marcnotes; my $note = ""; @@ -1406,12 +1481,12 @@ The subjects are stored in differents places depending on MARC flavour sub GetMarcSubjects { my ( $record, $marcflavour ) = @_; my ( $mintag, $maxtag ); - if ( $marcflavour eq "MARC21" ) { - $mintag = "600"; - $maxtag = "699"; - } else { # assume unimarc if not marc21 + if ( $marcflavour eq "UNIMARC" ) { $mintag = "600"; $maxtag = "611"; + } else { # assume marc21 if not unimarc + $mintag = "600"; + $maxtag = "699"; } my @marcsubjects; @@ -1441,7 +1516,10 @@ sub GetMarcSubjects { my $value = $subject_subfield->[1]; my $linkvalue = $value; $linkvalue =~ s/(\(|\))//g; - my $operator = " and " unless $counter == 0; + my $operator; + if ( $counter != 0 ) { + $operator = ' and '; + } if ( $code eq 9 ) { $found9 = 1; @link_loop = ( { 'limit' => 'an', link => "$linkvalue" } ); @@ -1449,7 +1527,10 @@ sub GetMarcSubjects { if ( not $found9 ) { push @link_loop, { 'limit' => $subject_limit, link => $linkvalue, operator => $operator }; } - my $separator = C4::Context->preference("authoritysep") unless $counter == 0; + my $separator; + if ( $counter != 0 ) { + $separator = C4::Context->preference('authoritysep'); + } # ignore $9 my @this_link_loop = @link_loop; @@ -1479,12 +1560,12 @@ sub GetMarcAuthors { # tagslib useful for UNIMARC author reponsabilities my $tagslib = &GetMarcStructure( 1, '' ); # FIXME : we don't have the framework available, we take the default framework. May be buggy on some setups, will be usually correct. - if ( $marcflavour eq "MARC21" ) { - $mintag = "700"; - $maxtag = "720"; - } elsif ( $marcflavour eq "UNIMARC" ) { # assume unimarc if not marc21 + if ( $marcflavour eq "UNIMARC" ) { $mintag = "700"; $maxtag = "712"; + } elsif ( $marcflavour eq "MARC21" || $marcflavour eq "NORMARC" ) { # assume marc21 or normarc if not unimarc + $mintag = "700"; + $maxtag = "720"; } else { return; } @@ -1507,7 +1588,10 @@ sub GetMarcAuthors { my $value = $authors_subfield->[1]; my $linkvalue = $value; $linkvalue =~ s/(\(|\))//g; - my $operator = " and " unless $count_auth == 0; + my $operator; + if ( $count_auth != 0 ) { + $operator = ' and '; + } # if we have an authority link, use that as the link, otherwise use standard searching if ($subfield9) { @@ -1523,8 +1607,17 @@ sub GetMarcAuthors { $value = GetAuthorisedValueDesc( $field->tag(), $authors_subfield->[0], $authors_subfield->[1], '', $tagslib ) if ( $marcflavour eq 'UNIMARC' and ( $authors_subfield->[0] =~ /4/ ) ); my @this_link_loop = @link_loop; - my $separator = C4::Context->preference("authoritysep") unless $count_auth == 0; - push @subfields_loop, { code => $subfieldcode, value => $value, link_loop => \@this_link_loop, separator => $separator } unless ( $authors_subfield->[0] eq '9' ); + my $separator; + if ( $count_auth != 0 ) { + $separator = C4::Context->preference('authoritysep'); + } + push @subfields_loop, + { code => $subfieldcode, + value => $value, + link_loop => \@this_link_loop, + separator => $separator + } + unless ( $authors_subfield->[0] eq '9' ); $count_auth++; } push @marcauthors, { MARCAUTHOR_SUBFIELDS_LOOP => \@subfields_loop }; @@ -1599,12 +1692,12 @@ The series are stored in differents places depending on MARC flavour sub GetMarcSeries { my ( $record, $marcflavour ) = @_; my ( $mintag, $maxtag ); - if ( $marcflavour eq "MARC21" ) { - $mintag = "440"; - $maxtag = "490"; - } else { # assume unimarc if not marc21 + if ( $marcflavour eq "UNIMARC" ) { $mintag = "600"; $maxtag = "619"; + } else { # assume marc21 if not unimarc + $mintag = "440"; + $maxtag = "490"; } my @marcseries; @@ -1635,13 +1728,27 @@ sub GetMarcSeries { my $value = $series_subfield->[1]; my $linkvalue = $value; $linkvalue =~ s/(\(|\))//g; - my $operator = " and " unless $counter == 0; - push @link_loop, { link => $linkvalue, operator => $operator }; - my $separator = C4::Context->preference("authoritysep") unless $counter == 0; + if ( $counter != 0 ) { + push @link_loop, { link => $linkvalue, operator => ' and ', }; + } else { + push @link_loop, { link => $linkvalue, operator => undef, }; + } + my $separator; + if ( $counter != 0 ) { + $separator = C4::Context->preference('authoritysep'); + } if ($volume_number) { push @subfields_loop, { volumenum => $value }; } else { - push @subfields_loop, { code => $code, value => $value, link_loop => \@link_loop, separator => $separator, volumenum => $volume_number } unless ( $series_subfield->[0] eq '9' ); + if ( $series_subfield->[0] ne '9' ) { + push @subfields_loop, { + code => $code, + value => $value, + link_loop => \@link_loop, + separator => $separator, + volumenum => $volume_number, + }; + } } $counter++; } @@ -1656,6 +1763,48 @@ sub GetMarcSeries { return $marcseriessarray; } #end getMARCseriess +=head2 GetMarcHosts + + $marchostsarray = GetMarcHosts($record,$marcflavour); + +Get all host records (773s MARC21, 461 UNIMARC) from the MARC record and returns them in an array. + +=cut + +sub GetMarcHosts { + my ( $record, $marcflavour ) = @_; + my ( $tag,$title_subf,$bibnumber_subf,$itemnumber_subf); + $marcflavour ||="MARC21"; + if ( $marcflavour eq "MARC21" || $marcflavour eq "NORMARC" ) { + $tag = "773"; + $title_subf = "t"; + $bibnumber_subf ="0"; + $itemnumber_subf='9'; + } + elsif ($marcflavour eq "UNIMARC") { + $tag = "461"; + $title_subf = "t"; + $bibnumber_subf ="0"; + $itemnumber_subf='9'; + }; + + my @marchosts; + + foreach my $field ( $record->field($tag)) { + + my @fields_loop; + + my $hostbiblionumber = $field->subfield("$bibnumber_subf"); + my $hosttitle = $field->subfield($title_subf); + my $hostitemnumber=$field->subfield($itemnumber_subf); + push @fields_loop, { hostbiblionumber => $hostbiblionumber, hosttitle => $hosttitle, hostitemnumber => $hostitemnumber}; + push @marchosts, { MARCHOSTS_FIELDS_LOOP => \@fields_loop }; + + } + my $marchostsarray = \@marchosts; + return $marchostsarray; +} + =head2 GetFrameworkCode $frameworkcode = GetFrameworkCode( $biblionumber ) @@ -1693,6 +1842,86 @@ sub TransformKohaToMarc { return $record; } +=head2 PrepHostMarcField + + $hostfield = PrepHostMarcField ( $hostbiblionumber,$hostitemnumber,$marcflavour ) + +This function returns a host field populated with data from the host record, the field can then be added to an analytical record + +=cut + +sub PrepHostMarcField { + my ($hostbiblionumber,$hostitemnumber, $marcflavour) = @_; + $marcflavour ||="MARC21"; + + my $hostrecord = GetMarcBiblio($hostbiblionumber); + my $item = C4::Items::GetItem($hostitemnumber); + + my $hostmarcfield; + if ( $marcflavour eq "MARC21" || $marcflavour eq "NORMARC" ) { + + #main entry + my $mainentry; + if ($hostrecord->subfield('100','a')){ + $mainentry = $hostrecord->subfield('100','a'); + } elsif ($hostrecord->subfield('110','a')){ + $mainentry = $hostrecord->subfield('110','a'); + } else { + $mainentry = $hostrecord->subfield('111','a'); + } + + # qualification info + my $qualinfo; + if (my $field260 = $hostrecord->field('260')){ + $qualinfo = $field260->as_string( 'abc' ); + } + + + #other fields + my $ed = $hostrecord->subfield('250','a'); + my $barcode = $item->{'barcode'}; + my $title = $hostrecord->subfield('245','a'); + + # record control number, 001 with 003 and prefix + my $recctrlno; + if ($hostrecord->field('001')){ + $recctrlno = $hostrecord->field('001')->data(); + if ($hostrecord->field('003')){ + $recctrlno = '('.$hostrecord->field('003')->data().')'.$recctrlno; + } + } + + # issn/isbn + my $issn = $hostrecord->subfield('022','a'); + my $isbn = $hostrecord->subfield('020','a'); + + + $hostmarcfield = MARC::Field->new( + 773, '0', '', + '0' => $hostbiblionumber, + '9' => $hostitemnumber, + 'a' => $mainentry, + 'b' => $ed, + 'd' => $qualinfo, + 'o' => $barcode, + 't' => $title, + 'w' => $recctrlno, + 'x' => $issn, + 'z' => $isbn + ); + } elsif ($marcflavour eq "UNIMARC") { + $hostmarcfield = MARC::Field->new( + 461, '', '', + '0' => $hostbiblionumber, + 't' => $hostrecord->subfield('200','a'), + '9' => $hostitemnumber + ); + }; + + return $hostmarcfield; +} + + =head2 TransformKohaToMarcOneField $record = TransformKohaToMarcOneField( $sth, $record, $kohafieldname, $value, $frameworkcode ); @@ -1885,8 +2114,8 @@ sub _default_ind_to_space { =head2 TransformHtmlToMarc - L<$record> = TransformHtmlToMarc(L<$params>,L<$cgi>) - L<$params> is a ref to an array as below: + L<$record> = TransformHtmlToMarc(L<$cgi>) + L<$cgi> is the CGI object which containts the values for subfields { 'tag_010_indicator1_531951' , 'tag_010_indicator2_531951' , @@ -1903,15 +2132,15 @@ sub _default_ind_to_space { 'tag_200_code_f_873510_110730' , 'tag_200_subfield_f_873510_110730' , } - L<$cgi> is the CGI object which containts the value. L<$record> is the MARC::Record object. =cut sub TransformHtmlToMarc { - my $params = shift; my $cgi = shift; + my @params = $cgi->param(); + # explicitly turn on the UTF-8 flag for all # 'tag_' parameters to avoid incorrect character # conversion later on @@ -1931,8 +2160,8 @@ sub TransformHtmlToMarc { my $record = MARC::Record->new(); my $i = 0; my @fields; - while ( $params->[$i] ) { # browse all CGI params - my $param = $params->[$i]; + while ( $params[$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) @@ -1948,7 +2177,7 @@ sub TransformHtmlToMarc { my $tag = $1; my $ind1 = _default_ind_to_space( substr( $cgi->param($param), 0, 1 ) ); - my $ind2 = _default_ind_to_space( substr( $cgi->param( $params->[ $i + 1 ] ), 0, 1 ) ); + my $ind2 = _default_ind_to_space( substr( $cgi->param( $params[ $i + 1 ] ), 0, 1 ) ); $newfield = 0; my $j = $i + 2; @@ -1958,27 +2187,27 @@ sub TransformHtmlToMarc { # Force a fake leader even if not provided to avoid crashing # during decoding MARC record containing UTF-8 characters $record->leader( - length( $cgi->param($params->[$j+1]) ) == 24 - ? $cgi->param( $params->[ $j + 1 ] ) + length( $cgi->param($params[$j+1]) ) == 24 + ? $cgi->param( $params[ $j + 1 ] ) : ' nam a22 4500' ) ; # between 001 and 009 (included) - } elsif ( $cgi->param( $params->[ $j + 1 ] ) ne '' ) { - $newfield = MARC::Field->new( $tag, $cgi->param( $params->[ $j + 1 ] ), ); + } elsif ( $cgi->param( $params[ $j + 1 ] ) ne '' ) { + $newfield = MARC::Field->new( $tag, $cgi->param( $params[ $j + 1 ] ), ); } # > 009, deal with subfields } else { - while ( defined $params->[$j] && $params->[$j] =~ /_code_/ ) { # browse all it's subfield - my $inner_param = $params->[$j]; + while ( defined $params[$j] && $params[$j] =~ /_code_/ ) { # browse all it's subfield + my $inner_param = $params[$j]; if ($newfield) { - if ( $cgi->param( $params->[ $j + 1 ] ) ne '' ) { # only if there is a value (code => value) - $newfield->add_subfields( $cgi->param($inner_param) => $cgi->param( $params->[ $j + 1 ] ) ); + if ( $cgi->param( $params[ $j + 1 ] ) ne '' ) { # only if there is a value (code => value) + $newfield->add_subfields( $cgi->param($inner_param) => $cgi->param( $params[ $j + 1 ] ) ); } } else { - if ( $cgi->param( $params->[ $j + 1 ] ) ne '' ) { # creating only if there is a value (code => value) - $newfield = MARC::Field->new( $tag, $ind1, $ind2, $cgi->param($inner_param) => $cgi->param( $params->[ $j + 1 ] ), ); + if ( $cgi->param( $params[ $j + 1 ] ) ne '' ) { # creating only if there is a value (code => value) + $newfield = MARC::Field->new( $tag, $ind1, $ind2, $cgi->param($inner_param) => $cgi->param( $params[ $j + 1 ] ), ); } } $j += 2; @@ -2257,8 +2486,11 @@ sub PrepareItemrecordDisplay { my $tagslib = &GetMarcStructure( 1, $frameworkcode ); # return nothing if we don't have found an existing framework. - return "" unless $tagslib; - my $itemrecord = C4::Items::GetMarcItem( $bibnum, $itemnum ) if ($itemnum); + return q{} unless $tagslib; + my $itemrecord; + if ($itemnum) { + $itemrecord = C4::Items::GetMarcItem( $bibnum, $itemnum ); + } my @loop_data; my $authorised_values_sth = $dbh->prepare( "SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib" ); foreach my $tag ( sort keys %{$tagslib} ) { @@ -2297,15 +2529,20 @@ sub PrepareItemrecordDisplay { && C4::Context->preference('itemcallnumber') ) { my $CNtag = substr( C4::Context->preference('itemcallnumber'), 0, 3 ); my $CNsubfield = substr( C4::Context->preference('itemcallnumber'), 3, 1 ); - my $temp = $itemrecord->field($CNtag) if ($itemrecord); - if ($temp) { - $defaultvalue = $temp->subfield($CNsubfield); + if ($itemrecord) { + my $temp = $itemrecord->field($CNtag); + if ($temp) { + $defaultvalue = $temp->subfield($CNsubfield); + } } } if ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.itemcallnumber' && $defaultvalues && $defaultvalues->{'callnumber'} ) { - my $temp = $itemrecord->field($subfield) if ($itemrecord); + my $temp; + if ($itemrecord) { + $temp = $itemrecord->field($subfield); + } unless ($temp) { $defaultvalue = $defaultvalues->{'callnumber'} if $defaultvalues; } @@ -2313,7 +2550,10 @@ sub PrepareItemrecordDisplay { if ( ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.holdingbranch' || $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.homebranch' ) && $defaultvalues && $defaultvalues->{'branchcode'} ) { - my $temp = $itemrecord->field($subfield) if ($itemrecord); + my $temp; + if ($itemrecord) { + $temp = $itemrecord->field($subfield); + } unless ($temp) { $defaultvalue = $defaultvalues->{branchcode} if $defaultvalues; } @@ -2438,8 +2678,10 @@ sub PrepareItemrecordDisplay { } } } - my $itemnumber = $itemrecord->subfield( $itemtagfield, $itemtagsubfield ) - if ( $itemrecord && $itemrecord->field($itemtagfield) ); + my $itemnumber; + if ( $itemrecord && $itemrecord->field($itemtagfield) ) { + $itemnumber = $itemrecord->subfield( $itemtagfield, $itemtagsubfield ); + } return { 'itemtagfield' => $itemtagfield, 'itemtagsubfield' => $itemtagsubfield, @@ -2586,6 +2828,36 @@ sub GetNoZebraIndexes { return %indexes; } +=head2 EmbedItemsInMarcBiblio + + EmbedItemsInMarcBiblio($marc, $biblionumber); + +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. + +=cut + +sub EmbedItemsInMarcBiblio { + my ($marc, $biblionumber) = @_; + croak "No MARC record" unless $marc; + + my $frameworkcode = GetFrameworkCode($biblionumber); + _strip_item_fields($marc, $frameworkcode); + + # ... and embed the current items + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber = ?"); + $sth->execute($biblionumber); + my @item_fields; + my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode ); + while (my ($itemnumber) = $sth->fetchrow_array) { + my $item_marc = C4::Items::GetMarcItem($biblionumber, $itemnumber); + push @item_fields, $item_marc->field($itemtag); + } + $marc->append_fields(@item_fields); +} + =head1 INTERNAL FUNCTIONS =head2 _DelBiblioNoZebra($biblionumber,$record,$server); @@ -2924,7 +3196,7 @@ sub _koha_marc_update_bib_ids { # drop old field and create new one... $old_field = $record->field($biblio_tag); $record->delete_field($old_field) if $old_field; - $record->append_fields($new_field); + $record->insert_fields_ordered($new_field); # deal with biblioitemnumber if ( $biblioitem_tag < 10 ) { @@ -3247,9 +3519,12 @@ sub _koha_delete_biblio { $bkup_sth->finish; # delete the biblio - my $del_sth = $dbh->prepare("DELETE FROM biblio WHERE biblionumber=?"); - $del_sth->execute($biblionumber); - $del_sth->finish; + my $sth2 = $dbh->prepare("DELETE FROM biblio WHERE biblionumber=?"); + $sth2->execute($biblionumber); + # update the timestamp (Bugzilla 7146) + $sth2= $dbh->prepare("UPDATE deletedbiblio SET timestamp=NOW() WHERE biblionumber=?"); + $sth2->execute($biblionumber); + $sth2->finish; } $sth->finish; return undef; @@ -3293,9 +3568,12 @@ sub _koha_delete_biblioitems { $bkup_sth->finish; # delete the biblioitem - my $del_sth = $dbh->prepare("DELETE FROM biblioitems WHERE biblioitemnumber=?"); - $del_sth->execute($biblioitemnumber); - $del_sth->finish; + my $sth2 = $dbh->prepare("DELETE FROM biblioitems WHERE biblioitemnumber=?"); + $sth2->execute($biblioitemnumber); + # update the timestamp (Bugzilla 7146) + $sth2= $dbh->prepare("UPDATE deletedbiblioitems SET timestamp=NOW() WHERE biblioitemnumber=?"); + $sth2->execute($biblioitemnumber); + $sth2->finish; } $sth->finish; return undef; @@ -3340,7 +3618,7 @@ sub ModBiblioMarc { } substr( $string, 22, 6, "frey50" ); unless ( $record->subfield( 100, "a" ) ) { - $record->insert_grouped_field( MARC::Field->new( 100, "", "", "a" => $string ) ); + $record->insert_fields_ordered( MARC::Field->new( 100, "", "", "a" => $string ) ); } } @@ -3534,6 +3812,76 @@ sub get_biblio_authorised_values { return $authorised_values; } +=head2 CountBiblioInOrders + +=over 4 +$count = &CountBiblioInOrders( $biblionumber); + +=back + +This function return count of biblios in orders with $biblionumber + +=cut + +sub CountBiblioInOrders { + my ($biblionumber) = @_; + my $dbh = C4::Context->dbh; + my $query = "SELECT count(*) + FROM aqorders + WHERE biblionumber=? AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')"; + my $sth = $dbh->prepare($query); + $sth->execute($biblionumber); + my $count = $sth->fetchrow; + return ($count); +} + +=head2 GetSubscriptionsId + +=over 4 +$subscriptions = &GetSubscriptionsId($biblionumber); + +=back + +This function return an array of subscriptionid with $biblionumber + +=cut + +sub GetSubscriptionsId { + my ($biblionumber) = @_; + my $dbh = C4::Context->dbh; + my $query = "SELECT subscriptionid + FROM subscription + WHERE biblionumber=?"; + my $sth = $dbh->prepare($query); + $sth->execute($biblionumber); + my @subscriptions = $sth->fetchrow_array; + return (@subscriptions); +} + +=head2 GetHolds + +=over 4 +$holds = &GetHolds($biblionumber); + +=back + +This function return the count of holds with $biblionumber + +=cut + +sub GetHolds { + my ($biblionumber) = @_; + my $dbh = C4::Context->dbh; + my $query = "SELECT count(*) + FROM reserves + WHERE biblionumber=?"; + my $sth = $dbh->prepare($query); + $sth->execute($biblionumber); + my $holds = $sth->fetchrow; + return ($holds); +} + + 1; __END__