Bug 29234: Transit on checking
[koha-ffzg.git] / C4 / Circulation.pm
index d8b70cc..237181f 100644 (file)
@@ -48,7 +48,7 @@ use Koha::Checkouts;
 use Koha::Illrequests;
 use Koha::Items;
 use Koha::Patrons;
-use Koha::Patron::Debarments qw( DelUniqueDebarment GetDebarments AddUniqueDebarment );
+use Koha::Patron::Debarments qw( DelUniqueDebarment AddUniqueDebarment );
 use Koha::Database;
 use Koha::Libraries;
 use Koha::Account::Lines;
@@ -824,6 +824,7 @@ sub CanBookBeIssued {
                 borrowernumber => $patron->borrowernumber,
                 ccode          => $item_object->ccode,
                 categorycode   => $patron->categorycode,
+                location       => $item_object->location,
             }
         );
         ModDateLastSeen( $item_object->itemnumber ); # FIXME Move to Koha::Item
@@ -1191,7 +1192,7 @@ sub CanBookBeIssued {
                     $needsconfirmation{'ressurname'} = $patron->surname;
                     $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
                     $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
-                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
+                    $needsconfirmation{'resbranchcode'} = $res->{branchcode};
                     $needsconfirmation{'resreservedate'} = $res->{reservedate};
                     $needsconfirmation{'reserve_id'} = $res->{reserve_id};
                 }
@@ -1202,7 +1203,7 @@ sub CanBookBeIssued {
                     $needsconfirmation{'ressurname'} = $patron->surname;
                     $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
                     $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
-                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
+                    $needsconfirmation{'resbranchcode'} = $res->{branchcode};
                     $needsconfirmation{'resreservedate'} = $res->{reservedate};
                     $needsconfirmation{'reserve_id'} = $res->{reserve_id};
                 }
@@ -1213,7 +1214,7 @@ sub CanBookBeIssued {
                     $needsconfirmation{'ressurname'} = $patron->surname;
                     $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
                     $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
-                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
+                    $needsconfirmation{'resbranchcode'} = $res->{branchcode};
                     $needsconfirmation{'resreservedate'} = $res->{reservedate};
                     $needsconfirmation{'reserve_id'} = $res->{reserve_id};
                 }
@@ -1354,7 +1355,12 @@ sub checkHighHolds {
         due_date    => undef,
     };
 
-    my $holds = Koha::Holds->search( { biblionumber => $item->biblionumber } );
+
+    # Count holds on this record, ignoring the borrowers own holds as they would be filled by the checkout
+    my $holds = Koha::Holds->search({
+        biblionumber => $item->biblionumber,
+        borrowernumber => { '!=' => $patron->borrowernumber }
+    });
 
     if ( $holds->count() ) {
         $return_data->{outstanding} = $holds->count();
@@ -1369,8 +1375,8 @@ sub checkHighHolds {
 
             # static means just more than a given number of holds on the record
 
-            # If the number of holds is less than the threshold, we can stop here
-            if ( $holds->count() < $decreaseLoanHighHoldsValue ) {
+            # If the number of holds is not above the threshold, we can stop here
+            if ( $holds->count() <= $decreaseLoanHighHoldsValue ) {
                 return $return_data;
             }
         }
@@ -1387,7 +1393,9 @@ sub checkHighHolds {
             }
 
             # Remove any items that are not holdable for this patron
-            @items = grep { CanItemBeReserved( $patron , $_, undef, { ignore_found_holds => 1 } )->{status} eq 'OK' } @items;
+            # We need to ignore hold counts as the borrower's own hold that will be filled by the checkout
+            # could prevent them from placing further holds
+            @items = grep { CanItemBeReserved( $patron, $_, undef, { ignore_hold_counts => 1 } )->{status} eq 'OK' } @items;
 
             my $items_count = scalar @items;
 
@@ -1539,6 +1547,7 @@ sub AddIssue {
             );
         }
         else {
+
             unless ($datedue) {
                 my $itype = $item_object->effective_itemtype;
                 $datedue = CalcDateDue( $issuedate, $itype, $branchcode, $borrower );
@@ -2089,6 +2098,16 @@ sub AddReturn {
         }
     }
 
+    if ( $item->withdrawn ) { # book has been cancelled
+        $messages->{'withdrawn'} = 1;
+
+        # In the case where we block return of withdrawn, we should completely block the return
+        # without updating item statuses, so we exit early
+        return ( 0, $messages, $issue, ( $patron ? $patron->unblessed : {} ))
+            if C4::Context->preference("BlockReturnOfWithdrawnItems");
+    }
+
+
         # full item data, but no borrowernumber or checkout info (no issue)
     my $hbr = Koha::CirculationRules->get_return_branch_policy($item);
         # get the proper branch to which to return the item
@@ -2158,11 +2177,6 @@ sub AddReturn {
         return ( $doreturn, $messages, $issue, $patron_unblessed);
     }
 
-    if ( $item->withdrawn ) { # book has been cancelled
-        $messages->{'withdrawn'} = 1;
-        $doreturn = 0 if C4::Context->preference("BlockReturnOfWithdrawnItems");
-    }
-
     if ( $item->itemlost and C4::Context->preference("BlockReturnOfLostItems") ) {
         $doreturn = 0;
     }
@@ -2279,8 +2293,15 @@ sub AddReturn {
                 $validTransfer = 1 if $transfer->reason eq 'Reserve';
             }
             else {
-                $messages->{'WasTransfered'}   = $transfer->tobranch;
                 $messages->{'TransferTrigger'} = $transfer->reason;
+                if ( $transfer->frombranch eq $branch ) {
+                    $transfer->transit;
+                    $messages->{'WasTransfered'}   = $transfer->tobranch;
+                }
+                else {
+                    $messages->{'WrongTransfer'}     = $transfer->tobranch;
+                    $messages->{'WrongTransferItem'} = $item->itemnumber;
+                }
             }
         }
     }
@@ -2293,10 +2314,23 @@ sub AddReturn {
         if ( $issue and $issue->is_overdue($return_date) ) {
         # fix fine days
             my ($debardate,$reminder) = _debar_user_on_return( $patron_unblessed, $item->unblessed, dt_from_string($issue->date_due), $return_date );
-            if ($reminder){
-                $messages->{'PrevDebarred'} = $debardate;
-            } else {
-                $messages->{'Debarred'} = $debardate if $debardate;
+            if ($debardate and $debardate ne "9999-12-31") {
+                if ($reminder){
+                    $messages->{'PrevDebarred'} = $debardate;
+                } else {
+                    $messages->{'Debarred'} = $debardate;
+                }
+            } elsif ($patron->debarred) {
+                if ( $patron->debarred eq "9999-12-31") {
+                    $messages->{'ForeverDebarred'} = $patron->debarred;
+                } else {
+                    my $borrower_debar_dt = dt_from_string( $patron->debarred );
+                    $borrower_debar_dt->truncate(to => 'day');
+                    my $today_dt = $return_date->clone()->truncate(to => 'day');
+                    if ( DateTime->compare( $borrower_debar_dt, $today_dt ) != -1 ) {
+                        $messages->{'PrevDebarred'} = $patron->debarred;
+                    }
+                }
             }
         # there's no overdue on the item but borrower had been previously debarred
         } elsif ( $issue->date_due and $patron->debarred ) {
@@ -2532,10 +2566,11 @@ sub MarkIssueReturned {
         }
 
         # Remove any OVERDUES related debarment if the borrower has no overdues
+        my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
         if ( C4::Context->preference('AutoRemoveOverduesRestrictions')
           && $patron->debarred
           && !$patron->has_overdues
-          && @{ GetDebarments({ borrowernumber => $borrowernumber, type => 'OVERDUES' }) }
+          && $overdue_restrictions->count
         ) {
             DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
         }
@@ -2624,9 +2659,10 @@ sub _calculate_new_debar_dt {
 
         my ( $has_been_extended );
         if ( C4::Context->preference('CumulativeRestrictionPeriods') and $borrower->{debarred} ) {
-            my $debarment = @{ GetDebarments( { borrowernumber => $borrower->{borrowernumber}, type => 'SUSPENSION' } ) }[0];
+            my $patron = Koha::Patrons->find($borrower->{borrowernumber});
+            my $debarment = $patron->restrictions->search({type => 'SUSPENSION' },{rows => 1})->single;
             if ( $debarment ) {
-                $return_date = dt_from_string( $debarment->{expiration}, 'sql' );
+                $return_date = dt_from_string( $debarment->expiration, 'sql' );
                 $has_been_extended = 1;
             }
         }
@@ -2926,6 +2962,10 @@ sub CanBookBeRenewed {
         }
     }
 
+    # There is an item level hold on this item, no other item can fill the hold
+    return ( 0, "on_reserve" )
+      if ( $item->current_holds->search( { non_priority => 0 } )->count );
+
     my $fillable_holds = Koha::Holds->search(
         {
             biblionumber => $item->biblionumber,
@@ -2992,7 +3032,7 @@ sub CanBookBeRenewed {
 
 =head2 AddRenewal
 
-  &AddRenewal($borrowernumber, $itemnumber, $branch, [$datedue], [$lastreneweddate], [$seen]);
+  &AddRenewal($borrowernumber, $itemnumber, $branch, [$datedue], [$lastreneweddate], [$seen], [$automatic]);
 
 Renews a loan.
 
@@ -3021,6 +3061,8 @@ C<$seen> is a boolean flag indicating if the item was seen or not during the ren
 informs the incrementing of the unseen_renewals column. If this flag is not supplied, we
 fallback to a true value
 
+C<$automatic> is a boolean flag indicating the renewal was triggered automatically and not by a person ( librarian or patron )
+
 =cut
 
 sub AddRenewal {
@@ -3031,6 +3073,7 @@ sub AddRenewal {
     my $lastreneweddate = shift || dt_from_string();
     my $skipfinecalc    = shift;
     my $seen            = shift;
+    my $automatic       = shift;
 
     # Fallback on a 'seen' renewal
     $seen = defined $seen && $seen == 0 ? 0 : 1;
@@ -3040,6 +3083,8 @@ sub AddRenewal {
     my $issue  = $item_object->checkout;
     my $item_unblessed = $item_object->unblessed;
 
+    my $renewal_type = $automatic ? "Automatic" : "Manual";
+
     my $dbh = C4::Context->dbh;
 
     return unless $issue;
@@ -3123,7 +3168,8 @@ sub AddRenewal {
         $renews = ( $item_object->renewals || 0 ) + 1;
         $item_object->renewals($renews);
         $item_object->onloan($datedue);
-        $item_object->store({ log_action => 0 });
+        # Don't index as we are in a transaction
+        $item_object->store({ log_action => 0, skip_record_index => 1 });
 
         # Charge a new rental fee, if applicable
         my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
@@ -3163,10 +3209,11 @@ sub AddRenewal {
         }
 
         # Remove any OVERDUES related debarment if the borrower has no overdues
+        my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
         if ( $patron
           && $patron->is_debarred
           && ! $patron->has_overdues
-          && @{ GetDebarments({ borrowernumber => $borrowernumber, type => 'OVERDUES' }) }
+          && $overdue_restrictions->count
         ) {
             DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
         }
@@ -3174,10 +3221,11 @@ sub AddRenewal {
         # Add renewal record
         my $renewal = Koha::Checkouts::Renewal->new(
             {
-                checkout_id => $issue->issue_id,
-                renewer_id  => C4::Context->userenv ? C4::Context->userenv->{'number'} : undef,
-                seen        => $seen,
-                interface   => C4::Context->interface
+                checkout_id  => $issue->issue_id,
+                interface    => C4::Context->interface,
+                renewal_type => $renewal_type,
+                renewer_id   => C4::Context->userenv ? C4::Context->userenv->{'number'} : undef,
+                seen         => $seen,
             }
         )->store();
 
@@ -3206,6 +3254,9 @@ sub AddRenewal {
             }
         });
     });
+    # We index now, after the transaction is committed
+    my $indexer = Koha::SearchEngine::Indexer->new({ index => $Koha::SearchEngine::BIBLIOS_INDEX });
+    $indexer->index_records( $item_object->biblionumber, "specialUpdate", "biblioserver" );
 
     return $datedue;
 }