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

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

Return to bug 31112