From 0e7f0246baef862478b197fd3cc2ab4a163ccd88 Mon Sep 17 00:00:00 2001 From: Lari Taskula Date: Fri, 10 Feb 2017 15:11:17 +0200 Subject: [PATCH] Bug 18072: Add Koha::Biblio->can_be_transferred This patch adds a new method Koha::Biblio->can_be_transferred. The method checks if at least one of the item of that biblio can be transferred to desired location. This method will be useful for building a smarter pickup location list for holds, because we will be able to hide those libraries to which none of the items of this biblio can be transferred to due to branch transfer limits (see Bug 7614). To test: 1. prove t/db_dependent/Koha/Biblios.t Signed-off-by: Josef Moravec Signed-off-by: Tomas Cohen Arazi --- Koha/Biblio.pm | 90 +++++++++++++++++++++++++++++++++++++++++++ Koha/Item.pm | 4 ++ t/db_dependent/Koha/Biblios.t | 77 ++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) diff --git a/Koha/Biblio.pm b/Koha/Biblio.pm index d226304267..2f9d95235c 100644 --- a/Koha/Biblio.pm +++ b/Koha/Biblio.pm @@ -33,8 +33,12 @@ use Koha::Biblioitems; use Koha::ArticleRequests; use Koha::ArticleRequest::Status; use Koha::IssuingRules; +use Koha::Item::Transfer::Limits; +use Koha::Libraries; use Koha::Subscriptions; +use Koha::Exceptions::Library; + =head1 NAME Koha::Biblio - Koha Biblio Object class @@ -99,6 +103,92 @@ sub can_article_request { return q{}; } +=head3 can_be_transferred + +$biblio->can_be_transferred({ to => $to_library, from => $from_library }) + +Checks if at least one item of a biblio can be transferred to given library. + +This feature is controlled by two system preferences: +UseBranchTransferLimits to enable / disable the feature +BranchTransferLimitsType to use either an itemnumber or ccode as an identifier + for setting the limitations + +Performance-wise, it is recommended to use this method for a biblio instead of +iterating each item of a biblio with Koha::Item->can_be_transferred(). + +Takes HASHref that can have the following parameters: + MANDATORY PARAMETERS: + $to : Koha::Library or branchcode string + OPTIONAL PARAMETERS: + $from : Koha::Library or branchcode string # if given, only items from that + # holdingbranch are considered + +Returns 1 if at least one of the item of a biblio can be transferred +to $to_library, otherwise 0. + +=cut + +sub can_be_transferred { + my ($self, $params) = @_; + + my $to = $params->{'to'}; + my $from = $params->{'from'}; + if (ref($to) ne 'Koha::Library') { + my $tobranchcode = defined $to ? $to : ''; + $to = Koha::Libraries->find($tobranchcode); + unless ($to) { + Koha::Exceptions::Library::NotFound->throw( + error => "Library '$tobranchcode' not found.", + ); + } + } + if ($from && ref($from) ne 'Koha::Library') { + my $frombranchcode = defined $from ? $from : ''; + $from = Koha::Libraries->find($frombranchcode); + unless ($from) { + Koha::Exceptions::Library::NotFound->throw( + error => "Library '$frombranchcode' not found.", + ); + } + } + + return 1 unless C4::Context->preference('UseBranchTransferLimits'); + my $limittype = C4::Context->preference('BranchTransferLimitsType'); + + my $items; + foreach my $item_of_bib ($self->items) { + next unless $item_of_bib->holdingbranch; + next if $from && $from->branchcode ne $item_of_bib->holdingbranch; + return 1 if $item_of_bib->holdingbranch eq $to->branchcode; + my $code = $limittype eq 'itemtype' + ? $item_of_bib->effective_itemtype + : $item_of_bib->ccode; + return 1 unless $code; + $items->{$code}->{$item_of_bib->holdingbranch} = 1; + } + + # At this point we will have a HASHref containing each itemtype/ccode that + # this biblio has, inside which are all of the holdingbranches where those + # items are located at. Then, we will query Koha::Item::Transfer::Limits to + # find out whether a transfer limits for such $limittype from any of the + # listed holdingbranches to the given $to library exist. If at least one + # holdingbranch for that $limittype does not have a transfer limit to given + # $to library, then we know that the transfer is possible. + foreach my $code (keys %{$items}) { + my @holdingbranches = keys %{$items->{$code}}; + return 1 if Koha::Item::Transfer::Limits->search({ + toBranch => $to->branchcode, + fromBranch => { 'in' => \@holdingbranches }, + $limittype => $code + }, { + group_by => [qw/fromBranch/] + })->count == scalar(@holdingbranches) ? 0 : 1; + } + + return 0; +} + =head3 article_request_type my $type = $biblio->article_request_type( $borrower ); diff --git a/Koha/Item.pm b/Koha/Item.pm index 890ebbd127..37610e3c32 100644 --- a/Koha/Item.pm +++ b/Koha/Item.pm @@ -211,6 +211,10 @@ Takes HASHref that can have the following parameters: Returns 1 if item can be transferred to $to_library, otherwise 0. +To find out whether at least one item of a Koha::Biblio can be transferred, please +see Koha::Biblio->can_be_transferred() instead of using this method for +multiple items of the same biblio. + =cut sub can_be_transferred { diff --git a/t/db_dependent/Koha/Biblios.t b/t/db_dependent/Koha/Biblios.t index 5cc286e1c1..0707e0c534 100644 --- a/t/db_dependent/Koha/Biblios.t +++ b/t/db_dependent/Koha/Biblios.t @@ -21,6 +21,8 @@ use Modern::Perl; use Test::More tests => 4; +use C4::Biblio; +use C4::Items; use C4::Reserves; use Koha::DateUtils qw( dt_from_string output_pref ); @@ -131,5 +133,80 @@ subtest 'waiting_or_in_transit' => sub { is($biblio->has_items_waiting_or_intransit, 1, 'Item has transfer'); }; +subtest 'can_be_transferred' => sub { + plan tests => 11; + + t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1); + t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype'); + + my $library1 = $builder->build( { source => 'Branch' } )->{branchcode}; + my $library2 = $builder->build( { source => 'Branch' } )->{branchcode}; + my $library3 = $builder->build( { source => 'Branch' } )->{branchcode}; + my ($bibnum, $title, $bibitemnum) = create_helper_biblio('ONLY1'); + my ($item_bibnum, $item_bibitemnum, $itemnumber) + = AddItem({ homebranch => $library1, holdingbranch => $library1 }, $bibnum); + my $item = Koha::Items->find($itemnumber); + my $biblio = Koha::Biblios->find($bibnum); + + is(Koha::Item::Transfer::Limits->search({ + fromBranch => $library1, + toBranch => $library2, + })->count, 0, 'There are no transfer limits between libraries.'); + ok($biblio->can_be_transferred({ to => $library2 }), + 'Some items of this biblio can be transferred between libraries.'); + + my $limit = Koha::Item::Transfer::Limit->new({ + fromBranch => $library1, + toBranch => $library2, + itemtype => $item->effective_itemtype, + })->store; + is(Koha::Item::Transfer::Limits->search({ + fromBranch => $library1, + toBranch => $library2, + })->count, 1, 'Given we have added a transfer limit that applies for all ' + .'of this biblio\s items,'); + is($biblio->can_be_transferred({ to => $library2 }), 0, + 'None of the items of biblio can no longer be transferred between ' + .'libraries.'); + is($biblio->can_be_transferred({ to => $library2, from => $library1 }), 0, + 'We get the same result also if we pass the from-library parameter.'); + $item->holdingbranch($library2)->store; + is($biblio->can_be_transferred({ to => $library2 }), 1, 'Given one of the ' + .'items is already located at to-library, then the transfer is possible.'); + $item->holdingbranch($library1)->store; + my ($item_bibnum2, $item_bibitemnum2, $itemnumber2) + = AddItem({ homebranch => $library1, holdingbranch => $library3 }, $bibnum); + my $item2 = Koha::Items->find($itemnumber2); + is($biblio->can_be_transferred({ to => $library2 }), 1, 'Given we added ' + .'another item that should have no transfer limits applying on, then ' + .'the transfer is possible.'); + $item2->holdingbranch($library1)->store; + is($biblio->can_be_transferred({ to => $library2 }), 0, 'Given all of items' + .' of the biblio are from same, transfer limited library, then transfer' + .' is not possible.'); + eval { $biblio->can_be_transferred({ to => undef }); }; + is(ref($@), 'Koha::Exceptions::Library::NotFound', 'Exception thrown when no' + .' library given.'); + eval { $biblio->can_be_transferred({ to => 'heaven' }); }; + is(ref($@), 'Koha::Exceptions::Library::NotFound', 'Exception thrown when' + .' invalid library is given.'); + eval { $biblio->can_be_transferred({ to => $library2, from => 'hell' }); }; + is(ref($@), 'Koha::Exceptions::Library::NotFound', 'Exception thrown when' + .' invalid library is given.'); +}; + $schema->storage->txn_rollback; +# Helper method to set up a Biblio. +sub create_helper_biblio { + my $itemtype = shift; + my ($bibnum, $title, $bibitemnum); + my $bib = MARC::Record->new(); + $title = 'Silence in the library'; + $bib->append_fields( + MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'), + MARC::Field->new('245', ' ', ' ', a => $title), + MARC::Field->new('942', ' ', ' ', c => $itemtype), + ); + return ($bibnum, $title, $bibitemnum) = AddBiblio($bib, ''); +} -- 2.15.2 (Apple Git-101.1)