From c77c56cded3f9c048eeb0a6ba49dc887d55ddee9 Mon Sep 17 00:00:00 2001 From: Olli-Antti Kivilahti Date: Fri, 28 Nov 2014 14:18:32 +0200 Subject: [PATCH] Bug 4283 - Merge bibliographic records Initial stuff. Some documents. --- C4/Biblio.pm | 27 ++++ cataloguing/deduplicator.pl | 97 ++++++++++++++ .../prog/en/modules/cataloguing/addbooks.tt | 3 + .../prog/en/modules/cataloguing/deduplicator.tt | 135 ++++++++++++++++++++ 4 files changed, 262 insertions(+) create mode 100755 cataloguing/deduplicator.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/deduplicator.tt diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 8bdb25f..30d785f 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -874,6 +874,33 @@ sub GetBiblionumberFromItemnumber { return ($result); } +=head2 GetBiblionumberSlice + + my $biblionumbers = C4::Biblio::GetBiblionumberSlice( 100, 450 ); + +@PARAM1 Long, maximum amount of biblio-rows to return. Same as the SQL LIMIT-clause. + Defaults to 0. +@PARAM2 Long, how many biblio-rows to skip starting from the first row. Same as the SQL OFFSET-clause. + Defaults to 500. +@RETURN Array of Long, a slice of biblionumbers starting from the offset and no more rows than the limit-parameter. +=cut + +sub GetBiblionumberSlice { + my ($limit, $offset) = @_; + $limit = ($limit) ? $limit : 500 ; + $offset = ($offset) ? $offset : 0; + + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("SELECT biblionumber FROM biblio LIMIT ? OFFSET ?"); + $sth->execute($limit, $offset); + + my @biblionumbers; + while(my $bn = $sth->fetchrow()) { + push @biblionumbers, $bn; + } + return \@biblionumbers; +} + =head2 GetBiblioFromItemNumber $item = &GetBiblioFromItemNumber($itemnumber,$barcode); diff --git a/cataloguing/deduplicator.pl b/cataloguing/deduplicator.pl new file mode 100755 index 0000000..d71bcd0 --- /dev/null +++ b/cataloguing/deduplicator.pl @@ -0,0 +1,97 @@ +#!/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 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. + +use Modern::Perl; +use CGI; +use C4::Output; +use C4::Auth; + +use C4::Matcher; +use C4::Items; +use C4::Biblio; + + +my $input = new CGI; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "cataloguing/deduplicator.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => { editcatalogue => 'edit_catalogue' }, + } +); + +my $max_matches = 100; +my $matcher_id = $input->param('matcher_id'); +my $op = $input->param('op'); + +#Get the matchers list and set the selected matcher as selected. +my @matchers = C4::Matcher::GetMatcherList( $matcher_id ); +foreach (@matchers) { + if ($matcher_id && $_->{matcher_id} == $matcher_id) { + $_->{selected} = 1; + last(); + } +} +$template->param( matchers => \@matchers ); + +if ($op && $op eq 'deduplicate') { + my $matcher = C4::Matcher->fetch($matcher_id); + my $biblionumbers = C4::Biblio::GetBiblionumberSlice( $input->param('limit'), $input->param('offset') ); + + my @duplicates; + foreach my $biblionumber (@$biblionumbers) { + my $marc = C4::Biblio::GetMarcBiblio($biblionumber); + my @matches = $matcher->get_matches( $marc, $max_matches ); + + if (scalar(@matches) > 1) { + foreach my $match (@matches) { + my $itemsCount = C4::Items::GetItemsCount($match->{record_id}); + $match->{itemsCount} = $itemsCount; + } + my $biblio = buildSlimBiblio($biblionumber, $marc); + $biblio->{matches} = \@matches; + + push @duplicates, $biblio; + } + } + $template->param( duplicates => \@duplicates ) if scalar(@duplicates) > 0; +} + +output_html_with_http_headers $input, $cookie, $template->output; + + +sub buildSlimBiblio { + my ($biblionumber, $marc) = @_; + + my $biblio = {biblionumber => $biblionumber}; + my $title = $marc->subfield('245','a'); + $title = $marc->subfield('240','a') unless $title; + my $author = $marc->subfield('100','a'); + $author = $marc->subfield('110','a') unless $author; + + $biblio->{author} = $author; + $biblio->{title} = $title; + + return $biblio; +} \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt index 8a02dd5..6eae94d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt @@ -73,6 +73,9 @@ [% END %] +
+ +
[% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/deduplicator.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/deduplicator.tt new file mode 100644 index 0000000..052893c --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/deduplicator.tt @@ -0,0 +1,135 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Cataloging › Deduplicator +[% INCLUDE 'greybox.inc' %] +[% INCLUDE 'doc-head-close.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'cataloging-search.inc' %] + + +
+
+
+ + +

Deduplicator

+ +
+
+ +
+ Configure the deduplication search! +
    +
  1. + How many bibliographic records to deduplicate? Hint: less than 1000. +
  2. +
  3. + From which bibliographic record to start? Hint: increment this by the limit of previous deduplication run. If limit = 200, then first offset is 0, then 200, then 400... +
  4. +
  5. + + + The matcher to use to find duplicates. Hint: one can define matchers from the administration menu. +
  6. +
  7. + +
  8. +
+
+
+
+ + + +[% IF duplicates %] +
+
+ + List of duplicates + + + + + + + +
    + [% FOREACH duplicate IN duplicates %] +
    + +
  1. + +
    [% duplicate.title %]
    +
    [% duplicate.author %]
    +
    +
  2. +
    + [% END %] +
+
+
+[% END %] +
+
+ + +[% INCLUDE 'intranet-bottom.inc' %] \ No newline at end of file -- 1.7.9.5