From ad69e459caa66bc9bb407b391997d9fa1c21eeb7 Mon Sep 17 00:00:00 2001 From: Lucas Gass Date: Mon, 28 Jul 2025 17:48:53 +0000 Subject: [PATCH] Bug 28530: Count incoming transfers against the float limit --- Koha/Library/FloatLimits.pm | 42 ++++++++- t/db_dependent/Koha/Library/FloatLimits.t | 109 +++++++++++++++++++++- 2 files changed, 146 insertions(+), 5 deletions(-) diff --git a/Koha/Library/FloatLimits.pm b/Koha/Library/FloatLimits.pm index 07b009e9a4d..066d88ca96d 100644 --- a/Koha/Library/FloatLimits.pm +++ b/Koha/Library/FloatLimits.pm @@ -1,5 +1,3 @@ -## Please see file perltidy.ERR -## Please see file perltidy.ERR package Koha::Library::FloatLimits; # Copyright ByWater Solutions 2016 @@ -65,21 +63,57 @@ sub lowest_ratio_library { my $item_count; if ($use_item_level) { - $item_count = Koha::Items->search( + my $at_branch_count = Koha::Items->search( { itype => $item->effective_itemtype, holdingbranch => $branch, onloan => undef }, )->count; + + # Count items in transit TO this branch + my $in_transit_count = Koha::Items->search( + { + itype => $item->effective_itemtype, + + # Join with active transfers where this branch is the destination + }, + { + join => 'branchtransfers', + where => { + 'branchtransfers.tobranch' => $branch, + 'branchtransfers.datearrived' => undef, # Still in transit + 'branchtransfers.datecancelled' => undef, #Not cancelled + }, + distinct => 1 + } + )->count; + $item_count = $at_branch_count + $in_transit_count; } else { - $item_count = Koha::Items->search( + my $at_branch_count = Koha::Items->search( { holdingbranch => $branch, 'biblioitem.itemtype' => $item->effective_itemtype, onloan => undef }, )->count; + + # Count items in transit TO this branch + my $in_transit_count = Koha::Items->search( + { + itype => $item->effective_itemtype, + }, + { + join => 'branchtransfers', + where => { + 'branchtransfers.tobranch' => $branch, + 'branchtransfers.datearrived' => undef, # Still in transit + 'branchtransfers.datecancelled' => undef, #Not cancelled + }, + distinct => 1 + } + )->count; + $item_count = $at_branch_count + $in_transit_count; } my $ratio = $item_count / $float_limit_val; diff --git a/t/db_dependent/Koha/Library/FloatLimits.t b/t/db_dependent/Koha/Library/FloatLimits.t index bd54b110053..edc59fd7646 100755 --- a/t/db_dependent/Koha/Library/FloatLimits.t +++ b/t/db_dependent/Koha/Library/FloatLimits.t @@ -19,7 +19,7 @@ use Modern::Perl; -use Test::More tests => 6; +use Test::More tests => 7; use Koha::Database; use C4::Circulation qw(CreateBranchTransferLimit); @@ -199,4 +199,111 @@ subtest 'onloan items excluded from ratio calculation' => sub { ); }; +subtest 'items in transit counted toward destination branch' => sub { + plan tests => 6; + + # Reset transfer limits for clean test + t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '0' ); + + Koha::Items->search( + { + holdingbranch => $library3->{branchcode}, + itype => $itemtype->itemtype, + onloan => { '!=' => undef } + } + )->update( { onloan => undef } ); + + # Verify initial counts + my $library2_initial = Koha::Items->search( + { + holdingbranch => $library2->{branchcode}, + itype => $itemtype->itemtype, + onloan => undef + } + )->count; + + my $library3_initial = Koha::Items->search( + { + holdingbranch => $library3->{branchcode}, + itype => $itemtype->itemtype, + onloan => undef + } + )->count; + + is( $library2_initial, 10, "Library2 initially has 10 available items" ); + is( $library3_initial, 15, "Library3 initially has 15 available items" ); + + # Initial selection should be library3 + is( + Koha::Library::FloatLimits->lowest_ratio_library( $item, $library1->{branchcode} )->branchcode, + $library3->{branchcode}, + "Library3 initially selected (ratio: 15/1000 = 0.015)" + ); + + # Create items in transit TO library2 + my @transit_items; + for ( 1 .. 2 ) { + my $transit_item = $builder->build_sample_item( + { + biblionumber => $biblio->biblionumber, + homebranch => $library1->{branchcode}, + holdingbranch => $library1->{branchcode}, + itype => $itemtype->itemtype, + } + ); + push @transit_items, $transit_item; + } + + # Create active transfers to library2 + my $transfer_date = dt_from_string(); + for my $transit_item (@transit_items) { + Koha::Item::Transfer->new( + { + itemnumber => $transit_item->itemnumber, + frombranch => $library1->{branchcode}, + tobranch => $library2->{branchcode}, + daterequested => $transfer_date, + datesent => $transfer_date, + reason => 'LibraryFloatLimit' + } + )->store; + } + + # Verify that items in transit are counted toward destination + my $in_transit_count = Koha::Items->search( + { + itype => $itemtype->itemtype, + }, + { + join => 'branchtransfers', + where => { + 'branchtransfers.tobranch' => $library2->{branchcode}, + 'branchtransfers.datearrived' => undef, + 'branchtransfers.datecancelled' => undef, + }, + distinct => 1 + } + )->count; + + is( $in_transit_count, 2, "2 items are in transit to library2" ); + + # Test 5: Library2's physical count should still be 10 + my $library2_physical = Koha::Items->search( + { + holdingbranch => $library2->{branchcode}, + itype => $itemtype->itemtype, + onloan => undef + } + )->count; + + is( $library2_physical, 10, "Library2 still has 10 physical items" ); + + # Library2's count should now be 10 + 2 = 12 + is( + Koha::Library::FloatLimits->lowest_ratio_library( $item, $library1->{branchcode} )->branchcode, + $library3->{branchcode}, + "Library3 still selected after items in transit to library2" + ); +}; + $schema->storage->txn_rollback; -- 2.39.5