X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=cataloguing%2Fmerge.pl;h=146e88e598c19ac30dddd6942d0eefd249f9790f;hb=5e4e10c4ca558180137bf5a4ff5a68495efa0ec7;hp=cc2d01d087ae2973c59c619305df01ca7614503e;hpb=bd73c9f9ce8d161a1ed0f2e1205e5c0c8eecb0ae;p=koha.git diff --git a/cataloguing/merge.pl b/cataloguing/merge.pl index cc2d01d087..146e88e598 100755 --- a/cataloguing/merge.pl +++ b/cataloguing/merge.pl @@ -1,41 +1,48 @@ -#!/usr/bin/perl - +#!/usr/bin/perl # Copyright 2009 BibLibre +# Parts Copyright Catalyst IT 2011 # # 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 . + +use Modern::Perl; +use CGI qw ( -utf8 ); -use strict; -#use warnings; FIXME - Bug 2505 -use CGI; use C4::Output; use C4::Auth; use C4::Items; use C4::Biblio; use C4::Serials; +use C4::Koha; +use C4::Reserves qw/MergeHolds/; +use C4::Acquisition qw/ModOrder GetOrdersByBiblionumber/; + +use Koha::BiblioFrameworks; +use Koha::Items; +use Koha::MetadataRecord; my $input = new CGI; -my @biblionumber = $input->param('biblionumber'); +my @biblionumbers = $input->multi_param('biblionumber'); my $merge = $input->param('merge'); my @errors; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { - template_name => "cataloguing/merge.tmpl", + template_name => "cataloguing/merge.tt", query => $input, type => "intranet", authnotrequired => 0, @@ -48,207 +55,212 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( #------------------------ if ($merge) { - my @params = $input->param(); my $dbh = C4::Context->dbh; - my $sth; # Creating a new record from the html code - my $record = TransformHtmlToMarc( \@params , $input ); - my $tobiblio = $input->param('biblio1'); - my $frombiblio = $input->param('biblio2'); + my $record = TransformHtmlToMarc( $input, 1 ); + my $ref_biblionumber = $input->param('ref_biblionumber'); + @biblionumbers = grep { $_ != $ref_biblionumber } @biblionumbers; + + # prepare report + my @report_records; + my $report_fields_str = $input->param('report_fields'); + $report_fields_str ||= C4::Context->preference('MergeReportFields'); + my @report_fields; + foreach my $field_str (split /,/, $report_fields_str) { + if ($field_str =~ /(\d{3})([0-9a-z]*)/) { + my ($field, $subfields) = ($1, $2); + push @report_fields, { + tag => $field, + subfields => [ split //, $subfields ] + } + } + } # Rewriting the leader - $record->leader(GetMarcBiblio($tobiblio)->leader()); + $record->leader(GetMarcBiblio({ biblionumber => $ref_biblionumber })->leader()); - my $frameworkcode = &GetFrameworkCode($tobiblio); + my $frameworkcode = $input->param('frameworkcode'); my @notmoveditems; # Modifying the reference record - ModBiblio($record, $tobiblio, $frameworkcode); + ModBiblio($record, $ref_biblionumber, $frameworkcode); # Moving items from the other record to the reference record - my $itemnumbers = get_itemnumbers_of($frombiblio); - foreach my $itloop ($itemnumbers->{$frombiblio}) { - foreach my $itemnumber (@$itloop) { - my $res = MoveItemFromBiblio($itemnumber, $frombiblio, $tobiblio); - if (not defined $res) { - push @notmoveditems, $itemnumber; - } - } + foreach my $biblionumber (@biblionumbers) { + my $items = Koha::Items->search({ biblionumber => $biblionumber }); + while ( my $item = $items->next) { + my $res = MoveItemFromBiblio( $item->itemnumber, $biblionumber, $ref_biblionumber ); + if ( not defined $res ) { + push @notmoveditems, $item->itemnumber; + } + } } # If some items could not be moved : if (scalar(@notmoveditems) > 0) { - my $itemlist = join(' ',@notmoveditems); - push @errors, "The following items could not be moved from the old record to the new one: $itemlist"; + my $itemlist = join(' ',@notmoveditems); + push @errors, { code => "CANNOT_MOVE", value => $itemlist }; } - # Moving subscriptions from the other record to the reference record - my $subcount = CountSubscriptionFromBiblionumber($frombiblio); - if ($subcount > 0) { - $sth = $dbh->prepare("UPDATE subscription SET biblionumber = ? WHERE biblionumber = ?"); - $sth->execute($tobiblio, $frombiblio); - - $sth = $dbh->prepare("UPDATE subscriptionhistory SET biblionumber = ? WHERE biblionumber = ?"); - $sth->execute($tobiblio, $frombiblio); - + my $sth_subscription = $dbh->prepare(" + UPDATE subscription SET biblionumber = ? WHERE biblionumber = ? + "); + my $sth_subscriptionhistory = $dbh->prepare(" + UPDATE subscriptionhistory SET biblionumber = ? WHERE biblionumber = ? + "); + my $sth_serial = $dbh->prepare(" + UPDATE serial SET biblionumber = ? WHERE biblionumber = ? + "); + my $sth_suggestions = $dbh->prepare(" + UPDATE suggestions SET biblionumber = ? WHERE biblionumber = ? + "); + + my $report_header = {}; + foreach my $biblionumber ($ref_biblionumber, @biblionumbers) { + # build report + my $marcrecord = GetMarcBiblio({ biblionumber => $biblionumber }); + my %report_record = ( + biblionumber => $biblionumber, + fields => {}, + ); + foreach my $field (@report_fields) { + my @marcfields = $marcrecord->field($field->{tag}); + foreach my $marcfield (@marcfields) { + my $tag = $marcfield->tag(); + if (scalar @{$field->{subfields}}) { + foreach my $subfield (@{$field->{subfields}}) { + my @values = $marcfield->subfield($subfield); + $report_header->{ $tag . $subfield } = 1; + push @{ $report_record{fields}->{$tag . $subfield} }, @values; + } + } elsif ($field->{tag} gt '009') { + my @marcsubfields = $marcfield->subfields(); + foreach my $marcsubfield (@marcsubfields) { + my ($code, $value) = @$marcsubfield; + $report_header->{ $tag . $code } = 1; + push @{ $report_record{fields}->{ $tag . $code } }, $value; + } + } else { + $report_header->{ $tag . '@' } = 1; + push @{ $report_record{fields}->{ $tag .'@' } }, $marcfield->data(); + } + } + } + push @report_records, \%report_record; } + foreach my $biblionumber (@biblionumbers) { + # Moving subscriptions from the other record to the reference record + my $subcount = CountSubscriptionFromBiblionumber($biblionumber); + if ($subcount > 0) { + $sth_subscription->execute($ref_biblionumber, $biblionumber); + $sth_subscriptionhistory->execute($ref_biblionumber, $biblionumber); + } + # Moving serials - $sth = $dbh->prepare("UPDATE serial SET biblionumber = ? WHERE biblionumber = ?"); - $sth->execute($tobiblio, $frombiblio); + $sth_serial->execute($ref_biblionumber, $biblionumber); - # TODO : Moving reserves + # Moving suggestions + $sth_suggestions->execute($ref_biblionumber, $biblionumber); - # Deleting the other record - if (scalar(@errors) == 0) { - my $error = DelBiblio($frombiblio); - push @errors, $error if ($error); + # Moving orders (orders linked to items of frombiblio have already been moved by MoveItemFromBiblio) + my @allorders = GetOrdersByBiblionumber($biblionumber); + foreach my $myorder (@allorders) { + $myorder->{'biblionumber'} = $ref_biblionumber; + ModOrder ($myorder); + # TODO : add error control (in ModOrder?) } - # Errors - my @errors_loop = map{{error => $_}}@errors; + # Deleting the other records + if (scalar(@errors) == 0) { + # Move holds + MergeHolds($dbh, $ref_biblionumber, $biblionumber); + my $error = DelBiblio($biblionumber); + push @errors, $error if ($error); + } +} # Parameters $template->param( - errors => \@errors_loop, - result => 1, - biblio1 => $input->param('biblio1') + result => 1, + report_records => \@report_records, + report_header => $report_header, + ref_biblionumber => scalar $input->param('ref_biblionumber') ); - #------------------------- # Show records to merge #------------------------- } else { - - my $mergereference = $input->param('mergereference'); - my $biblionumber = $input->param('biblionumber'); - - my $data1 = GetBiblioData($biblionumber[0]); - my $data2 = GetBiblioData($biblionumber[1]); - - # Ask the user to choose which record will be the kept - if (not $mergereference) { - $template->param( - choosereference => 1, - biblio1 => $biblionumber[0], - biblio2 => $biblionumber[1], - title1 => $data1->{'title'}, - title2 => $data2->{'title'} - ); + my $ref_biblionumber = $input->param('ref_biblionumber'); + + if ($ref_biblionumber) { + my $framework = $input->param('frameworkcode'); + $framework //= GetFrameworkCode($ref_biblionumber); + + # Getting MARC Structure + my $tagslib = GetMarcStructure(1, $framework); + + my $marcflavour = lc(C4::Context->preference('marcflavour')); + + # Creating a loop for display + my @records; + foreach my $biblionumber (@biblionumbers) { + my $marcrecord = GetMarcBiblio({ biblionumber => $biblionumber }); + my $frameworkcode = GetFrameworkCode($biblionumber); + my $recordObj = new Koha::MetadataRecord({'record' => $marcrecord, schema => $marcflavour}); + my $record = { + recordid => $biblionumber, + record => $marcrecord, + frameworkcode => $frameworkcode, + display => $recordObj->createMergeHash($tagslib), + }; + if ($ref_biblionumber and $ref_biblionumber == $biblionumber) { + $record->{reference} = 1; + $template->param(ref_record => $record); + unshift @records, $record; + } else { + push @records, $record; + } + } + + my ($biblionumbertag) = GetMarcFromKohaField('biblio.biblionumber'); + + # Parameters + $template->param( + ref_biblionumber => $ref_biblionumber, + records => \@records, + ref_record => $records[0], + framework => $framework, + biblionumbertag => $biblionumbertag, + MergeReportFields => C4::Context->preference('MergeReportFields'), + ); } else { - - if (scalar(@biblionumber) != 2) { - push @errors, "An unexpected number of records was provided for merging. Currently only two records at a time can be merged."; - } - - # Checks if both records use the same framework - my $frameworkcode1 = &GetFrameworkCode($biblionumber[0]); - my $frameworkcode2 = &GetFrameworkCode($biblionumber[1]); - my $framework; - if ($frameworkcode1 ne $frameworkcode2) { - push @errors, "The records selected for merging are using different frameworks. Currently merging is only available for records using the same framework."; - } else { - $framework = $frameworkcode1; - } - - # Getting MARC Structure - my $tagslib = GetMarcStructure(1, $framework); - - my $notreference = ($biblionumber[0] == $mergereference) ? $biblionumber[1] : $biblionumber[0]; - - # Creating a loop for display - my @record1 = _createMarcHash(GetMarcBiblio($mergereference), $tagslib); - my @record2 = _createMarcHash(GetMarcBiblio($notreference), $tagslib); - - # Errors - my @errors_loop = map{{error => $_}}@errors; - - # Parameters - $template->param( - errors => \@errors_loop, - biblio1 => $mergereference, - biblio2 => $notreference, - mergereference => $mergereference, - record1 => @record1, - record2 => @record2, - framework => $framework - ); + my @records; + foreach my $biblionumber (@biblionumbers) { + my $frameworkcode = GetFrameworkCode($biblionumber); + my $record = { + biblionumber => $biblionumber, + data => GetBiblioData($biblionumber), + frameworkcode => $frameworkcode, + }; + push @records, $record; + } + # Ask the user to choose which record will be the kept + $template->param( + choosereference => 1, + records => \@records, + ); + + my $frameworks = Koha::BiblioFrameworks->search({}, { order_by => ['frameworktext'] }); + $template->param( frameworks => $frameworks ); } } -output_html_with_http_headers $input, $cookie, $template->output; -exit; - -=head1 FUNCTIONS - -=cut - -# ------------------------ -# Functions -# ------------------------ -sub _createMarcHash { - my $record = shift; - my $tagslib = shift; - my @array; - my @fields = $record->fields(); - - - foreach my $field (@fields) { - my $fieldtag = $field->tag(); - if ($fieldtag < 10) { - if ($tagslib->{$fieldtag}->{'@'}->{'tab'} >= 0) { - push @array, { - field => [ - { - tag => $fieldtag, - key => createKey(), - value => $field->data(), - } - ] - }; - } - } else { - my @subfields = $field->subfields(); - my @subfield_array; - foreach my $subfield (@subfields) { - if ($tagslib->{$fieldtag}->{@$subfield[0]}->{'tab'} >= 0) { - push @subfield_array, { - subtag => @$subfield[0], - subkey => createKey(), - value => @$subfield[1], - }; - } - - } - - if ($tagslib->{$fieldtag}->{'tab'} >= 0 && $fieldtag ne '995') { - push @array, { - field => [ - { - tag => $fieldtag, - key => createKey(), - indicator1 => $field->indicator(1), - indicator2 => $field->indicator(2), - subfield => [@subfield_array], - } - ] - }; - } - - } - } - return [@array]; - -} -=head2 CreateKey - -Create a random value to set it into the input name - -=cut - -sub createKey(){ - return int(rand(1000000)); +if (@errors) { + # Errors + $template->param( errors => \@errors ); } - +output_html_with_http_headers $input, $cookie, $template->output; +exit;