@@ -, +, @@ - Add some biblios to a list - In the list check some biblios and click on 'Merge selected records' - Choose the biblio which will be kept, all others will be deleted - On the next page you have all biblios you chose in tabs (left side of the screen) and the preview of result (right side) - Pick some fields or subfields from records that will be deleted or delete some fields from reference record. - Click on 'Merge', if there is no errors you are redirected to the biblio view. --- Koha/Util/MARC.pm | 37 +-- cataloguing/merge.pl | 282 +++++++------ installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 14 + .../prog/en/includes/merge-record.inc | 426 +++++++++++--------- .../en/modules/admin/preferences/cataloguing.pref | 9 + .../prog/en/modules/cataloguing/merge.tt | 374 +++++++++++++++--- .../prog/en/modules/virtualshelves/shelves.tt | 20 +- 8 files changed, 753 insertions(+), 410 deletions(-) --- a/Koha/Util/MARC.pm +++ a/Koha/Util/MARC.pm @@ -46,16 +46,11 @@ sub createMergeHash { if ( !defined($tagslib) || $tagslib->{$fieldtag}->{'@'}->{'tab'} >= 0 ) { - push @array, - { - field => [ - { - tag => $fieldtag, - key => _createKey(), - value => $field->data(), - } - ] - }; + push @array, { + tag => $fieldtag, + key => _createKey(), + value => $field->data(), + }; } } else { @@ -65,12 +60,11 @@ sub createMergeHash { if ( !defined($tagslib) || $tagslib->{$fieldtag}->{ @$subfield[0] }->{'tab'} >= 0 ) { - push @subfield_array, - { + push @subfield_array, { subtag => @$subfield[0], subkey => _createKey(), value => @$subfield[1], - }; + }; } } @@ -78,17 +72,12 @@ sub createMergeHash { if ( ( !defined($tagslib) || $tagslib->{$fieldtag}->{'tab'} >= 0 ) && @subfield_array ) { - push @array, - { - field => [ - { - tag => $fieldtag, - key => _createKey(), - indicator1 => $field->indicator(1), - indicator2 => $field->indicator(2), - subfield => [@subfield_array], - } - ] + push @array, { + tag => $fieldtag, + key => _createKey(), + indicator1 => $field->indicator(1), + indicator2 => $field->indicator(2), + subfield => [@subfield_array], }; } --- a/cataloguing/merge.pl +++ a/cataloguing/merge.pl @@ -1,6 +1,5 @@ #!/usr/bin/perl - # Copyright 2009 BibLibre # Parts Copyright Catalyst IT 2011 # @@ -19,8 +18,8 @@ # with Koha; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -use strict; -#use warnings; FIXME - Bug 2505 +use Modern::Perl; + use CGI; use C4::Output; use C4::Auth; @@ -33,14 +32,14 @@ use C4::Acquisition qw/ModOrder GetOrdersByBiblionumber/; use Koha::MetadataRecord; my $input = new CGI; -my @biblionumber = $input->param('biblionumber'); +my @biblionumbers = $input->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, @@ -54,28 +53,41 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( if ($merge) { my $dbh = C4::Context->dbh; - my $sth; # Creating a new record from the html code my $record = TransformHtmlToMarc( $input ); - my $tobiblio = $input->param('biblio1'); - my $frombiblio = $input->param('biblio2'); + 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($ref_biblionumber)->leader()); 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 - # Also moving orders from the other record to the reference record, only if the order is linked to an item of the other record - my $itemnumbers = get_itemnumbers_of($frombiblio); - foreach my $itloop ($itemnumbers->{$frombiblio}) { - foreach my $itemnumber (@$itloop) { - my $res = MoveItemFromBiblio($itemnumber, $frombiblio, $tobiblio); + foreach my $biblionumber (@biblionumbers) { + my $itemnumbers = get_itemnumbers_of($biblionumber); + foreach my $itemnumber (@{ $itemnumbers->{$biblionumber} }) { + my $res = MoveItemFromBiblio($itemnumber, $biblionumber, $ref_biblionumber); if (not defined $res) { push @notmoveditems, $itemnumber; } @@ -87,137 +99,165 @@ if ($merge) { 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 $report_header = {}; + foreach my $biblionumber ($ref_biblionumber, @biblionumbers) { + # build report + my $marcrecord = GetMarcBiblio($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(); + my %subfields; + 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; } - # Moving serials - $sth = $dbh->prepare("UPDATE serial SET biblionumber = ? WHERE biblionumber = ?"); - $sth->execute($tobiblio, $frombiblio); + 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); + } - # TODO : Moving reserves + # Moving serials + $sth_serial->execute($ref_biblionumber, $biblionumber); # Moving orders (orders linked to items of frombiblio have already been moved by MoveItemFromBiblio) - my @allorders = GetOrdersByBiblionumber($frombiblio); - my @tobiblioitem = GetBiblioItemByBiblioNumber ($tobiblio); + my @allorders = GetOrdersByBiblionumber($biblionumber); + my @tobiblioitem = GetBiblioItemByBiblioNumber ($ref_biblionumber); my $tobiblioitem_biblioitemnumber = $tobiblioitem [0]-> {biblioitemnumber }; foreach my $myorder (@allorders) { - $myorder->{'biblionumber'} = $tobiblio; + $myorder->{'biblionumber'} = $ref_biblionumber; ModOrder ($myorder); # TODO : add error control (in ModOrder?) } - # Deleting the other record + # Deleting the other records if (scalar(@errors) == 0) { - # Move holds - MergeHolds($dbh,$tobiblio,$frombiblio); - my $error = DelBiblio($frombiblio); - push @errors, $error if ($error); + # Move holds + MergeHolds($dbh, $ref_biblionumber, $biblionumber); + my $error = DelBiblio($biblionumber); + push @errors, $error if ($error); } +} # Parameters $template->param( - result => 1, - biblio1 => $input->param('biblio1') + result => 1, + report_records => \@report_records, + report_header => $report_header, + ref_biblionumber => $input->param('ref_biblionumber') ); #------------------------- # Show records to merge #------------------------- } else { - my $mergereference = $input->param('mergereference'); - my $biblionumber = $input->param('biblionumber'); - - if (scalar(@biblionumber) != 2) { - push @errors, { code => "WRONG_COUNT", value => scalar(@biblionumber) }; - } - else { - my $data1 = GetBiblioData($biblionumber[0]); - my $record1 = GetMarcBiblio($biblionumber[0]); - - my $data2 = GetBiblioData($biblionumber[1]); - my $record2 = GetMarcBiblio($biblionumber[1]); - - # Checks if both records use the same framework - my $frameworkcode1 = &GetFrameworkCode($biblionumber[0]); - my $frameworkcode2 = &GetFrameworkCode($biblionumber[1]); - - - my $subtitle1 = GetRecordValue('subtitle', $record1, $frameworkcode1); - my $subtitle2 = GetRecordValue('subtitle', $record2, $frameworkcode1); - - if ($mergereference) { - - my $framework; - if ($frameworkcode1 ne $frameworkcode2) { - $framework = $input->param('frameworkcode') - or push @errors, "Famework not selected."; + 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); + my $frameworkcode = GetFrameworkCode($biblionumber); + my $recordObj = new Koha::MetadataRecord({'record' => $marcrecord, schema => $marcflavour}); + my $record = { + biblionumber => $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 { - $framework = $frameworkcode1; + push @records, $record; } - - # Getting MARC Structure - my $tagslib = GetMarcStructure(1, $framework); - - my $notreference = ($biblionumber[0] == $mergereference) ? $biblionumber[1] : $biblionumber[0]; - - # Creating a loop for display - - my $recordObj1 = new Koha::MetadataRecord({ 'record' => GetMarcBiblio($mergereference), 'schema' => lc C4::Context->preference('marcflavour') }); - my $recordObj2 = new Koha::MetadataRecord({ 'record' => GetMarcBiblio($notreference), 'schema' => lc C4::Context->preference('marcflavour') }); - - my @record1 = $recordObj1->createMergeHash($tagslib); - my @record2 = $recordObj2->createMergeHash($tagslib); - - # Parameters - $template->param( - biblio1 => $mergereference, - biblio2 => $notreference, - mergereference => $mergereference, - record1 => @record1, - record2 => @record2, - framework => $framework, - ); } - else { + 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 { + 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, - biblio1 => $biblionumber[0], - biblio2 => $biblionumber[1], - title1 => $data1->{'title'}, - subtitle1 => $subtitle1, - title2 => $data2->{'title'}, - subtitle2 => $subtitle2 + $template->param( + choosereference => 1, + records => \@records, + ); + + my $frameworks = getframeworks; + my @frameworkselect; + foreach my $thisframeworkcode ( keys %$frameworks ) { + my %row = ( + value => $thisframeworkcode, + frameworktext => $frameworks->{$thisframeworkcode}->{'frameworktext'}, ); - if ($frameworkcode1 ne $frameworkcode2) { - my $frameworks = getframeworks; - my @frameworkselect; - foreach my $thisframeworkcode ( keys %$frameworks ) { - my %row = ( - value => $thisframeworkcode, - frameworktext => $frameworks->{$thisframeworkcode}->{'frameworktext'}, - ); - if ($frameworkcode1 eq $thisframeworkcode){ - $row{'selected'} = 1; - } - push @frameworkselect, \%row; - } - $template->param( - frameworkselect => \@frameworkselect, - frameworkcode1 => $frameworkcode1, - frameworkcode2 => $frameworkcode2, - ); - } + push @frameworkselect, \%row; } + $template->param( + frameworkselect => \@frameworkselect, + ); } } @@ -228,11 +268,3 @@ if (@errors) { output_html_with_http_headers $input, $cookie, $template->output; exit; - -=head1 FUNCTIONS - -=cut - -# ------------------------ -# Functions -# ------------------------ --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -427,3 +427,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES(' INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('UseCourseReserves', '0', 'Enable the course reserves feature.', NULL, 'YesNo'); INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacHoldNotes',0,'Show hold notes on OPAC','','YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CalculateFinesOnReturn','1','Switch to control if overdue fines are calculated on return or not', '', 'YesNo'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('MergeReportFields','','Displayed fields for deleted MARC records after merge',NULL,'Free'); --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -6991,6 +6991,20 @@ if ( CheckVersion($DBversion) ) { } + + + +$DBversion = "3.13.00.XXX"; +if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { + $dbh->do(" + INSERT INTO systempreferences (variable,value,explanation,options,type) + VALUES('MergeReportFields','','Displayed fields for deleted MARC records after merge',NULL,'Free'); + "); + print "Upgrade to $DBversion done (Add system preference 'MergeReportFields')\n"; + SetVersion($DBversion); +} + + =head1 FUNCTIONS =head2 TableExists($table) --- a/koha-tmpl/intranet-tmpl/prog/en/includes/merge-record.inc +++ a/koha-tmpl/intranet-tmpl/prog/en/includes/merge-record.inc @@ -1,219 +1,251 @@ [% BLOCK sourcetab %] -
- [% IF ( records ) %] - -
- -
- [% END %] -
+
+
+ +
+
[% END %] + [% BLOCK mergejs %] - // Creating tabs - $("#tabs").tabs(); - - // Toggle a field / subfield - function toggleField(pField) { - - // Getting the key of the clicked checkbox - var ckid = $(pField).attr("id"); - var tab = ckid.split('_'); - var source = tab[1]; // From which record the click came from - var key = tab[2]; - var type = $(pField).attr("class"); - - // Getting field/subfield - var field; - var subfield; - if (type == "subfieldpick") { - - field = $(pField).parent().parent().parent().find("span.field").text(); - subfield = $(pField).parent().find("span.subfield").text(); - } else { - - field = $(pField).parent().find("span.field").text(); - } - - // If the field has just been checked - if (pField.checked) { - - // We check for repeatability - var canbeadded = true; - if (type == "subfieldpick") { - var repeatable = 1; - var alreadyexists = 0; - if (tagslib[field] && tagslib[field][subfield]) { - repeatable = tagslib[field][subfield].repeatable; // Note : we can't use the dot notation here (tagslib.021) because the key is a number - // TODO : Checking for subfields - } - } else { - if (tagslib[field]) { - repeatable = tagslib[field].repeatable; - alreadyexists = $("#resultul span.field:contains(" + field + ")"); - if (repeatable == 0 && alreadyexists.length != 0) { - canbeadded = false; - } - } - } - // If the field is not repeatable, we check if it already exists in the result table - if (canbeadded == false) { - alert(_("The field is non-repeatable and already exists in the destination record. Therefore, you cannot add it.")); - pField.checked = 0; - } else { - - // Cloning the field or subfield we picked - var clone = $(pField).parent().clone(); - - // Removing the checkboxes from it - $(clone).find("input.subfieldpick, input.fieldpick").each(function() { - $(this).remove(); - }); - - - // If we are a subfield - if (type == "subfieldpick") { - // then we need to find who is our parent field... - fieldkey = $(pField).parent().parent().parent().attr("id"); - - // Find where to add the subfield - - // First, check if the field is not already in the destination record - if ($("#resultul li#" + fieldkey).length > 0) { - // If so, we add our field to it - $("#resultul li#" + fieldkey + " ul").append(clone); - } else { - // If not, we add the subfield to the first matching field - var where = 0; - $("#resultul li span.field").each(function() { - if (where == 0 && $(this).text() == field) { - where = this; - } - }); - - // If there is no matching field in the destination record - if (where == 0) { - - // TODO: - // We select the whole field and removing non-selected subfields, instead of... - - // Alerting the user - alert(_("This subfield cannot be added: there is no") + " " + field + " " + _("field in the destination record.")); - pField.checked = false; - - } else { - $(where).nextAll("ul").append(clone); - } - - } - - - - } else { - // If we are a field - var where = 0; - // Find where to add the field - $("#resultul li span.field").each(function() { - if (where == 0 && $(this).text() > field) { - where = this; - } - }); - - $(where).parent().before(clone); - } - } - } else { - - // Else, we remove it from the results tab - $("ul#resultul li#k" + key).remove(); - } -} - - - // When a field is checked / unchecked - $('input.fieldpick').click(function() { - toggleField(this); - // (un)check all subfields - var ischecked = this.checked; - $(this).parent().find("input.subfieldpick").each(function() { - this.checked = ischecked; - }); - }); - - // When a field or subfield is checked / unchecked - $("input.subfieldpick").click(function() { - toggleField(this); - }); + // Creating tabs + $("#tabs").tabs(); + + // Toggle a field / subfield + function toggleField(pField) { + // Getting the key of the clicked checkbox + var ckid = $(pField).attr("id"); + var tab = ckid.split('_'); + var source = tab[1]; // From which record the click came from + var key = tab[2]; + var type = $(pField).attr("class"); + + // Getting field/subfield + var field; + var subfield; + if (type == "subfieldpick") { + field = $(pField).parent().parent().parent().find("span.field").text(); + subfield = $(pField).parent().find("span.subfield").text(); + } else { + field = $(pField).parent().find("span.field").text(); + } + + // If the field has just been checked + if (pField.checked) { + // We check for repeatability + var canbeadded = true; + if (type == "subfieldpick") { + var repeatable = 1; + var alreadyexists = 0; + if (tagslib[field] && tagslib[field][subfield]) { + // Note : we can't use the dot notation here (tagslib.021) + // because the key is a number + repeatable = tagslib[field][subfield].repeatable; + if (repeatable == 0) { + canbeadded = false; + $("#resultul span.field:contains(" + field + ")") + .each(function() { + if ($(this).parent() + .find("span.subfield:contains(" + subfield + ")") + .length == 0) + { + canbeadded = true; + } + }); + } + } + } else { + if (tagslib[field]) { + repeatable = tagslib[field].repeatable; + alreadyexists = $("#resultul span.field:contains(" + field + ")"); + if (repeatable == 0 && alreadyexists.length != 0) { + canbeadded = false; + } + } + } + // If the field is not repeatable, we check if it already exists in the result table + if (canbeadded == false) { + var field_or_subfield = (type == "subfieldpick") ? _("subfield") : _("field"); + alert(_("The " + field_or_subfield + " is non-repeatable and already exists in the destination record. Therefore, you cannot add it.")); + pField.checked = 0; + } else { + // Cloning the field or subfield we picked + var clone = $(pField).parent().clone(); + + // Removing the checkboxes from it + $(clone).find("input.subfieldpick, input.fieldpick").each(function() { + $(this).remove(); + }); + $(clone).find('label').each(function() { + $(this).replaceWith($(this).contents()); + }); + + // If we are a subfield + if (type == "subfieldpick") { + // then we need to find who is our parent field... + fieldkey = $(pField).parent().parent().parent().attr("id"); + + // Find where to add the subfield + + // First, check if the field is not already in the destination record + if ($("#resultul li#" + fieldkey).length > 0) { + // If so, we add our field to it + $("#resultul li#" + fieldkey + " ul").append(clone); + } else { + // If not, we add the subfield to the first matching field + var where = 0; + $("#resultul li span.field").each(function() { + if (where == 0 && $(this).text() == field) { + where = this; + } + }); + + // If there is no matching field in the destination record + if (where == 0) { + // TODO: + // We select the whole field and removing non-selected subfields, instead of... + + // Alerting the user + alert(_("This subfield cannot be added: there is no " + field + " field in the destination record.")); + pField.checked = false; + + } else { + $(where).nextAll("ul").append(clone); + } + } + } else { + // If we are a field + var where = 0; + // Find where to add the field + $("#resultul li span.field").each(function() { + if (where == 0 && $(this).text() > field) { + where = this; + } + }); + if (where) { + $(where).parent().before(clone); + } else { + $("#resultul").prepend(clone); + } + } + } + } else { + // Else, we remove it from the results tab + $("ul#resultul li#k" + key).remove(); + } + } + + // Check all checkboxes in first tab, and uncheck all others to avoid + // inconsistencies from a page refresh. + $('#tabs div#tabrecord[% ref_biblionumber %]').find('input[type="checkbox"]').attr('checked', true); + $('#tabs > div:not("#tabrecord[% ref_biblionumber %]")').find('input[type="checkbox"]').removeAttr('checked'); + + // When a field is checked / unchecked + $('input.fieldpick').click(function() { + toggleField(this); + // (un)check all subfields + var ischecked = this.checked; + $(this).parent().find("input.subfieldpick").each(function() { + this.checked = ischecked; + }); + }); + + // When a field or subfield is checked / unchecked + $("input.subfieldpick").click(function() { + toggleField(this); + }); [% END %] + [% BLOCK mergesource %]

Source records

- [% PROCESS sourcetab records=record1 recordnumber=1 defaultrecord=1 %] - [% PROCESS sourcetab records=record2 recordnumber=2 defaultrecord=0 %] + [% IF ( sourcerecords.size ) %] + [% FOREACH record IN sourcerecords %] + [% PROCESS sourcetab tabrecord=record %] + [% END %] + [% END %]
[% END %] + [% BLOCK mergetarget %]

Destination record

-
+
[% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref @@ -176,3 +176,12 @@ Cataloging: - pref: NotesBlacklist class: multi - note fields in title notes separator (OPAC record details) and in the description separator (Staff client record details). The fields should appear separated with commas and according with the Koha MARC format (eg 3.. for UNIMARC, 5.. for MARC21) + - + - pref: MergeReportFields + - "fields to display for deleted records after merge" + - "
example: '001,245ab,600'" + - "displays:" + - "