Lines 1-9
Link Here
|
1 |
#!/usr/bin/perl |
1 |
#!/usr/bin/perl |
2 |
|
2 |
|
3 |
use Modern::Perl; |
3 |
use Modern::Perl; |
4 |
use Test::More tests => 5; |
4 |
use Test::More tests => 6; |
5 |
use Test::NoWarnings; |
5 |
use Test::NoWarnings; |
6 |
use Test::MockModule; |
6 |
use Test::MockModule; |
|
|
7 |
use Time::Fake; |
7 |
|
8 |
|
8 |
use t::lib::Mocks; |
9 |
use t::lib::Mocks; |
9 |
use t::lib::TestBuilder; |
10 |
use t::lib::TestBuilder; |
Lines 15-28
use Koha::DateUtils qw( dt_from_string );
Link Here
|
15 |
use Koha::Holds; |
16 |
use Koha::Holds; |
16 |
use Koha::Old::Holds; |
17 |
use Koha::Old::Holds; |
17 |
|
18 |
|
18 |
my $schema = Koha::Database->new->schema; |
19 |
my $builder = t::lib::TestBuilder->new(); |
|
|
20 |
my $schema = Koha::Database->new->schema; |
21 |
|
19 |
$schema->storage->txn_begin; |
22 |
$schema->storage->txn_begin; |
20 |
|
23 |
|
21 |
subtest 'CancelExpiredReserves tests incl. holidays' => sub { |
24 |
subtest 'CancelExpiredReserves tests incl. holidays' => sub { |
22 |
plan tests => 4; |
25 |
plan tests => 4; |
23 |
|
26 |
|
24 |
my $builder = t::lib::TestBuilder->new(); |
|
|
25 |
|
26 |
t::lib::Mocks::mock_preference( 'ExpireReservesOnHolidays', 0 ); |
27 |
t::lib::Mocks::mock_preference( 'ExpireReservesOnHolidays', 0 ); |
27 |
|
28 |
|
28 |
# Waiting holds could be cancelled only if ExpireReservesMaxPickUpDelay is set to "allow", see bug 19260 |
29 |
# Waiting holds could be cancelled only if ExpireReservesMaxPickUpDelay is set to "allow", see bug 19260 |
Lines 119-125
subtest 'Test handling of waiting reserves by CancelExpiredReserves' => sub {
Link Here
|
119 |
|
120 |
|
120 |
Koha::Holds->delete; |
121 |
Koha::Holds->delete; |
121 |
|
122 |
|
122 |
my $builder = t::lib::TestBuilder->new(); |
|
|
123 |
my $category = $builder->build( { source => 'Category' } ); |
123 |
my $category = $builder->build( { source => 'Category' } ); |
124 |
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; |
124 |
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; |
125 |
my $item = $builder->build_sample_item; |
125 |
my $item = $builder->build_sample_item; |
Lines 184-191
subtest 'Test handling of waiting reserves by CancelExpiredReserves' => sub {
Link Here
|
184 |
subtest 'Test handling of in transit reserves by CancelExpiredReserves' => sub { |
184 |
subtest 'Test handling of in transit reserves by CancelExpiredReserves' => sub { |
185 |
plan tests => 2; |
185 |
plan tests => 2; |
186 |
|
186 |
|
187 |
my $builder = t::lib::TestBuilder->new(); |
|
|
188 |
|
189 |
t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 ); |
187 |
t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 ); |
190 |
my $expdate = dt_from_string->add( days => -2 ); |
188 |
my $expdate = dt_from_string->add( days => -2 ); |
191 |
my $reserve = $builder->build( |
189 |
my $reserve = $builder->build( |
Lines 225-232
subtest 'Test handling of in transit reserves by CancelExpiredReserves' => sub {
Link Here
|
225 |
subtest 'Test handling of cancellation reason if passed' => sub { |
223 |
subtest 'Test handling of cancellation reason if passed' => sub { |
226 |
plan tests => 2; |
224 |
plan tests => 2; |
227 |
|
225 |
|
228 |
my $builder = t::lib::TestBuilder->new(); |
|
|
229 |
|
230 |
my $expdate = dt_from_string->add( days => -2 ); |
226 |
my $expdate = dt_from_string->add( days => -2 ); |
231 |
my $reserve = $builder->build( |
227 |
my $reserve = $builder->build( |
232 |
{ |
228 |
{ |
Lines 254-257
subtest 'Test handling of cancellation reason if passed' => sub {
Link Here
|
254 |
is( $old_reserve->cancellation_reason, 'EXPIRED', "Hold cancellation_reason was set correctly" ); |
250 |
is( $old_reserve->cancellation_reason, 'EXPIRED', "Hold cancellation_reason was set correctly" ); |
255 |
}; |
251 |
}; |
256 |
|
252 |
|
|
|
253 |
subtest 'Holiday logic edge cases' => sub { |
254 |
|
255 |
plan tests => 2; |
256 |
|
257 |
subtest 'Hold expired on business day should be cancelled retrospectively when script runs on holiday' => sub { |
258 |
plan tests => 1; |
259 |
|
260 |
$schema->storage->txn_begin; |
261 |
|
262 |
t::lib::Mocks::mock_preference( 'ExpireReservesOnHolidays', 0 ); |
263 |
t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 ); |
264 |
|
265 |
# Clear any existing holidays from previous tests |
266 |
Koha::Caches->get_instance()->flush_all(); |
267 |
|
268 |
# Create a library for our tests |
269 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
270 |
|
271 |
# The bug scenario: Hold expired on Monday (business day), script runs on Wednesday (holiday) |
272 |
# The hold SHOULD be cancelled because it expired on a business day and Tuesday was a business day |
273 |
# that was missed, so we need retrospective cancellation even though today is a holiday |
274 |
|
275 |
my $monday = dt_from_string('2024-01-15'); # Monday (business day, hold expires) |
276 |
my $wednesday = dt_from_string('2024-01-17'); # Wednesday (holiday, script runs now) |
277 |
|
278 |
# Create a hold that expired on Monday (business day) |
279 |
my $hold_expired_monday = $builder->build_object( |
280 |
{ |
281 |
class => 'Koha::Holds', |
282 |
value => { |
283 |
branchcode => $library->branchcode, |
284 |
patron_expiration_date => $monday->ymd, |
285 |
expirationdate => $monday->ymd, |
286 |
cancellationdate => undef, |
287 |
priority => 0, |
288 |
found => 'W', |
289 |
}, |
290 |
} |
291 |
); |
292 |
|
293 |
# Make Wednesday a holiday (but Monday and Tuesday are business days) |
294 |
my $wednesday_holiday = $builder->build( |
295 |
{ |
296 |
source => 'SpecialHoliday', |
297 |
value => { |
298 |
branchcode => $library->branchcode, |
299 |
day => $wednesday->day, |
300 |
month => $wednesday->month, |
301 |
year => $wednesday->year, |
302 |
title => 'Wednesday Holiday', |
303 |
isexception => 0 |
304 |
}, |
305 |
} |
306 |
); |
307 |
|
308 |
# Clear cache so holiday is recognized |
309 |
Koha::Caches->get_instance()->flush_all(); |
310 |
|
311 |
# Set fake time to Wednesday (holiday) |
312 |
Time::Fake->offset( $wednesday->epoch ); |
313 |
|
314 |
# The hold SHOULD be cancelled because: |
315 |
# 1. It expired on Monday (business day) |
316 |
# 2. Tuesday was a business day that was missed |
317 |
# 3. Even though today (Wednesday) is a holiday, we need retrospective cancellation |
318 |
CancelExpiredReserves(); |
319 |
|
320 |
my $hold_check = Koha::Holds->find( $hold_expired_monday->id ); |
321 |
is( |
322 |
$hold_check, undef, |
323 |
'Hold that expired on business day should be cancelled retrospectively even when script runs on holiday' |
324 |
); |
325 |
|
326 |
# Reset time |
327 |
Time::Fake->reset; |
328 |
|
329 |
$schema->storage->txn_rollback; |
330 |
}; |
331 |
|
332 |
subtest 'Hold expired on holiday should not be cancelled when script runs on same holiday' => sub { |
333 |
plan tests => 1; |
334 |
|
335 |
$schema->storage->txn_begin; |
336 |
|
337 |
t::lib::Mocks::mock_preference( 'ExpireReservesOnHolidays', 0 ); |
338 |
t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 ); |
339 |
|
340 |
# Clear any existing holidays from previous tests |
341 |
Koha::Caches->get_instance()->flush_all(); |
342 |
|
343 |
# Create a library for our tests |
344 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
345 |
|
346 |
# Control scenario: Hold expired on Monday (holiday), script runs on Monday (same holiday) |
347 |
# The hold should NOT be cancelled because it expired today and today is a holiday |
348 |
|
349 |
my $monday = dt_from_string('2024-01-15'); # Monday (holiday, hold expires and script runs) |
350 |
|
351 |
# Create a hold that expired on Monday (holiday) |
352 |
my $hold_expired_monday = $builder->build_object( |
353 |
{ |
354 |
class => 'Koha::Holds', |
355 |
value => { |
356 |
branchcode => $library->branchcode, |
357 |
patron_expiration_date => $monday->ymd, |
358 |
expirationdate => $monday->ymd, |
359 |
cancellationdate => undef, |
360 |
priority => 0, |
361 |
found => 'W', |
362 |
}, |
363 |
} |
364 |
); |
365 |
|
366 |
# Make Monday a holiday |
367 |
my $monday_holiday = $builder->build( |
368 |
{ |
369 |
source => 'SpecialHoliday', |
370 |
value => { |
371 |
branchcode => $library->branchcode, |
372 |
day => $monday->day, |
373 |
month => $monday->month, |
374 |
year => $monday->year, |
375 |
title => 'Monday Holiday', |
376 |
isexception => 0 |
377 |
}, |
378 |
} |
379 |
); |
380 |
|
381 |
# Clear cache so holiday is recognized |
382 |
Koha::Caches->get_instance()->flush_all(); |
383 |
|
384 |
# Set fake time to Monday (holiday) |
385 |
Time::Fake->offset( $monday->epoch ); |
386 |
|
387 |
# The hold should NOT be cancelled because it expired today and today is a holiday |
388 |
CancelExpiredReserves(); |
389 |
|
390 |
my $hold_check = Koha::Holds->find( $hold_expired_monday->id ); |
391 |
ok( |
392 |
$hold_check, |
393 |
'Hold that expired on holiday should not be cancelled when script runs on same holiday' |
394 |
); |
395 |
|
396 |
# Reset time |
397 |
Time::Fake->reset; |
398 |
|
399 |
$schema->storage->txn_rollback; |
400 |
}; |
401 |
}; |
402 |
|
257 |
$schema->storage->txn_rollback; |
403 |
$schema->storage->txn_rollback; |
258 |
- |
|
|