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

(-)a/C4/Circulation.pm (-58 / +27 lines)
Lines 2949-3027 sub CanBookBeRenewed { Link Here
2949
        }
2949
        }
2950
    }
2950
    }
2951
2951
2952
    # Note: possible_reserves will contain all title level holds on this bib and item level
2952
    if ( C4::Context->preference('AllowRenewalIfOtherItemsAvailable') && !Koha::Holds->search( { itemnumber => $itemnumber, found => undef } )->count()
2953
    # holds on the checked out item
2953
 )
2954
    my ( $resfound, $resrec, $possible_reserves ) = C4::Reserves::CheckReserves($itemnumber);
2955
2956
    # If next hold is non priority, then check if any hold with priority (non_priority = 0) exists for the same biblionumber.
2957
    if ( $resfound && $resrec->{non_priority} ) {
2958
        $resfound = Koha::Holds->search(
2959
            { biblionumber => $resrec->{biblionumber}, non_priority => 0 } )
2960
          ->count > 0;
2961
    }
2962
2963
2964
2965
    # This item can fill one or more unfilled reserve, can those unfilled reserves
2966
    # all be filled by other available items?
2967
    if ( $resfound
2968
        && C4::Context->preference('AllowRenewalIfOtherItemsAvailable') && !Koha::Holds->search( { itemnumber => $itemnumber, found => undef } )->count() )
2969
    {
2954
    {
2955
        my $biblio = Koha::Biblios->find($item->biblionumber);
2956
        my @possible_holds = $biblio->current_holds->unfilled->search({non_priority => 0})->as_list;
2957
2970
        # Get all other items that could possibly fill reserves
2958
        # Get all other items that could possibly fill reserves
2971
        # FIXME We could join reserves (or more tables) here to eliminate some checks later
2959
        # FIXME We could join reserves (or more tables) here to eliminate some checks later
2972
        my $items = Koha::Items->search({
2960
        my @other_items = Koha::Items->search({
2973
            biblionumber => $resrec->{biblionumber},
2961
            biblionumber => $biblio->biblionumber,
2974
            onloan       => undef,
2962
            onloan       => undef,
2975
            notforloan   => 0,
2963
            notforloan   => 0,
2976
            -not         => { itemnumber => $itemnumber }
2964
            -not         => { itemnumber => $itemnumber } })->as_list;
2977
					});
2965
2978
        my $item_count = $items->count();
2979
2980
        # Get all other reserves that could have been filled by this item
2981
        my @borrowernumbers = map { $_->{borrowernumber} } @$possible_reserves;
2982
        # Note: fetching the patrons in this manner means that a patron with 2 holds will
2983
        # not block renewal if one reserve can be satisfied i.e. each patron is checked once
2984
        my $patrons = Koha::Patrons->search({
2985
            borrowernumber => { -in => \@borrowernumbers }
2986
					    });
2987
        my $patron_count = $patrons->count();
2988
2989
        return ( 0, "on_reserve" ) if ($patron_count > $item_count);
2990
        # We cannot possibly fill all reserves if we don't have enough items
2991
2992
        # If we can fill each hold that has been found with the available items on the record
2993
        # then the patron can renew. If we cannot, they cannot renew.
2994
        # FIXME This code does not check whether the item we are renewing can fill
2995
        # any of the existing reserves.
2996
        my $reservable = 0;
2997
        my %matched_items;
2966
        my %matched_items;
2998
        my $seen = 0;
2967
        foreach my $possible_hold (@possible_holds) {
2999
      PATRON: while ( my $patron = $patrons->next ) {
2968
            my $fillable = 0;
3000
          # If there is a reserve that cannot be filled we are done
2969
            my $patron_with_reserve = Koha::Patrons->find($possible_hold->borrowernumber);
3001
          return ( 0, "on_reserve" ) if ( $seen > $reservable );
2970
            my $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $item->biblionumber, patron => $patron_with_reserve });
3002
          my $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $item->biblionumber, patron => $patron });
2971
3003
          while ( my $other_item = $items->next ) {
2972
            # FIXME: We are not checking whether the item we are renewing can fill the hold
2973
2974
            foreach my $other_item (@other_items) {
3004
              next if defined $matched_items{$other_item->itemnumber};
2975
              next if defined $matched_items{$other_item->itemnumber};
3005
              next if IsItemOnHoldAndFound( $other_item->itemnumber );
2976
              next if IsItemOnHoldAndFound( $other_item->itemnumber );
3006
              next unless IsAvailableForItemLevelRequest($other_item, $patron, undef, $items_any_available);
2977
              next unless IsAvailableForItemLevelRequest($other_item, $patron_with_reserve, undef, $items_any_available);
3007
              next unless CanItemBeReserved($patron,$other_item,undef,{ignore_hold_counts=>1})->{status} eq 'OK';
2978
              next unless CanItemBeReserved($patron_with_reserve,$other_item,undef,{ignore_hold_counts=>1})->{status} eq 'OK';
3008
              # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
2979
              # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
3009
              # CanItemBeReserved checks 'rules' and 'policies' which means
2980
              # CanItemBeReserved checks 'rules' and 'policies' which means
3010
              # items will fill holds at checkin that are rejected here
2981
              # items will fill holds at checkin that are rejected here
3011
              $reservable++;
2982
              $fillable = 1;
3012
              if ($reservable >= $patron_count) {
3013
                  $resfound = 0;
3014
                  last PATRON;
3015
              }
3016
              $matched_items{$other_item->itemnumber} = 1;
2983
              $matched_items{$other_item->itemnumber} = 1;
3017
              last;
2984
              last;
3018
          }
2985
            }
3019
          $items->reset;
2986
            return ( 0, "on_reserve" ) unless $fillable;
3020
          $seen++;
2987
        }
3021
      }
2988
2989
    } else {
2990
        my ($status, $matched_reserve, $possible_reserves) = CheckReserves($itemnumber);
2991
        return ( 0, "on_reserve" ) if $matched_reserve;
3022
    }
2992
    }
3023
2993
3024
    return ( 0, "on_reserve" ) if $resfound;    # '' when no hold was found
3025
    return ( 0, $auto_renew, { soonest_renew_date => $soonest } ) if $auto_renew =~ 'too_soon';#$auto_renew ne "no" && $auto_renew ne "ok";
2994
    return ( 0, $auto_renew, { soonest_renew_date => $soonest } ) if $auto_renew =~ 'too_soon';#$auto_renew ne "no" && $auto_renew ne "ok";
3026
    $soonest = GetSoonestRenewDate($borrowernumber, $itemnumber);
2995
    $soonest = GetSoonestRenewDate($borrowernumber, $itemnumber);
3027
    if ( $soonest > dt_from_string() ){
2996
    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