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 <josef.moravec@gmail.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
This commit is contained in:
Lari Taskula 2017-02-10 15:11:17 +02:00 committed by Nick Clemens
parent 118a714c1d
commit bd87407798
3 changed files with 171 additions and 0 deletions

View File

@ -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 );

View File

@ -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 {

View File

@ -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, '');
}