=head2 CanBookBeReserved
- $canReserve = &CanBookBeReserved($borrowernumber, $biblionumber, $branchcode)
+ $canReserve = &CanBookBeReserved($borrowernumber, $biblionumber, $branchcode, $params)
if ($canReserve eq 'OK') { #We can reserve this Item! }
+ $params are passed directly through to CanItemBeReserved
+
See CanItemBeReserved() for possible return values.
=cut
sub CanBookBeReserved{
- my ($borrowernumber, $biblionumber, $pickup_branchcode) = @_;
+ my ($borrowernumber, $biblionumber, $pickup_branchcode, $params) = @_;
my @itemnumbers = Koha::Items->search({ biblionumber => $biblionumber})->get_column("itemnumber");
#get items linked via host records
my $canReserve = { status => '' };
foreach my $itemnumber (@itemnumbers) {
- $canReserve = CanItemBeReserved( $borrowernumber, $itemnumber, $pickup_branchcode );
+ $canReserve = CanItemBeReserved( $borrowernumber, $itemnumber, $pickup_branchcode, $params );
return { status => 'OK' } if $canReserve->{status} eq 'OK';
}
return $canReserve;
=head2 CanItemBeReserved
- $canReserve = &CanItemBeReserved($borrowernumber, $itemnumber, $branchcode)
+ $canReserve = &CanItemBeReserved($borrowernumber, $itemnumber, $branchcode, $params)
if ($canReserve->{status} eq 'OK') { #We can reserve this Item! }
+ current params are 'ignore_found_holds' - if true holds that have been trapped are not counted
+ toward the patron limit, used by checkHighHolds to avoid counting the hold we will fill with the
+ current checkout against the high holds threshold
+
@RETURNS { status => OK }, if the Item can be reserved.
{ status => ageRestricted }, if the Item is age restricted for this borrower.
{ status => damaged }, if the Item is damaged.
=cut
sub CanItemBeReserved {
- my ( $borrowernumber, $itemnumber, $pickup_branchcode ) = @_;
+ my ( $borrowernumber, $itemnumber, $pickup_branchcode, $params ) = @_;
my $dbh = C4::Context->dbh;
my $ruleitemtype; # itemtype of the matching issuing rule
$ruleitemtype = undef;
}
- my $holds = Koha::Holds->search(
- {
- borrowernumber => $borrowernumber,
- biblionumber => $item->biblionumber,
- }
- );
+ my $search_params = {
+ borrowernumber => $borrowernumber,
+ biblionumber => $item->biblionumber,
+ };
+ $search_params->{found} = undef if $params->{ignore_found_holds};
+
+ my $holds = Koha::Holds->search($search_params);
if ( defined $holds_per_record && $holds_per_record ne ''
&& $holds->count() >= $holds_per_record ) {
return { status => "tooManyHoldsForThisRecord", limit => $holds_per_record };
use t::lib::TestBuilder;
use t::lib::Mocks;
-use Test::More tests => 17;
+use Test::More tests => 19;
my $dbh = C4::Context->dbh;
my $schema = Koha::Database->new()->schema();
my $biblio = $builder->build_sample_biblio();
+# The biblio gets 10 items
my @items;
for my $i ( 1 .. 10 ) {
my $item = $builder->build_sample_item(
push( @items, $item );
}
+# Place 6 holds, patrons 0,1,2,3,4,5
for my $i ( 0 .. 5 ) {
my $patron = $patrons[$i];
my $hold = Koha::Hold->new(
)->store();
}
-my $item = pop(@items);
-my $patron = pop(@patrons);
+my $item = shift(@items);
+my $patron = shift(@patrons);
+my $patron_hold = Koha::Holds->find({ borrowernumber => $patron->borrowernumber, biblionumber => $item->biblionumber });
Koha::CirculationRules->set_rules(
{
my $data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 1, "Static mode should exceed threshold" );
-is( $data->{outstanding}, 6, "Should have 5 outstanding holds" );
+is( $data->{outstanding}, 6, "Should have 6 outstanding holds" );
is( $data->{duration}, 1, "Should have duration of 1" );
is( ref( $data->{due_date} ), 'DateTime', "due_date should be a DateTime object" );
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 0, "Should not exceed threshold" );
+
+# Place 6 more holds - patrons 5,6,7,8,9,10
for my $i ( 5 .. 10 ) {
my $patron = $patrons[$i];
my $hold = Koha::Hold->new(
)->store();
}
+# 12 holds, threshold is 1 over 10 holdable items = 11
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 1, "Should exceed threshold of 1" );
+is( $data->{outstanding}, 12, "Should exceed threshold of 1" );
+# 12 holds, threshold is 2 over 10 holdable items = 12 (equal is okay)
t::lib::Mocks::mock_preference( 'decreaseLoanHighHoldsValue', 2 );
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 0, "Should not exceed threshold of 2" );
$unholdable->damaged(-1);
$unholdable->store();
+# 12 holds, threshold is 2 over 9 holdable items = 11
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 1, "Should exceed threshold with one damaged item" );
$unholdable->itemlost(-1);
$unholdable->store();
+# 12 holds, threshold is 2 over 9 holdable items = 11
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 1, "Should exceed threshold with one lost item" );
$unholdable->notforloan(-1);
$unholdable->store();
+# 12 holds, threshold is 2 over 9 holdable items = 11
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 1, "Should exceed threshold with one notforloan item" );
$unholdable->withdrawn(-1);
$unholdable->store();
+# 12 holds, threshold is 2 over 9 holdable items = 11
+$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
+is( $data->{exceeded}, 1, "Should exceed threshold with one withdrawn item" );
+
+$patron_hold->found('F')->store;
+# 11 holds, threshold is 2 over 9 holdable items = 11
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
is( $data->{exceeded}, 1, "Should exceed threshold with one withdrawn item" );
+$patron_hold->found(undef)->store;
t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');