bug 10052: DBrev 3.13.00.005
[koha_fer] / C4 / Reserves.pm
index c4b2c66..5ff12e4 100644 (file)
@@ -36,6 +36,9 @@ use C4::Members qw();
 use C4::Letters;
 use C4::Branch qw( GetBranchDetail );
 use C4::Dates qw( format_date_in_iso );
+
+use Koha::DateUtils;
+
 use List::MoreUtils qw( firstidx );
 
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
@@ -85,7 +88,7 @@ This modules provides somes functions to deal with reservations.
 
 BEGIN {
     # set the version for version checking
-    $VERSION = 3.01;
+    $VERSION = 3.07.00.049;
     require Exporter;
     @ISA = qw(Exporter);
     @EXPORT = qw(
@@ -732,16 +735,40 @@ sub GetReservesForBranch {
     return (@transreserv);
 }
 
+=head2 GetReserveStatus
+
+  $reservestatus = GetReserveStatus($itemnumber, $biblionumber);
+
+Take an itemnumber or a biblionumber and return the status of the reserve places on it.
+If several reserves exist, the reserve with the lower priority is given.
+
+=cut
+
 sub GetReserveStatus {
-    my ($itemnumber) = @_;
-    
+    my ($itemnumber, $biblionumber) = @_;
+
     my $dbh = C4::Context->dbh;
-    
-    my $itemstatus = $dbh->prepare("SELECT found FROM reserves WHERE itemnumber = ?");
-    
-    $itemstatus->execute($itemnumber);
-    my ($found) = $itemstatus->fetchrow_array;
-    return $found;
+
+    my ($sth, $found, $priority);
+    if ( $itemnumber ) {
+        $sth = $dbh->prepare("SELECT found, priority FROM reserves WHERE itemnumber = ? order by priority LIMIT 1");
+        $sth->execute($itemnumber);
+        ($found, $priority) = $sth->fetchrow_array;
+    }
+
+    if ( $biblionumber and not defined $found and not defined $priority ) {
+        $sth = $dbh->prepare("SELECT found, priority FROM reserves WHERE biblionumber = ? order by priority LIMIT 1");
+        $sth->execute($biblionumber);
+        ($found, $priority) = $sth->fetchrow_array;
+    }
+
+    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
 }
 
 =head2 CheckReserves
@@ -1392,7 +1419,7 @@ be the target of an item-level hold request.
 Note that IsAvailableForItemLevelRequest() does not
 check if the staff operator is authorized to place
 a request on the item - in particular,
-this routine does not check IndependantBranches
+this routine does not check IndependentBranches
 and canreservefromotherbranches.
 
 =cut
@@ -1438,7 +1465,7 @@ sub IsAvailableForItemLevelRequest {
     if (C4::Context->preference('AllowOnShelfHolds')) {
         return $available_per_item;
     } else {
-        return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "W")); 
+        return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "Waiting"));
     }
 }
 
@@ -1517,20 +1544,27 @@ be cleared when it is unsuspended.
 =cut
 
 sub ToggleSuspend {
-    my ( $borrowernumber, $biblionumber ) = @_;
+    my ( $borrowernumber, $biblionumber, $suspend_until ) = @_;
+
+    $suspend_until = output_pref( dt_from_string( $suspend_until ), 'iso' ) if ( $suspend_until );
+
+    my $do_until = ( $suspend_until ) ? '?' : 'NULL';
 
     my $dbh = C4::Context->dbh;
 
     my $sth = $dbh->prepare(
         "UPDATE reserves SET suspend = NOT suspend,
-        suspend_until = CASE WHEN suspend = 0 THEN NULL ELSE suspend_until END
+        suspend_until = CASE WHEN suspend = 0 THEN NULL ELSE $do_until END
         WHERE biblionumber = ?
         AND borrowernumber = ?
     ");
-    $sth->execute(
-        $biblionumber,
-        $borrowernumber,
-    );
+
+    my @params;
+    push( @params, $suspend_until ) if ( $suspend_until );
+    push( @params, $biblionumber );
+    push( @params, $borrowernumber );
+
+    $sth->execute( @params );
     $sth->finish;
 }
 
@@ -1825,25 +1859,14 @@ sub _koha_notify_reserve {
     my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber);
     
     # Try to get the borrower's email address
-    my $to_address;
-    my $which_address = C4::Context->preference('AutoEmailPrimaryAddress');
-    # If the system preference is set to 'first valid' (value == OFF), look up email address
-    if ($which_address eq 'OFF') {
-        $to_address = C4::Members::GetFirstValidEmailAddress( $borrowernumber );
-    } else {
-        $to_address = $borrower->{$which_address};
-    }
+    my $to_address = C4::Members::GetNoticeEmailAddress($borrowernumber);
     
     my $letter_code;
     my $print_mode = 0;
     my $messagingprefs;
     if ( $to_address || $borrower->{'smsalertnumber'} ) {
         $messagingprefs = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $borrowernumber, message_name => 'Hold_Filled' } );
-
-        return if ( !defined( $messagingprefs->{'letter_code'} ) );
-        $letter_code = $messagingprefs->{'letter_code'};
     } else {
-        $letter_code = 'HOLD_PRINT';
         $print_mode = 1;
     }
 
@@ -1859,9 +1882,8 @@ sub _koha_notify_reserve {
 
     my $admin_email_address = $branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress');
 
-    my $letter =  C4::Letters::GetPreparedLetter (
+    my %letter_params = (
         module => 'reserves',
-        letter_code => $letter_code,
         branchcode => $reserve->{branchcode},
         tables => {
             'branches'  => $branch_details,
@@ -1871,11 +1893,13 @@ sub _koha_notify_reserve {
             'items', $reserve->{'itemnumber'},
         },
         substitute => { today => C4::Dates->new()->output() },
-    ) or die "Could not find a letter called '$letter_code' in the 'reserves' module";
-
+    );
 
 
     if ( $print_mode ) {
+        $letter_params{ 'letter_code' } = 'HOLD_PRINT';
+        my $letter =  C4::Letters::GetPreparedLetter ( %letter_params ) or die "Could not find a letter called '$letter_params{'letter_code'}' in the 'reserves' module";
+
         C4::Letters::EnqueueLetter( {
             letter => $letter,
             borrowernumber => $borrowernumber,
@@ -1885,8 +1909,10 @@ sub _koha_notify_reserve {
         return;
     }
 
-    if ( grep { $_ eq 'email' } @{$messagingprefs->{transports}} ) {
-        # aka, 'email' in ->{'transports'}
+    if ( $to_address && defined $messagingprefs->{transports}->{'email'} ) {
+        $letter_params{ 'letter_code' } = $messagingprefs->{transports}->{'email'};
+        my $letter =  C4::Letters::GetPreparedLetter ( %letter_params ) or die "Could not find a letter called '$letter_params{'letter_code'}' in the 'reserves' module";
+
         C4::Letters::EnqueueLetter(
             {   letter                 => $letter,
                 borrowernumber         => $borrowernumber,
@@ -1896,7 +1922,10 @@ sub _koha_notify_reserve {
         );
     }
 
-    if ( grep { $_ eq 'sms' } @{$messagingprefs->{transports}} ) {
+    if ( $borrower->{'smsalertnumber'} && defined $messagingprefs->{transports}->{'sms'} ) {
+        $letter_params{ 'letter_code' } = $messagingprefs->{transports}->{'sms'};
+        my $letter =  C4::Letters::GetPreparedLetter ( %letter_params ) or die "Could not find a letter called '$letter_params{'letter_code'}' in the 'reserves' module";
+
         C4::Letters::EnqueueLetter(
             {   letter                 => $letter,
                 borrowernumber         => $borrowernumber,
@@ -1995,7 +2024,10 @@ sub MoveReserve {
             ModReserveFill($borr_res);
         }
 
-        if ($cancelreserve) { # cancel reserves on this item
+        if ( $cancelreserve eq 'revert' ) { ## Revert waiting reserve to priority 1
+            RevertWaitingStatus({ itemnumber => $itemnumber });
+        }
+        elsif ( $cancelreserve eq 'cancel' || $cancelreserve ) { # cancel reserves on this item
             CancelReserve(0, $res->{'itemnumber'}, $res->{'borrowernumber'});
             CancelReserve($res->{'biblionumber'}, 0, $res->{'borrowernumber'});
         }
@@ -2046,6 +2078,66 @@ sub MergeHolds {
     }
 }
 
+=head2 RevertWaitingStatus
+
+  $success = RevertWaitingStatus({ itemnumber => $itemnumber });
+
+  Reverts a 'waiting' hold back to a regular hold with a priority of 1.
+
+  Caveat: Any waiting hold fixed with RevertWaitingStatus will be an
+          item level hold, even if it was only a bibliolevel hold to
+          begin with. This is because we can no longer know if a hold
+          was item-level or bib-level after a hold has been set to
+          waiting status.
+
+=cut
+
+sub RevertWaitingStatus {
+    my ( $params ) = @_;
+    my $itemnumber = $params->{'itemnumber'};
+
+    return unless ( $itemnumber );
+
+    my $dbh = C4::Context->dbh;
+
+    ## Get the waiting reserve we want to revert
+    my $query = "
+        SELECT * FROM reserves
+        WHERE itemnumber = ?
+        AND found IS NOT NULL
+    ";
+    my $sth = $dbh->prepare( $query );
+    $sth->execute( $itemnumber );
+    my $reserve = $sth->fetchrow_hashref();
+
+    ## Increment the priority of all other non-waiting
+    ## reserves for this bib record
+    $query = "
+        UPDATE reserves
+        SET
+          priority = priority + 1
+        WHERE
+          biblionumber =  ?
+        AND
+          priority > 0
+    ";
+    $sth = $dbh->prepare( $query );
+    $sth->execute( $reserve->{'biblionumber'} );
+
+    ## Fix up the currently waiting reserve
+    $query = "
+    UPDATE reserves
+    SET
+      priority = 1,
+      found = NULL,
+      waitingdate = NULL
+    WHERE
+      reserve_id = ?
+    ";
+    $sth = $dbh->prepare( $query );
+    return $sth->execute( $reserve->{'reserve_id'} );
+}
+
 =head2 ReserveSlip
 
   ReserveSlip($branchcode, $borrowernumber, $biblionumber)
@@ -2069,9 +2161,9 @@ sub ReserveSlip {
         tables => {
             'reserves'    => $reserve,
             'branches'    => $reserve->{branchcode},
-            'borrowers'   => $reserve,
-            'biblio'      => $reserve,
-            'items'       => $reserve,
+            'borrowers'   => $reserve->{borrowernumber},
+            'biblio'      => $reserve->{biblionumber},
+            'items'       => $reserve->{itemnumber},
         },
     );
 }