Bug 42310: (QA follow-up) Add closed_dates_in_range to Koha::Calendar
Introduces a public Koha::Calendar->closed_dates_in_range($from_dt, $to_dt) method that returns an arrayref of ISO date strings representing every closed day in the inclusive range, honouring weekly, annual repeating, single and exception (open-override) closures. This replaces callers that were reaching into Koha::Calendar private state (_holidays, weekly_closed_days, day_month_closed_days) to reconstruct the same logic. A follow-up under Bug 42206 converts the REST controller; further callers can be migrated incrementally. Test plan: 1. prove t/db_dependent/Koha/Calendar.t 2. Verify the new 'closed_dates_in_range' subtest passes Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
parent
5875ce4c75
commit
7a8a220842
|
|
@ -484,6 +484,38 @@ sub delete_exception {
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub closed_dates_in_range {
|
||||||
|
my ( $self, $from_dt, $to_dt ) = @_;
|
||||||
|
|
||||||
|
croak 'Missing from_dt in closed_dates_in_range' unless $from_dt;
|
||||||
|
croak 'Missing to_dt in closed_dates_in_range' unless $to_dt;
|
||||||
|
|
||||||
|
my $holidays = $self->_holidays;
|
||||||
|
|
||||||
|
my @closed;
|
||||||
|
my $current = $from_dt->clone;
|
||||||
|
while ( $current <= $to_dt ) {
|
||||||
|
my $ymd = $current->ymd('');
|
||||||
|
|
||||||
|
# Exception (open override) wins over any other closure rule.
|
||||||
|
if ( defined $holidays->{$ymd} && $holidays->{$ymd} == 0 ) {
|
||||||
|
$current->add( days => 1 );
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( defined $holidays->{$ymd} && $holidays->{$ymd} == 1 )
|
||||||
|
|| $self->{weekly_closed_days}->[ $current->day_of_week % 7 ]
|
||||||
|
|| $self->{day_month_closed_days}->{ $current->month }->{ $current->day } )
|
||||||
|
{
|
||||||
|
push @closed, $current->ymd;
|
||||||
|
}
|
||||||
|
|
||||||
|
$current->add( days => 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return \@closed;
|
||||||
|
}
|
||||||
|
|
||||||
sub copy_to {
|
sub copy_to {
|
||||||
my ( $self, $target_branchcode ) = @_;
|
my ( $self, $target_branchcode ) = @_;
|
||||||
croak "No target_branchcode" unless $target_branchcode;
|
croak "No target_branchcode" unless $target_branchcode;
|
||||||
|
|
@ -771,6 +803,17 @@ list of specified dates
|
||||||
|
|
||||||
$calendar->delete_exception({ date => '2026-12-25' });
|
$calendar->delete_exception({ date => '2026-12-25' });
|
||||||
|
|
||||||
|
=head3 closed_dates_in_range
|
||||||
|
|
||||||
|
my $dates = $calendar->closed_dates_in_range($from_dt, $to_dt);
|
||||||
|
|
||||||
|
Returns an arrayref of ISO date strings (YYYY-MM-DD) representing every
|
||||||
|
closed day between C<$from_dt> and C<$to_dt> (inclusive), taking
|
||||||
|
weekly, annual-repeating, single and exception (open override)
|
||||||
|
closures into account. Exceptions win: a date listed as an exception
|
||||||
|
is never returned even if a weekly or repeating rule would otherwise
|
||||||
|
close it.
|
||||||
|
|
||||||
=head3 copy_to
|
=head3 copy_to
|
||||||
|
|
||||||
$calendar->copy_to($target_branchcode);
|
$calendar->copy_to($target_branchcode);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
use Modern::Perl;
|
use Modern::Perl;
|
||||||
|
|
||||||
use Test::More tests => 5;
|
use Test::More tests => 6;
|
||||||
use Test::Exception;
|
use Test::Exception;
|
||||||
use Test::NoWarnings;
|
use Test::NoWarnings;
|
||||||
|
|
||||||
|
|
@ -229,6 +229,49 @@ subtest 'CRUD methods' => sub {
|
||||||
$schema->storage->txn_rollback;
|
$schema->storage->txn_rollback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
subtest 'closed_dates_in_range' => sub {
|
||||||
|
|
||||||
|
plan tests => 5;
|
||||||
|
|
||||||
|
$schema->storage->txn_begin;
|
||||||
|
|
||||||
|
my $library = $builder->build_object( { class => 'Koha::Libraries' } );
|
||||||
|
my $branchcode = $library->branchcode;
|
||||||
|
|
||||||
|
# Sunday closed every week, 25 December every year, 2026-06-15 single,
|
||||||
|
# 2026-12-25 open exception (overrides the repeating rule).
|
||||||
|
$builder->build_object(
|
||||||
|
{ class => 'Koha::Calendar::WeeklyClosures', value => { library_id => $branchcode, weekday => 0 } } );
|
||||||
|
$builder->build_object(
|
||||||
|
{
|
||||||
|
class => 'Koha::Calendar::RepeatingClosures',
|
||||||
|
value => { library_id => $branchcode, day => 25, month => 12 }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$builder->build_object(
|
||||||
|
{ class => 'Koha::Calendar::SingleClosures', value => { library_id => $branchcode, date => '2026-06-15' } } );
|
||||||
|
$builder->build_object(
|
||||||
|
{ class => 'Koha::Calendar::Exceptions', value => { library_id => $branchcode, date => '2026-12-25' } } );
|
||||||
|
|
||||||
|
my $calendar = Koha::Calendar->new( branchcode => $branchcode );
|
||||||
|
|
||||||
|
my $closed = $calendar->closed_dates_in_range( dt_from_string('2026-06-14'), dt_from_string('2026-06-16') );
|
||||||
|
is_deeply( $closed, [ '2026-06-14', '2026-06-15' ], 'Sunday and single closure returned' );
|
||||||
|
|
||||||
|
$closed = $calendar->closed_dates_in_range( dt_from_string('2026-12-24'), dt_from_string('2026-12-26') );
|
||||||
|
is_deeply( $closed, [], 'Exception suppresses repeating closure on 2026-12-25' );
|
||||||
|
|
||||||
|
$closed = $calendar->closed_dates_in_range( dt_from_string('2027-06-15'), dt_from_string('2027-06-15') );
|
||||||
|
is_deeply( $closed, [], 'Open Tuesday not returned' );
|
||||||
|
|
||||||
|
$closed = $calendar->closed_dates_in_range( dt_from_string('2027-12-25'), dt_from_string('2027-12-25') );
|
||||||
|
is_deeply( $closed, ['2027-12-25'], 'Repeating closure returned in a year with no exception' );
|
||||||
|
|
||||||
|
throws_ok { $calendar->closed_dates_in_range() } qr/Missing from_dt/, 'croaks without from_dt';
|
||||||
|
|
||||||
|
$schema->storage->txn_rollback;
|
||||||
|
};
|
||||||
|
|
||||||
subtest 'delete_*_closure clears _holidays cache' => sub {
|
subtest 'delete_*_closure clears _holidays cache' => sub {
|
||||||
|
|
||||||
plan tests => 4;
|
plan tests => 4;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue