Bug 41410: Unit tests

Covers the new LocalHoldsPriorityExclusivityPeriod behaviour and keeps
existing tests working with the schema change:

 - t/db_dependent/Holds/LocalHoldsPriority.t: new subtest exercising
   all four cases -- pref disabled, pref active on a fresh hold, pref
   active past the window, and pref active with no hold_fill_targets
   row (queue hasn't run).
 - t/db_dependent/HoldsQueue.t: assert that after CreateQueue() with a
   local-group match, both tmp_holdsqueue and hold_fill_targets rows
   carry local_holdgroup_match = 1.
 - t/db_dependent/Reserves.t, t/db_dependent/Koha/Hold.t: qualify the
   two direct "INSERT INTO hold_fill_targets VALUES (...)" statements
   with explicit column names so they continue to work now that
   hold_fill_targets has one extra column.

Test plan:
  prove t/db_dependent/Holds/LocalHoldsPriority.t \
        t/db_dependent/HoldsQueue.t \
        t/db_dependent/Reserves.t \
        t/db_dependent/Koha/Hold.t

All tests should pass.

Sponsored-by: Main Library Alliance <https://www.mainlib.org/>

Signed-off-by: Trevor Diamond <trevor.diamond@mainlib.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
Martin Renvoize 2026-04-15 17:59:58 +01:00 committed by Pedro Amorim
parent a2ef73fe95
commit bec5c357b4
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
4 changed files with 133 additions and 4 deletions

View File

@ -6,7 +6,7 @@ use t::lib::Mocks;
use C4::Context;
use Test::NoWarnings;
use Test::More tests => 7;
use Test::More tests => 8;
use MARC::Record;
use Koha::Patrons;
@ -391,3 +391,118 @@ subtest "exclude from local holds" => sub {
$schema->storage->txn_rollback;
};
subtest 'LocalHoldsPriorityExclusivityPeriod' => sub {
plan tests => 4;
$schema->storage->txn_begin;
my $dbh = C4::Context->dbh;
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', 'GiveLibraryGroup' );
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'homebranch' );
my $group =
Koha::Library::Group->new( { title => "Excl period group", ft_local_hold_group => 1 } )->store();
my $local_lib = $builder->build_object( { class => 'Koha::Libraries' } );
my $other_lib_in = $builder->build_object( { class => 'Koha::Libraries' } );
my $non_local_lib = $builder->build_object( { class => 'Koha::Libraries' } );
Koha::Library::Group->new( { parent_id => $group->id, branchcode => $local_lib->branchcode } )->store;
Koha::Library::Group->new( { parent_id => $group->id, branchcode => $other_lib_in->branchcode } )->store;
my $category = $builder->build_object(
{ class => 'Koha::Patron::Categories', value => { exclude_from_local_holds_priority => 0 } } );
my $biblio = $builder->build_sample_biblio();
my $local_item = $builder->build_sample_item(
{
biblionumber => $biblio->biblionumber,
homebranch => $other_lib_in->branchcode,
holdingbranch => $other_lib_in->branchcode,
exclude_from_local_holds_priority => 0,
}
);
my $non_local_item = $builder->build_sample_item(
{
biblionumber => $biblio->biblionumber,
homebranch => $non_local_lib->branchcode,
holdingbranch => $non_local_lib->branchcode,
exclude_from_local_holds_priority => 0,
}
);
my $patron = $builder->build_object(
{
class => 'Koha::Patrons',
value => {
branchcode => $local_lib->branchcode,
categorycode => $category->categorycode,
}
}
);
my $reserve_id = AddReserve(
{
branchcode => $local_lib->branchcode,
borrowernumber => $patron->borrowernumber,
biblionumber => $biblio->biblionumber,
priority => 1,
}
);
# Simulate the holds queue having targeted the local-group item for this reserve.
$dbh->do(
q{
INSERT INTO hold_fill_targets
(borrowernumber, biblionumber, itemnumber, source_branchcode,
item_level_request, reserve_id, local_holdgroup_match)
VALUES (?, ?, ?, ?, ?, ?, ?)
},
undef,
(
$patron->borrowernumber, $biblio->biblionumber, $local_item->itemnumber,
$local_item->homebranch, 0, $reserve_id, 1
)
);
# 1. Pref disabled (0): the non-local item may still fill the hold.
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityExclusivityPeriod', 0 );
my ( undef, $reserve ) = CheckReserves($non_local_item);
is(
$reserve->{reserve_id}, $reserve_id,
"Non-local item fills the hold when exclusivity period is disabled"
);
# 2. Pref active, hold is fresh: non-local item must be skipped.
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityExclusivityPeriod', 7 );
( undef, $reserve ) = CheckReserves($non_local_item);
ok(
!$reserve,
"Non-local item is blocked by exclusivity period when queue targeted a local match"
);
# 3. Push reservedate back past the exclusivity window: should fill again.
$dbh->do(
q{UPDATE reserves SET reservedate = DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY) WHERE reserve_id = ?},
undef, $reserve_id
);
( undef, $reserve ) = CheckReserves($non_local_item);
is(
$reserve->{reserve_id}, $reserve_id,
"Non-local item fills the hold once the exclusivity period has expired"
);
# 4. Remove the hold_fill_targets row: with no queue target we must not block.
$dbh->do( q{UPDATE reserves SET reservedate = CURRENT_DATE WHERE reserve_id = ?}, undef, $reserve_id );
$dbh->do( q{DELETE FROM hold_fill_targets WHERE reserve_id = ?}, undef, $reserve_id );
( undef, $reserve ) = CheckReserves($non_local_item);
is(
$reserve->{reserve_id}, $reserve_id,
"Non-local item fills the hold when no hold_fill_targets row exists for the reserve"
);
$schema->storage->txn_rollback;
};

View File

@ -9,7 +9,7 @@
use Modern::Perl;
use Test::NoWarnings;
use Test::More tests => 65;
use Test::More tests => 67;
use Data::Dumper;
use C4::Calendar;
@ -469,6 +469,18 @@ is(
$holds_queue->[0]->{cardnumber}, $borrower3->{cardnumber},
"Holds queue giving priority to patron who's home library matches item's home library"
);
is(
$holds_queue->[0]->{local_holdgroup_match}, 1,
"tmp_holdsqueue.local_holdgroup_match is set when LocalHoldsPriority finds a local match"
);
my $hft_row = $dbh->selectrow_hashref(
"SELECT local_holdgroup_match FROM hold_fill_targets WHERE borrowernumber = ?",
undef, $borrower3->{borrowernumber}
);
is(
$hft_row->{local_holdgroup_match}, 1,
"hold_fill_targets.local_holdgroup_match is set when LocalHoldsPriority finds a local match"
);
### Test branch transfer limits ###
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );

View File

@ -2316,7 +2316,8 @@ subtest '_Findgroupreserve in the context of hold groups' => sub {
# Fake the holds queue
my $dbh = C4::Context->dbh;
$dbh->do(
q{INSERT INTO hold_fill_targets VALUES (?, ?, ?, ?, ?,?)}, undef,
q{INSERT INTO hold_fill_targets (borrowernumber, biblionumber, itemnumber, source_branchcode, item_level_request, reserve_id) VALUES (?, ?, ?, ?, ?, ?)},
undef,
(
$patron_1->borrowernumber, $item->biblionumber, $item->itemnumber, $item->homebranch, 0,
$first_reserve_id_again

View File

@ -1108,7 +1108,8 @@ subtest 'MoveReserve additional test' => sub {
# Fake the holds queue
$dbh->do(
q{INSERT INTO hold_fill_targets VALUES (?, ?, ?, ?, ?,?)}, undef,
q{INSERT INTO hold_fill_targets (borrowernumber, biblionumber, itemnumber, source_branchcode, item_level_request, reserve_id) VALUES (?, ?, ?, ?, ?, ?)},
undef,
( $patron_1->borrowernumber, $biblio->biblionumber, $item_1->itemnumber, $item_1->homebranch, 0, $reserve_1 )
);