View | Details | Raw Unified | Return to bug 31112
Collapse All | Expand All

(-)a/C4/Circulation.pm (-58 / +27 lines)
Lines 2945-3023 sub CanBookBeRenewed { Link Here
2945
        }
2945
        }
2946
    }
2946
    }
2947
2947
2948
    # Note: possible_reserves will contain all title level holds on this bib and item level
2948
    if ( C4::Context->preference('AllowRenewalIfOtherItemsAvailable') && !Koha::Holds->search( { itemnumber => $itemnumber, found => undef } )->count()
2949
    # holds on the checked out item
2949
 )
2950
    my ( $resfound, $resrec, $possible_reserves ) = C4::Reserves::CheckReserves($itemnumber);
2951
2952
    # If next hold is non priority, then check if any hold with priority (non_priority = 0) exists for the same biblionumber.
2953
    if ( $resfound && $resrec->{non_priority} ) {
2954
        $resfound = Koha::Holds->search(
2955
            { biblionumber => $resrec->{biblionumber}, non_priority => 0 } )
2956
          ->count > 0;
2957
    }
2958
2959
2960
2961
    # This item can fill one or more unfilled reserve, can those unfilled reserves
2962
    # all be filled by other available items?
2963
    if ( $resfound
2964
        && C4::Context->preference('AllowRenewalIfOtherItemsAvailable') && !Koha::Holds->search( { itemnumber => $itemnumber, found => undef } )->count() )
2965
    {
2950
    {
2951
        my $biblio = Koha::Biblios->find($item->biblionumber);
2952
        my @possible_holds = $biblio->current_holds->unfilled->search({non_priority => 0})->as_list;
2953
2966
        # Get all other items that could possibly fill reserves
2954
        # Get all other items that could possibly fill reserves
2967
        # FIXME We could join reserves (or more tables) here to eliminate some checks later
2955
        # FIXME We could join reserves (or more tables) here to eliminate some checks later
2968
        my $items = Koha::Items->search({
2956
        my @other_items = Koha::Items->search({
2969
            biblionumber => $resrec->{biblionumber},
2957
            biblionumber => $biblio->biblionumber,
2970
            onloan       => undef,
2958
            onloan       => undef,
2971
            notforloan   => 0,
2959
            notforloan   => 0,
2972
            -not         => { itemnumber => $itemnumber }
2960
            -not         => { itemnumber => $itemnumber } })->as_list;
2973
					});
2961
2974
        my $item_count = $items->count();
2975
2976
        # Get all other reserves that could have been filled by this item
2977
        my @borrowernumbers = map { $_->{borrowernumber} } @$possible_reserves;
2978
        # Note: fetching the patrons in this manner means that a patron with 2 holds will
2979
        # not block renewal if one reserve can be satisfied i.e. each patron is checked once
2980
        my $patrons = Koha::Patrons->search({
2981
            borrowernumber => { -in => \@borrowernumbers }
2982
					    });
2983
        my $patron_count = $patrons->count();
2984
2985
        return ( 0, "on_reserve" ) if ($patron_count > $item_count);
2986
        # We cannot possibly fill all reserves if we don't have enough items
2987
2988
        # If we can fill each hold that has been found with the available items on the record
2989
        # then the patron can renew. If we cannot, they cannot renew.
2990
        # FIXME This code does not check whether the item we are renewing can fill
2991
        # any of the existing reserves.
2992
        my $reservable = 0;
2993
        my %matched_items;
2962
        my %matched_items;
2994
        my $seen = 0;
2963
        foreach my $possible_hold (@possible_holds) {
2995
      PATRON: while ( my $patron = $patrons->next ) {
2964
            my $fillable = 0;
2996
          # If there is a reserve that cannot be filled we are done
2965
            my $patron_with_reserve = Koha::Patrons->find($possible_hold->borrowernumber);
2997
          return ( 0, "on_reserve" ) if ( $seen > $reservable );
2966
            my $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $item->biblionumber, patron => $patron_with_reserve });
2998
          my $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $item->biblionumber, patron => $patron });
2967
2999
          while ( my $other_item = $items->next ) {
2968
            # FIXME: We are not checking whether the item we are renewing can fill the hold
2969
2970
            foreach my $other_item (@other_items) {
3000
              next if defined $matched_items{$other_item->itemnumber};
2971
              next if defined $matched_items{$other_item->itemnumber};
3001
              next if IsItemOnHoldAndFound( $other_item->itemnumber );
2972
              next if IsItemOnHoldAndFound( $other_item->itemnumber );
3002
              next unless IsAvailableForItemLevelRequest($other_item, $patron, undef, $items_any_available);
2973
              next unless IsAvailableForItemLevelRequest($other_item, $patron_with_reserve, undef, $items_any_available);
3003
              next unless CanItemBeReserved($patron,$other_item,undef,{ignore_hold_counts=>1})->{status} eq 'OK';
2974
              next unless CanItemBeReserved($patron_with_reserve,$other_item,undef,{ignore_hold_counts=>1})->{status} eq 'OK';
3004
              # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
2975
              # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
3005
              # CanItemBeReserved checks 'rules' and 'policies' which means
2976
              # CanItemBeReserved checks 'rules' and 'policies' which means
3006
              # items will fill holds at checkin that are rejected here
2977
              # items will fill holds at checkin that are rejected here
3007
              $reservable++;
2978
              $fillable = 1;
3008
              if ($reservable >= $patron_count) {
3009
                  $resfound = 0;
3010
                  last PATRON;
3011
              }
3012
              $matched_items{$other_item->itemnumber} = 1;
2979
              $matched_items{$other_item->itemnumber} = 1;
3013
              last;
2980
              last;
3014
          }
2981
            }
3015
          $items->reset;
2982
            return ( 0, "on_reserve" ) unless $fillable;
3016
          $seen++;
2983
        }
3017
      }
2984
2985
    } else {
2986
        my ($status, $matched_reserve, $possible_reserves) = CheckReserves($itemnumber);
2987
        return ( 0, "on_reserve" ) if $matched_reserve;
3018
    }
2988
    }
3019
2989
3020
    return ( 0, "on_reserve" ) if $resfound;    # '' when no hold was found
3021
    return ( 0, $auto_renew, { soonest_renew_date => $soonest } ) if $auto_renew =~ 'too_soon';#$auto_renew ne "no" && $auto_renew ne "ok";
2990
    return ( 0, $auto_renew, { soonest_renew_date => $soonest } ) if $auto_renew =~ 'too_soon';#$auto_renew ne "no" && $auto_renew ne "ok";
3022
    $soonest = GetSoonestRenewDate($borrowernumber, $itemnumber);
2991
    $soonest = GetSoonestRenewDate($borrowernumber, $itemnumber);
3023
    if ( $soonest > dt_from_string() ){
2992
    if ( $soonest > dt_from_string() ){
(-)a/t/db_dependent/Circulation.t (-2 / +20 lines)
Lines 420-426 subtest "GetIssuingCharges tests" => sub { Link Here
420
420
421
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
421
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
422
subtest "CanBookBeRenewed tests" => sub {
422
subtest "CanBookBeRenewed tests" => sub {
423
    plan tests => 104;
423
    plan tests => 105;
424
424
425
    C4::Context->set_preference('ItemsDeniedRenewal','');
425
    C4::Context->set_preference('ItemsDeniedRenewal','');
426
    # Generate test biblio
426
    # Generate test biblio
Lines 570-575 subtest "CanBookBeRenewed tests" => sub { Link Here
570
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
570
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
571
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
571
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
572
572
573
574
    # Second biblio-level hold
575
    my $reserve_id = AddReserve(
576
        {
577
            branchcode       => $branch,
578
            borrowernumber   => $reserving_borrowernumber,
579
            biblionumber     => $biblio->biblionumber,
580
            priority         => $priority,
581
            reservation_date => $resdate,
582
            expiration_date  => $expdate,
583
            notes            => $notes,
584
            itemnumber       => $checkitem,
585
            found            => $found,
586
        }
587
    );
588
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
589
    is( $renewokay, 0, 'Renewal not possible when single patron\'s holds exceed the number of available items');
590
    Koha::Holds->find($reserve_id)->delete;
591
573
    # Now let's add an item level hold, we should no longer be able to renew the item
592
    # Now let's add an item level hold, we should no longer be able to renew the item
574
    my $hold = Koha::Database->new()->schema()->resultset('Reserve')->create(
593
    my $hold = Koha::Database->new()->schema()->resultset('Reserve')->create(
575
        {
594
        {
576
- 

Return to bug 31112