| 
      
            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() ){ |