@@ -, +, @@ the additional frameworks, the mapping in Default. 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'; biblio.author again in that framework. 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. add or receive an order as usual. 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). --- 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 --- a/Koha/MarcSubfieldStructures.pm +++ a/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 --- a/installer/data/mysql/atomicupdate/bug19096.perl +++ a/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"; +} --- a/t/db_dependent/Koha/MarcSubfieldStructures.t +++ a/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; --