| 
      
            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 | 
              -   | 
               | 
               |