From 4d7e36e977b0305f5f6c4a0650f9b7fdc5974e39 Mon Sep 17 00:00:00 2001 From: Marcel de Rooy Date: Thu, 17 Aug 2017 10:57:28 +0200 Subject: [PATCH] Bug 19096: Add dbrev to sync kohafield in all frameworks The dbrev will use two new routines in MarcSubfieldStructures: [1] get_kohafield_exceptions is used to report deviating kohafields in the additional frameworks, [2] sync_kohafield is used to reset kohafield in the other frameworks to the mapping in Default. Test plan: Unit test and database revision: [1] Run t/db_dependent/Koha/MarcSubfieldStructures.t [2] Verify that your Default 100a is mapped to biblio.author. Go to another framework and clear the mapping via mysql command line: UPDATE marc_subfield_structure SET kohafield=NULL WHERE frameworkcode=[your_framework] AND tagfield='100' AND tagsubfield='a'; [3] Run the db revision. It should report that 100a was adjusted. [4] Check in admin/marc_subfield_structure that your 100a is mapped to biblio.author again in that framework. Additional interface testing (ensuring that the changes on this report do not interfere with multiple mappings): [5] Make two mappings for copyrightdate: 260c and 264a. And make two mappings for biblioitems.pages: 300a and say 300g. Toggle with some field values in those fields in the cataloging editor and verify the contents of biblio.copyrightdate and biblioitems.pages. The former should contain one year (due to additional logic) and the latter should contain A | B if both fields are filled. Remove the mapping for 300g. [6] Set AcqCreateItem to ordering or placing. Verify that you can still add or receive an order as usual. [7] Add a mapping for itemcallnumber to 952f (this should remove the one for coded_location_qualifier). This is very unusual but serves well in testing multiple mappings for items. Add or receive an order (fill 952f and 952o) with same and/or different values. Verify the contents of items.callnumber. (Check with regular item editor; see note.) Do a similar edit in the regular item editor. Note: You should expect to see A | B in both 952f and 925o if both fields are filled with a different value. Set items.coded_location_qualifier back to 952f in koha2marclinks. Note: When AcqCreateItem==ordering, you will not see A|B in the callno field when adding an item on neworderempty.pl. But when you submit the main form, addorder.pl is called. At that time an item is created and you will see that A|B is in both fields (952f and 952o). Signed-off-by: Josef Moravec Signed-off-by: Kyle M Hall --- Koha/MarcSubfieldStructures.pm | 65 ++++++++++++++++++++++++- installer/data/mysql/atomicupdate/bug19096.perl | 20 ++++++++ t/db_dependent/Koha/MarcSubfieldStructures.t | 52 +++++++++++++++++++- 3 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug19096.perl diff --git a/Koha/MarcSubfieldStructures.pm b/Koha/MarcSubfieldStructures.pm index c2f5656..d9c839f 100644 --- a/Koha/MarcSubfieldStructures.pm +++ b/Koha/MarcSubfieldStructures.pm @@ -20,7 +20,8 @@ use Modern::Perl; use Carp; use Koha::Database; - +use Koha::BiblioFrameworks; +use Koha::Caches; use Koha::MarcSubfieldStructure; use base qw(Koha::Objects); @@ -31,10 +32,70 @@ Koha::MarcSubfieldStructures - Koha MarcSubfieldStructure Object set class =head1 API -=head2 Class Methods +=head2 Class methods + +=head3 sync_kohafield + + Synchronizes the used kohafields in the Default framework to all other + frameworks. =cut +sub sync_kohafield { + my ( $class ) = @_; + + # Clear the destination frameworks first + Koha::MarcSubfieldStructures->search({ frameworkcode => { '>', q{} }, kohafield => { '>', q{} } })->update({ kohafield => undef }); + + # Now copy from Default + my $rs = Koha::MarcSubfieldStructures->search({ frameworkcode => q{}, kohafield => { '>', q{} } }); + while( my $rec = $rs->next ) { + Koha::MarcSubfieldStructures->search({ frameworkcode => { '>', q{} }, tagfield => $rec->tagfield, tagsubfield => $rec->tagsubfield })->update({ kohafield => $rec->kohafield }); + } + + # Clear the cache + my @fw = Koha::BiblioFrameworks->search({ frameworkcode => { '>', q{} } })->get_column('frameworkcode'); + foreach( @fw ) { + Koha::Caches->get_instance->clear_from_cache( "MarcSubfieldStructure-$_" ); + } + Koha::Caches->get_instance->clear_from_cache("default_value_for_mod_marc-"); +} + +=head3 get_kohafield_exceptions + + Get all kohafield exceptions (deviations from the Default framework) + + Returns an arrayref of [ framework, field, subfield, kohafield ] + where kohafield is the original (deviating) value. + +=cut + +sub get_kohafield_exceptions { + my ( $class, $params ) = @_; + + # Too bad that DBIx is not very helpful here + my $default = Koha::MarcSubfieldStructures->search({ + frameworkcode => q{}, + kohafield => { '>' => '' }, + }); + my $other = Koha::MarcSubfieldStructures->search({ + frameworkcode => { '!=' => q{} }, + }, { order_by => { -asc => [ qw/tagfield tagsubfield/ ] } }); + + # Compare + my @return; + while( my $rec = $other->next ) { + my @tags = ( $rec->tagfield, $rec->tagsubfield ); + my $defa = $default->find( q{}, @tags ); + if( $rec->kohafield ) { + push @return, [ $rec->frameworkcode, @tags, $rec->kohafield ] if !$defa || !$defa->kohafield || $defa->kohafield ne $rec->kohafield; + } else { + push @return, [ $rec->frameworkcode, @tags, q{} ] if $defa && $defa->kohafield; + } + } + return \@return; +} + =head3 type =cut diff --git a/installer/data/mysql/atomicupdate/bug19096.perl b/installer/data/mysql/atomicupdate/bug19096.perl new file mode 100644 index 0000000..72a2c46 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug19096.perl @@ -0,0 +1,20 @@ +$DBversion = 'XXX'; # will be replaced by the RM +if( CheckVersion( $DBversion ) ) { + require Koha::MarcSubfieldStructures; + + my $diff = Koha::MarcSubfieldStructures->get_kohafield_exceptions; + if( @$diff ) { + print "WARNING: The Default framework is now considered as authoritative for Koha to MARC mappings. We have found that your additional frameworks contained ".@$diff." mapping(s) that deviate from the standard mappings. Please look at the following list and consider if you need to add them again in Default (possibly as a second mapping).\n"; + foreach( @$diff ) { + print "Field ". $_->[1].$_->[2]. " in framework ". $_->[0]. ": "; + if( $_->[3] ) { + print "Mapping to ". $_->[3]. " has been adjusted.\n"; + } else { + print "Mapping has been reset.\n"; + } + } + Koha::MarcSubfieldStructures->sync_kohafield; + } + SetVersion( $DBversion ); + print "Upgrade to $DBversion done (Bug 19096 - Make Default authoritative for Koha to MARC mappings)\n"; +} diff --git a/t/db_dependent/Koha/MarcSubfieldStructures.t b/t/db_dependent/Koha/MarcSubfieldStructures.t index d65f4cc..c962474 100644 --- a/t/db_dependent/Koha/MarcSubfieldStructures.t +++ b/t/db_dependent/Koha/MarcSubfieldStructures.t @@ -19,7 +19,7 @@ use Modern::Perl; -use Test::More tests => 1; +use Test::More tests => 2; use Koha::MarcSubfieldStructure; use Koha::MarcSubfieldStructures; @@ -56,4 +56,54 @@ subtest 'Trivial tests' => sub { is( Koha::MarcSubfieldStructures->search->count, $nb_of_fields + 1, 'Delete should have deleted the field' ); }; +subtest 'get_kohafield_exceptions / sync_kohafield' => sub { + plan tests => 14; + + # start from scratch again, add a new framework + Koha::MarcSubfieldStructures->delete; + my $builder = t::lib::TestBuilder->new; + my $fwc = $builder->build({ source => 'BiblioFramework' })->{frameworkcode}; + + # 100a mapped in Default, unmapped in other + Koha::MarcSubfieldStructure->new({ frameworkcode => q{}, tagfield => '100', tagsubfield => 'a', kohafield => 'biblio.author' })->store; + Koha::MarcSubfieldStructure->new({ frameworkcode => $fwc, tagfield => '100', tagsubfield => 'a', kohafield => '' })->store; + my $res = Koha::MarcSubfieldStructures->get_kohafield_exceptions; + is( @$res, 1, 'Found one exception' ); + is( $res->[0]->[1] . $res->[0]->[2], '100a', '100a was reported' ); + Koha::MarcSubfieldStructures->sync_kohafield; + $res = Koha::MarcSubfieldStructures->get_kohafield_exceptions; + is( @$res, 0, 'Found no exceptions after syncing' ); + is( Koha::MarcSubfieldStructures->find($fwc, '100', 'a')->kohafield, + 'biblio.author', '100a in added framework adjusted' ); + + # 245a unmapped in Default, mapped in other + # 300a not in Default, mapped in other + Koha::MarcSubfieldStructure->new({ frameworkcode => q{}, tagfield => '245', tagsubfield => 'a', kohafield => q{} })->store; + Koha::MarcSubfieldStructure->new({ frameworkcode => $fwc, tagfield => '245', tagsubfield => 'a', kohafield => 'biblio.title' })->store; + Koha::MarcSubfieldStructure->new({ frameworkcode => $fwc, tagfield => '300', tagsubfield => 'a', kohafield => 'biblioitems.pages' })->store; + $res = Koha::MarcSubfieldStructures->get_kohafield_exceptions; + is( @$res, 2, 'Found two exceptions' ); + is( $res->[0]->[1] . $res->[0]->[2], '245a', '245a was reported' ); + is( $res->[1]->[1] . $res->[1]->[2], '300a', '300a was reported' ); + Koha::MarcSubfieldStructures->sync_kohafield; + $res = Koha::MarcSubfieldStructures->get_kohafield_exceptions; + is( @$res, 0, 'Found no exceptions after syncing again' ); + is( Koha::MarcSubfieldStructures->find($fwc, '245', 'a')->kohafield, + undef, '245a in added framework cleared' ); + is( Koha::MarcSubfieldStructures->find($fwc, '300', 'a')->kohafield, + undef, '300a in added framework cleared' ); + + # 300a mapped in Default to another field than in other framework + Koha::MarcSubfieldStructure->new({ frameworkcode => q{}, tagfield => '300', tagsubfield => 'a', kohafield => 'something_else' })->store; + Koha::MarcSubfieldStructures->find($fwc, '300', 'a')->update({ kohafield => 'biblioitems.pages' }); + $res = Koha::MarcSubfieldStructures->get_kohafield_exceptions; + is( @$res, 1, 'Found one exception' ); + is( $res->[0]->[1] . $res->[0]->[2], '300a', '300a was reported again' ); + Koha::MarcSubfieldStructures->sync_kohafield; + $res = Koha::MarcSubfieldStructures->get_kohafield_exceptions; + is( @$res, 0, 'Found no exceptions after third syncing' ); + is( Koha::MarcSubfieldStructures->find($fwc, '300', 'a')->kohafield, + 'something_else', '300a in added framework adjusted' ); +}; + $schema->storage->txn_rollback; -- 2.10.2