Bug 7688: (follow-up) update test cases to reflect change in NewSubscription()
[koha_fer] / C4 / Reserves.pm
index 813b1cc..f8666a3 100644 (file)
@@ -131,6 +131,8 @@ BEGIN {
         &ReserveSlip
         &ToggleSuspend
         &SuspendAll
+
+        &GetReservesControlBranch
     );
     @EXPORT_OK = qw( MergeHolds );
 }    
@@ -213,6 +215,7 @@ sub AddReserve {
                 'branches'  => $branch_details,
                 'borrowers' => $borrower,
                 'biblio'    => $biblionumber,
+                'items'     => $checkitem,
             },
         ) ) {
 
@@ -253,7 +256,6 @@ sub AddReserve {
 
 sub GetReserve {
     my ($reserve_id) = @_;
-    #warn "C4::Reserves::GetReserve( $reserve_id )";
 
     my $dbh = C4::Context->dbh;
     my $query = "SELECT * FROM reserves WHERE reserve_id = ?";
@@ -511,11 +513,22 @@ sub CanItemBeReserved{
     }
     
     # we check if it's ok or not
-    if( $reservecount < $allowedreserves ){
-        return 1;
-    }else{
+    if( $reservecount >= $allowedreserves ){
         return 0;
     }
+
+    # If reservecount is ok, we check item branch if IndependentBranches is ON
+    # and canreservefromotherbranches is OFF
+    if ( C4::Context->preference('IndependentBranches')
+        and !C4::Context->preference('canreservefromotherbranches') )
+    {
+        my $itembranch = $item->{homebranch};
+        if ($itembranch ne $borrower->{branchcode}) {
+            return 0;
+        }
+    }
+
+    return 1;
 }
 #--------------------------------------------------------------------------------
 =head2 GetReserveCount
@@ -612,7 +625,6 @@ sub GetReserveFee {
     my $sth = $dbh->prepare($query);
     $sth->execute($borrowernumber);
     my $data = $sth->fetchrow_hashref;
-    $sth->finish();
     my $fee      = $data->{'reservefee'};
     my $cntitems = @- > $bibitems;
 
@@ -653,7 +665,6 @@ sub GetReserveFee {
                 }
             }
         }
-        $sth1->finish;
         my $cntitemsfound = @biblioitems;
         my $issues        = 0;
         my $x             = 0;
@@ -789,20 +800,23 @@ sub GetReserveStatus {
     if(defined $found) {
         return 'Waiting'  if $found eq 'W' and $priority == 0;
         return 'Finished' if $found eq 'F';
-        return 'Reserved' if $priority > 0;
     }
-    return '';
-    #empty string here will remove need for checking undef, or less log lines
+
+    return 'Reserved' if $priority > 0;
+
+    return ''; # empty string here will remove need for checking undef, or less log lines
 }
 
 =head2 CheckReserves
 
   ($status, $reserve, $all_reserves) = &CheckReserves($itemnumber);
   ($status, $reserve, $all_reserves) = &CheckReserves(undef, $barcode);
+  ($status, $reserve, $all_reserves) = &CheckReserves($itemnumber,undef,$lookahead);
 
 Find a book in the reserves.
 
 C<$itemnumber> is the book's item number.
+C<$lookahead> is the number of days to look in advance for future reserves.
 
 As I understand it, C<&CheckReserves> looks for the given item in the
 reserves. If it is found, that's a match, and C<$status> is set to
@@ -823,7 +837,7 @@ table in the Koha database.
 =cut
 
 sub CheckReserves {
-    my ( $item, $barcode ) = @_;
+    my ( $item, $barcode, $lookahead_days) = @_;
     my $dbh = C4::Context->dbh;
     my $sth;
     my $select;
@@ -870,7 +884,7 @@ sub CheckReserves {
     return ( '' ) if  ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype;
 
     # Find this item in the reserves
-    my @reserves = _Findgroupreserve( $bibitem, $biblio, $itemnumber );
+    my @reserves = _Findgroupreserve( $bibitem, $biblio, $itemnumber, $lookahead_days);
 
     # $priority and $highest are used to find the most important item
     # in the list returned by &_Findgroupreserve. (The lower $priority,
@@ -887,7 +901,7 @@ sub CheckReserves {
                 if ( $res->{'priority'} && $res->{'priority'} < $priority ) {
                     my $borrowerinfo=C4::Members::GetMember(borrowernumber => $res->{'borrowernumber'});
                     my $iteminfo=C4::Items::GetItem($itemnumber);
-                    my $branch=C4::Circulation::_GetCircControlBranch($iteminfo,$borrowerinfo);
+                    my $branch = GetReservesControlBranch( $iteminfo, $borrowerinfo );
                     my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$iteminfo->{'itype'});
                     next if ($branchitemrule->{'holdallowed'} == 0);
                     next if (($branchitemrule->{'holdallowed'} == 1) && ($branch ne $borrowerinfo->{'branchcode'}));
@@ -996,7 +1010,6 @@ sub CancelReserve {
     ";
     my $sth = $dbh->prepare($query);
     $sth->execute( $reserve_id );
-    $sth->finish;
 
     $query = "
         INSERT INTO old_reserves
@@ -1079,7 +1092,6 @@ sub ModReserve {
         ";
         my $sth = $dbh->prepare($query);
         $sth->execute( $reserve_id );
-        $sth->finish;
         $query = "
             INSERT INTO old_reserves
             SELECT *
@@ -1103,7 +1115,6 @@ sub ModReserve {
         ";
         my $sth = $dbh->prepare($query);
         $sth->execute( $rank, $branchcode, $itemnumber, $reserve_id );
-        $sth->finish;
 
         if ( defined( $suspend_until ) ) {
             if ( $suspend_until ) {
@@ -1149,7 +1160,6 @@ sub ModReserveFill {
     my $sth = $dbh->prepare($query);
     $sth->execute( $biblionumber, $borrowernumber, $resdate );
     ($priority) = $sth->fetchrow_array;
-    $sth->finish;
 
     # update the database...
     $query = "UPDATE reserves
@@ -1161,7 +1171,6 @@ sub ModReserveFill {
                 ";
     $sth = $dbh->prepare($query);
     $sth->execute( $biblionumber, $resdate, $borrowernumber );
-    $sth->finish;
 
     # move to old_reserves
     $query = "INSERT INTO old_reserves
@@ -1439,7 +1448,7 @@ sub IsAvailableForItemLevelRequest {
     $available_per_item = 0 if $item->{itemlost} or
                                ( $item->{notforloan} > 0 ) or
                                ($item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems')) or
-                               $item->{wthdrawn} or
+                               $item->{withdrawn} or
                                $notforloan_per_itemtype;
 
 
@@ -1466,9 +1475,14 @@ sub AlterPriority {
 
     my $reserve = GetReserve( $reserve_id );
 
+    if ( $reserve->{cancellationdate} ) {
+        warn "I cannot alter the priority for reserve_id $reserve_id, the reserve has been cancelled (".$reserve->{cancellationdate}.')';
+        return;
+    }
+
     if ( $where eq 'up' || $where eq 'down' ) {
-    
-      my $priority = $reserve->{'priority'};        
+
+      my $priority = $reserve->{'priority'};
       $priority = $where eq 'up' ? $priority - 1 : $priority + 1;
       _FixPriority( $reserve_id, $priority )
 
@@ -1498,7 +1512,6 @@ sub ToggleLowestPriority {
 
     my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?");
     $sth->execute( $reserve_id );
-    $sth->finish;
     
     _FixPriority( $reserve_id, '999999' );
 }
@@ -1516,7 +1529,7 @@ be cleared when it is unsuspended.
 sub ToggleSuspend {
     my ( $reserve_id, $suspend_until ) = @_;
 
-    $suspend_until = output_pref( dt_from_string( $suspend_until ), 'iso' ) if ( $suspend_until );
+    $suspend_until = output_pref({ dt => dt_from_string( $suspend_until ), dateformat => 'iso' }) if ( $suspend_until );
 
     my $do_until = ( $suspend_until ) ? '?' : 'NULL';
 
@@ -1533,7 +1546,6 @@ sub ToggleSuspend {
     push( @params, $reserve_id );
 
     $sth->execute( @params );
-    $sth->finish;
 }
 
 =head2 SuspendAll
@@ -1589,7 +1601,6 @@ sub SuspendAll {
     $dbh = C4::Context->dbh;
     $sth = $dbh->prepare( $query );
     $sth->execute( @query_params );
-    $sth->finish;
 }
 
 
@@ -1628,7 +1639,6 @@ sub _FixPriority {
         $sth->execute( $reserve_id );
     }
     my @priority;
-    my @reservedates;
 
     # get whats left
     my $query = "
@@ -1641,7 +1651,6 @@ sub _FixPriority {
     my $sth = $dbh->prepare($query);
     $sth->execute( $res->{'biblionumber'} );
     while ( my $line = $sth->fetchrow_hashref ) {
-        push( @reservedates, $line );
         push( @priority,     $line );
     }
 
@@ -1675,7 +1684,6 @@ sub _FixPriority {
             $j + 1,
             $priority[$j]->{'reserve_id'}
         );
-        $sth->finish;
     }
     
     $sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" );
@@ -1690,11 +1698,12 @@ sub _FixPriority {
 
 =head2 _Findgroupreserve
 
-  @results = &_Findgroupreserve($biblioitemnumber, $biblionumber, $itemnumber);
+  @results = &_Findgroupreserve($biblioitemnumber, $biblionumber, $itemnumber, $lookahead);
 
 Looks for an item-specific match first, then for a title-level match, returning the
 first match found.  If neither, then we look for a 3rd kind of match based on
 reserve constraints.
+Lookahead is the number of days to look in advance.
 
 TODO: add more explanation about reserve constraints
 
@@ -1706,7 +1715,7 @@ C<biblioitemnumber>.
 =cut
 
 sub _Findgroupreserve {
-    my ( $bibitem, $biblio, $itemnumber ) = @_;
+    my ( $bibitem, $biblio, $itemnumber, $lookahead) = @_;
     my $dbh   = C4::Context->dbh;
 
     # TODO: consolidate at least the SELECT portion of the first 2 queries to a common $select var.
@@ -1731,11 +1740,11 @@ sub _Findgroupreserve {
         AND priority > 0
         AND item_level_request = 1
         AND itemnumber = ?
-        AND reservedate <= CURRENT_DATE()
+        AND reservedate <= DATE_ADD(NOW(),INTERVAL ? DAY)
         AND suspend = 0
     /;
     my $sth = $dbh->prepare($item_level_target_query);
-    $sth->execute($itemnumber);
+    $sth->execute($itemnumber, $lookahead||0);
     my @results;
     if ( my $data = $sth->fetchrow_hashref ) {
         push( @results, $data );
@@ -1762,11 +1771,11 @@ sub _Findgroupreserve {
         AND priority > 0
         AND item_level_request = 0
         AND hold_fill_targets.itemnumber = ?
-        AND reservedate <= CURRENT_DATE()
+        AND reservedate <= DATE_ADD(NOW(),INTERVAL ? DAY)
         AND suspend = 0
     /;
     $sth = $dbh->prepare($title_level_target_query);
-    $sth->execute($itemnumber);
+    $sth->execute($itemnumber, $lookahead||0);
     @results = ();
     if ( my $data = $sth->fetchrow_hashref ) {
         push( @results, $data );
@@ -1794,11 +1803,11 @@ sub _Findgroupreserve {
           AND reserves.reservedate    = reserveconstraints.reservedate )
           OR  reserves.constrainttype='a' )
           AND (reserves.itemnumber IS NULL OR reserves.itemnumber = ?)
-          AND reserves.reservedate <= CURRENT_DATE()
+          AND reserves.reservedate <= DATE_ADD(NOW(),INTERVAL ? DAY)
           AND suspend = 0
     /;
     $sth = $dbh->prepare($query);
-    $sth->execute( $biblio, $bibitem, $itemnumber );
+    $sth->execute( $biblio, $bibitem, $itemnumber, $lookahead||0);
     @results = ();
     while ( my $data = $sth->fetchrow_hashref ) {
         push( @results, $data );
@@ -2011,7 +2020,7 @@ This shifts the holds from C<$from_biblio> to C<$to_biblio> and reorders them by
 sub MergeHolds {
     my ( $dbh, $to_biblio, $from_biblio ) = @_;
     my $sth = $dbh->prepare(
-        "SELECT count(*) as reserve_id FROM reserves WHERE biblionumber = ?"
+        "SELECT count(*) as reserve_count FROM reserves WHERE biblionumber = ?"
     );
     $sth->execute($from_biblio);
     if ( my $data = $sth->fetchrow_hashref() ) {
@@ -2152,8 +2161,11 @@ sub ReserveSlip {
 
 #   return unless ( C4::Context->boolean_preference('printreserveslips') );
 
-    my $reserve = GetReserveInfo($borrowernumber,$biblionumber )
-      or return;
+    my $reserve_id = GetReserveId({
+        biblionumber => $biblionumber,
+        borrowernumber => $borrowernumber
+    }) or return;
+    my $reserve = GetReserveInfo($reserve_id) or return;
 
     return  C4::Letters::GetPreparedLetter (
         module => 'circulation',
@@ -2169,6 +2181,32 @@ sub ReserveSlip {
     );
 }
 
+=head2 GetReservesControlBranch
+
+  my $reserves_control_branch = GetReservesControlBranch($item, $borrower);
+
+  Return the branchcode to be used to determine which reserves
+  policy applies to a transaction.
+
+  C<$item> is a hashref for an item. Only 'homebranch' is used.
+
+  C<$borrower> is a hashref to borrower. Only 'branchcode' is used.
+
+=cut
+
+sub GetReservesControlBranch {
+    my ( $item, $borrower ) = @_;
+
+    my $reserves_control = C4::Context->preference('ReservesControlBranch');
+
+    my $branchcode =
+        ( $reserves_control eq 'ItemHomeLibrary' ) ? $item->{'homebranch'}
+      : ( $reserves_control eq 'PatronLibrary' )   ? $borrower->{'branchcode'}
+      :                                              undef;
+
+    return $branchcode;
+}
+
 =head1 AUTHOR
 
 Koha Development Team <http://koha-community.org/>