From 892f8b45c881529c44b1819543727419e1fe9055 Mon Sep 17 00:00:00 2001 From: Nick Clemens Date: Mon, 15 Nov 2021 13:54:00 +0000 Subject: [PATCH] Bug 29483: Check ItemsAnyAvailableAndNotRestricted once per patron ItemsAnyAvailableAndNotRestricted can take a long time and create nested loops. We can check it once per patron, however, this requires us to flip the loops. Since an item can only be used once, we now add a check to see if this item has already been assigned to a borrower. To test: 1 - Find or create a biblio with 100 items 2 - Place ten 'Next available' holds on a biblio 3 - Set preference 'AllowRenewalIfOtherItemsAvailable' to 'Allow' Set circ rules 'On shelf holds allowed' to 'If any unavailable' 4 - Checkout one of the items to a patron, backdated to be overdue 5 - Note a long loading time for the patron's checkouts 6 - Apply patch, restart_all 7 - Patron loads much faster --- C4/Circulation.pm | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 0791c7f7c2..5d946ae2a3 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -27,7 +27,7 @@ use Encode; use Koha::DateUtils qw( dt_from_string output_pref ); use C4::Context; use C4::Stats qw( UpdateStats ); -use C4::Reserves qw( CheckReserves CanItemBeReserved MoveReserve ModReserve ModReserveMinusPriority RevertWaitingStatus IsItemOnHoldAndFound IsAvailableForItemLevelRequest ); +use C4::Reserves qw( CheckReserves CanItemBeReserved MoveReserve ModReserve ModReserveMinusPriority RevertWaitingStatus IsItemOnHoldAndFound IsAvailableForItemLevelRequest ItemsAnyAvailableAndNotRestricted ); use C4::Biblio qw( UpdateTotalIssues ); use C4::Items qw( ModItemTransfer ModDateLastSeen CartToShelf ); use C4::Accounts; @@ -2853,19 +2853,22 @@ sub CanBookBeRenewed { # can be filled with available items. We can get the union of the sets simply # by pushing all the elements onto an array and removing the duplicates. my @reservable; - ITEM: while ( my $item = $items->next ) { - next if IsItemOnHoldAndFound( $item->itemnumber ); - while ( my $patron = $patrons->next ) { - next unless IsAvailableForItemLevelRequest($item, $patron); - next unless CanItemBeReserved($patron->borrowernumber,$item->itemnumber,undef,{ignore_hold_counts=>1})->{status} eq 'OK'; - push @reservable, $item->itemnumber; + my %matched_items; + PATRON: while ( my $patron = $patrons->next ) { + my $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $item->biblionumber, patron => $patron }); + while ( my $other_item = $items->next ) { + next if $matched_items{$other_item->itemnumber} == 1; + next if IsItemOnHoldAndFound( $other_item->itemnumber ); + next unless IsAvailableForItemLevelRequest($other_item, $patron, undef, $items_any_available); + next unless CanItemBeReserved($patron->borrowernumber,$other_item->itemnumber,undef,{ignore_hold_counts=>1})->{status} eq 'OK'; + push @reservable, $other_item->itemnumber; if (@reservable >= @borrowernumbers) { $resfound = 0; - last ITEM; + last PATRON; } - last; + $matched_items{$other_item->itemnumber} = 1; } - $patrons->reset; + $items->reset; } } } -- 2.20.1