From bfd6697c4e60ba6f6f97db7f535abe8563dd7bf6 Mon Sep 17 00:00:00 2001 From: Alex Arnaud Date: Wed, 9 Dec 2015 11:09:58 +0100 Subject: [PATCH] Bug 15336 - New command-line script: merge_bookseller.pl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test plan (i.e. merge bookseller n° 3 into the n° 6): run perl misc/migration_tools/merge_booksellers.pl -f 3 -t 6 -v -c Check that basketgroups, baskets, contacts, contracts and invoices had moved into bookseller 6. Check that bookseller n° 3 has been deleted. Remove -c (confirm) parameter to run in test mode only. Signed-off-by: Marc Véron --- Koha/Acquisition/Bookseller.pm | 29 ++++++++ misc/migration_tools/merge_vendors.pl | 120 ++++++++++++++++++++++++++++++++++ t/Bookseller.t | 99 +++++++++++++++++++++++++++- t/db_dependent/Bookseller.t | 105 ++++++++++++++++++++++++++++- 4 files changed, 349 insertions(+), 4 deletions(-) create mode 100644 misc/migration_tools/merge_vendors.pl diff --git a/Koha/Acquisition/Bookseller.pm b/Koha/Acquisition/Bookseller.pm index e32b010..d19df66 100644 --- a/Koha/Acquisition/Bookseller.pm +++ b/Koha/Acquisition/Bookseller.pm @@ -26,6 +26,35 @@ sub subscriptions { return Koha::Subscriptions->search( { aqbooksellerid => $self->id } ); } +sub merge_with { + my ($self, $booksellerid) = @_; + + my $result = {}; + + unless ( Koha::Acquisition::Booksellers->find( $booksellerid ) ) { + die("Unknown target bookseller number: $booksellerid"); + } + + foreach my $entity (qw(Aqbasketgroup Aqbasket Aqcontract Aqcontact Aqinvoice Deleteditem Item Subscription)) { + my $rs = Koha::Database->new()->schema->resultset($entity); + + my $foreign_key = $entity eq 'Subscription' ? 'aqbooksellerid' : 'booksellerid'; + $rs = $rs->search({$foreign_key => $self->id }); + + while (my $e = $rs->next) { + $e->set_column($foreign_key, $booksellerid); + $e->update(); + push @{ $result->{$entity} }, $e->id(); + } + } + return $result; +} + +# TODO Move code from ModBookseller +sub update { + die "not implemented yet"; +} + sub _type { return 'Aqbookseller'; } diff --git a/misc/migration_tools/merge_vendors.pl b/misc/migration_tools/merge_vendors.pl new file mode 100644 index 0000000..1471c74 --- /dev/null +++ b/misc/migration_tools/merge_vendors.pl @@ -0,0 +1,120 @@ +#!/usr/bin/perl + +# Copyright 2015 BibLibre +# +# 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 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. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Koha::Acquisition::Bookseller; +use C4::Acquisition; +use C4::Contract; + +use Getopt::Long; +use Pod::Usage; + +my ($help, $verbose, $mergefrom, $mergeto, $confirm); +GetOptions( + 'help|h' => \$help, + 'verbose|v' => \$verbose, + 'from|f:s' => \$mergefrom, + 'to|t:s' => \$mergeto, + 'confirm|c' => \$confirm, +) || pod2usage(1); + +if ($help || !$mergefrom || !$mergeto) { + pod2usage(1); +} + +if ($mergefrom eq $mergeto) { + pod2usage('Source and target vendors should be different.'); +} + +my $schema = Koha::Database->schema; +$schema->storage->txn_begin; + +my $from_vendor = Koha::Acquisition::Booksellers->find( $mergefrom ); +die "Unknown vendor id ($mergefrom)" unless $from_vendor; + +my $report = $from_vendor->merge_with($mergeto); + +if ($confirm) { + $schema->storage->txn_commit; +} +else { + $schema->storage->txn_rollback; +} + +Koha::Acquisition::Booksellers->find($mergefrom)->delete if $confirm; + +if ($verbose) { + print_report($report); +} + +print "Nothing done (test only). Use confirm option to commit changes in database\n" unless $confirm; + +sub print_report { + my $report = shift; + + foreach my $entity (keys %$report) { + my $count = scalar @{ $report->{$entity} }; + my $ids = join(', ', @{ $report->{$entity} }); + print "$entity merged: $count (numbers: $ids)\n"; + } +} + + +=head1 NAME + +merge source vendor (-f) into target vendor (-t) + +=head1 SYNOPSIS + +** WARNING ** This script can delete data. You must only use it if you know what your are doing + +merge_vendors.pl [-h|--help] [-v|--verbose] [-c|--confirm] --from=vendorid --to=vendorid + +=head1 OPTIONS + +=over + +=item B<-h|--help> + +Print a brief help message. + +=item B<--verbose> + + --verbose Show more information on what is done. + +=item B<--confirm> + + --confirm Commit the changes in database. Running without this + parameter is like testing. It is recommanded to run without + --confirm first to be sure of the changes. + +=item B<--from> + + --from= The source vendor identifier that will be merged in + target vendor. + +=item B<--to> + + --to= The target vendor identifier in which merge + source vendor. + +=back + +=cut diff --git a/t/Bookseller.t b/t/Bookseller.t index 360a0ad..6d6aab3 100755 --- a/t/Bookseller.t +++ b/t/Bookseller.t @@ -1,14 +1,107 @@ #!/usr/bin/perl # -# This Koha test module is a stub! +# This Koha test module is a stub! # Add more tests here!!! use strict; use warnings; -use Test::More tests => 1; +use C4::Acquisition qw( GetBasketgroup GetBasket GetInvoice ); +use C4::Contract qw( GetContract ); +use C4::Items qw ( GetItem ); +use C4::Serials qw( GetSubscription ); +use t::lib::TestBuilder; + +use Test::More tests => 14; BEGIN { - use_ok('C4::Bookseller'); + use_ok('Koha::Acquisition::Bookseller'); +} + +my $schema = Koha::Database->schema; +$schema->storage->txn_begin; + +our $builder = t::lib::TestBuilder->new; + +my $bookseller1 = create('Aqbookseller'); +my $booksellerid1 = $bookseller1->{id}; +my $bookseller2 = create('Aqbookseller'); +my $booksellerid2 = $bookseller2->{id}; + +my $bg1 = create('Aqbasketgroup', $booksellerid1); +my $bg2 = create('Aqbasketgroup', $booksellerid1); +my $bg3 = create('Aqbasketgroup', $booksellerid2); + +my $basket1 = create('Aqbasket', $booksellerid1); +my $basket2 = create('Aqbasket', $booksellerid1); + +my $contract = create('Aqcontract', $booksellerid1); + +my $contact = create('Aqcontact', $booksellerid1); + +my $invoice = create('Aqinvoice', $booksellerid1); + +my $deleteditem = create('Deleteditem', $booksellerid1); + +my $item1 = create('Item', $booksellerid1); + +my $subscription = create('Subscription', $booksellerid1); + +my $bookseller = Koha::Acquisition::Bookseller->fetch({id => $booksellerid1}); + +my ($error, $result) = $bookseller->merge_to(345876876); +is($error, "Unknown target bookseller number: 345876876", 'Merge to unknown bookseller return an error' ); + +($error, $result) = $bookseller->merge_to($booksellerid2); +my $expected_result = { + Aqbasketgroup => [$bg1->{id}, $bg2->{id}], + Aqbasket => [$basket1->{basketno}, $basket2->{basketno}], + Aqcontract => [$contract->{contractnumber}], + Aqcontact => [$contact->{id}], + Aqinvoice => [$invoice->{invoiceid}], + Deleteditem => [$deleteditem->{itemnumber}], + Item => [$item1->{itemnumber}], + Subscription => [$subscription->{subscriptionid}] +}; + +is_deeply($result, $expected_result, 'Result should be as expected'); + +is(GetBasketgroup($bg1->{id})->{'booksellerid'}, $booksellerid2, 'Basket group 1 has bookseller 2'); + +is(GetBasketgroup($bg2->{id})->{'booksellerid'}, $booksellerid2, 'Basket group 2 has bookseller 2'); + +is(GetBasketgroup($bg3->{id})->{'booksellerid'}, $booksellerid2, 'Basket group 3 keep bookseller 2'); + +is(GetBasket($basket1->{basketno})->{'booksellerid'}, $booksellerid2, 'Basket 1 has bookseller 2'); + +is(GetBasket($basket2->{basketno})->{'booksellerid'}, $booksellerid2, 'Basket 2 has bookseller 2'); + +is(GetContract({contractnumber => $contract->{contractnumber}})->{'booksellerid'}, $booksellerid2, 'Basket 1 has bookseller 2'); + +is(C4::Bookseller::Contact->fetch($contact->{id})->{'booksellerid'}, $booksellerid2, 'Contact 1 has booksellerid 2'); + +is(GetInvoice($invoice->{invoiceid})->{'booksellerid'}, $booksellerid2, 'Invoice has bookseller 2'); + +my $item = Koha::Database->new()->schema->resultset('Deleteditem') + ->find({itemnumber => $deleteditem->{itemnumber}}); +is($item->get_column('booksellerid'), $booksellerid2, 'Deleted item has bookseller 2'); + +is(GetItem($item1->{itemnumber})->{'booksellerid'}, $booksellerid2, 'Item has bookseller 2'); + +is(GetSubscription($subscription->{subscriptionid})->{'aqbooksellerid'}, $booksellerid2, 'Subscription has bookseller 2'); + +$schema->storage->txn_rollback; + +sub create { + my ($source, $booksellerid) = @_; + + my $build = { source => $source}; + my $foreign_key = $source eq 'Subscription' ? 'aqbooksellerid' : 'booksellerid'; + $build->{value} = {$foreign_key => $booksellerid} if $booksellerid; + + my $entity = $builder->build($build); + + return $entity; } +1; diff --git a/t/db_dependent/Bookseller.t b/t/db_dependent/Bookseller.t index 77cf3ef..f96e35b 100644 --- a/t/db_dependent/Bookseller.t +++ b/t/db_dependent/Bookseller.t @@ -2,7 +2,7 @@ use Modern::Perl; -use Test::More tests => 86; +use Test::More tests => 99; use Test::MockModule; use Test::Warn; @@ -11,9 +11,12 @@ use Koha::DateUtils; use DateTime::Duration; use t::lib::Mocks; use C4::Acquisition; +use C4::Contract qw( GetContract ); +use C4::Items qw ( GetItem ); use C4::Serials; use C4::Budgets; use C4::Biblio; +use t::lib::TestBuilder; use Koha::Acquisition::Booksellers; use Koha::Acquisition::Order; @@ -38,6 +41,8 @@ $schema->storage->txn_begin(); $dbh->{RaiseError} = 1; +our $builder = t::lib::TestBuilder->new; + #Start tests $dbh->do(q|DELETE FROM aqorders|); $dbh->do(q|DELETE FROM aqbasket|); @@ -751,6 +756,91 @@ is( $first_contact->phone, is( $contacts->count, 1, 'Only one contact after modification' ); +my $bookseller1 = create('Aqbookseller'); +my $booksellerid1 = $bookseller1->{id}; +my $bookseller2 = create('Aqbookseller'); +my $booksellerid2 = $bookseller2->{id}; + +my $bg1 = create( 'Aqbasketgroup', $booksellerid1 ); +my $bg2 = create( 'Aqbasketgroup', $booksellerid1 ); +my $bg3 = create( 'Aqbasketgroup', $booksellerid2 ); + +my $basket1 = create( 'Aqbasket', $booksellerid1 ); +my $basket2 = create( 'Aqbasket', $booksellerid1 ); + +my $contract = create( 'Aqcontract', $booksellerid1 ); + +my $contact = create( 'Aqcontact', $booksellerid1 ); + +my $invoice = create( 'Aqinvoice', $booksellerid1 ); + +my $deleteditem = create( 'Deleteditem', $booksellerid1 ); + +my $item1 = create( 'Item', $booksellerid1 ); + +my $subscription = create( 'Subscription', $booksellerid1 ); + +$bookseller = Koha::Acquisition::Booksellers->find( $booksellerid1 ); + +my $result = eval { $bookseller->merge_with(345876876) }; +ok( + $@ =~ /^Unknown target bookseller number: 345876876/, + 'Merge to unknown bookseller return an error' +); + +$result = $bookseller->merge_with($booksellerid2); +my $expected_result = { + Aqbasketgroup => [ $bg1->{id}, $bg2->{id} ], + Aqbasket => [ $basket1->{basketno}, $basket2->{basketno} ], + Aqcontract => [ $contract->{contractnumber} ], + Aqcontact => [ $contact->{id} ], + Aqinvoice => [ $invoice->{invoiceid} ], + Deleteditem => [ $deleteditem->{itemnumber} ], + Item => [ $item1->{itemnumber} ], + Subscription => [ $subscription->{subscriptionid} ] +}; + +is_deeply( $result, $expected_result, 'Result should be as expected' ); + +is( GetBasketgroup( $bg1->{id} )->{'booksellerid'}, + $booksellerid2, 'Basket group 1 has bookseller 2' ); + +is( GetBasketgroup( $bg2->{id} )->{'booksellerid'}, + $booksellerid2, 'Basket group 2 has bookseller 2' ); + +is( GetBasketgroup( $bg3->{id} )->{'booksellerid'}, + $booksellerid2, 'Basket group 3 keep bookseller 2' ); + +is( GetBasket( $basket1->{basketno} )->{'booksellerid'}, + $booksellerid2, 'Basket 1 has bookseller 2' ); + +is( GetBasket( $basket2->{basketno} )->{'booksellerid'}, + $booksellerid2, 'Basket 2 has bookseller 2' ); + +is( + GetContract( { contractnumber => $contract->{contractnumber} } ) + ->{'booksellerid'}, + $booksellerid2, + 'Basket 1 has bookseller 2' +); + +is( Koha::Acquisition::Bookseller::Contacts->find( $contact->{id} )->booksellerid, + $booksellerid2, 'Contact 1 has booksellerid 2' ); + +is( GetInvoice( $invoice->{invoiceid} )->{'booksellerid'}, + $booksellerid2, 'Invoice has bookseller 2' ); + +my $item = Koha::Database->new()->schema->resultset('Deleteditem') + ->find( { itemnumber => $deleteditem->{itemnumber} } ); +is( $item->get_column('booksellerid'), + $booksellerid2, 'Deleted item has bookseller 2' ); + +is( GetItem( $item1->{itemnumber} )->{'booksellerid'}, + $booksellerid2, 'Item has bookseller 2' ); + +is( GetSubscription( $subscription->{subscriptionid} )->{'aqbooksellerid'}, + $booksellerid2, 'Subscription has bookseller 2' ); + #End transaction $schema->storage->txn_rollback(); @@ -774,3 +864,16 @@ sub field_filter { } return $struct; } + +sub create { + my ( $source, $booksellerid ) = @_; + + my $build = { source => $source }; + my $foreign_key = + $source eq 'Subscription' ? 'aqbooksellerid' : 'booksellerid'; + $build->{value} = { $foreign_key => $booksellerid } if $booksellerid; + + my $entity = $builder->build($build); + + return $entity; +} -- 2.1.4