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

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

Return to bug 31112