Bug 40636: Add `Koha::Calendar->has_business_days_between()` method
This patch adds a new method to Koha::Calendar that returns a boolean indicating whether there are any business days between two given dates (exclusive). Implementation details: * Returns 1 if any business days exist between start and end dates * Returns 0 for consecutive days, same dates, or only holidays between * Uses exclusive range (does not include start or end dates) * Handles date comparison and timezone normalization * Efficient early return when first business day is found This is designed specifically for use cases like detecting missed business days due to server downtime or scheduling issues. To test: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/Calendar.t => SUCCESS: All tests pass! 3. Sign off :-D Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de> Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
1617927b99
commit
2bfb86afb5
|
|
@ -383,6 +383,28 @@ sub hours_between {
|
|||
return $duration;
|
||||
}
|
||||
|
||||
sub has_business_days_between {
|
||||
my ( $self, $start_dt, $end_dt ) = @_;
|
||||
|
||||
# Clone dates to avoid modifying originals
|
||||
my $current_date = $start_dt->clone->set_time_zone('floating');
|
||||
my $end_date = $end_dt->clone->set_time_zone('floating');
|
||||
|
||||
# Ensure start is before end
|
||||
if ( $current_date->compare($end_date) >= 0 ) {
|
||||
return 0; # Same date or start after end
|
||||
}
|
||||
|
||||
# Check each day between start and end (exclusive)
|
||||
$current_date->add( days => 1 );
|
||||
while ( $current_date->compare($end_date) < 0 ) {
|
||||
return 1 unless $self->is_holiday($current_date);
|
||||
$current_date->add( days => 1 );
|
||||
}
|
||||
|
||||
return 0; # No business days found
|
||||
}
|
||||
|
||||
sub set_daysmode {
|
||||
my ( $self, $mode ) = @_;
|
||||
|
||||
|
|
@ -506,6 +528,22 @@ relative order of the parameters.
|
|||
|
||||
Note: This routine assumes neither the passed start_dt nor end_dt can be a closed day
|
||||
|
||||
=head2 has_business_days_between
|
||||
|
||||
$boolean = $calendar->has_business_days_between($start_dt, $end_dt);
|
||||
|
||||
Passed two DateTime objects, returns 1 if there are any business days (non-holidays)
|
||||
between the start and end dates (exclusive), 0 otherwise.
|
||||
|
||||
This method is useful for determining if business days were missed between two dates,
|
||||
such as when checking if server downtime caused business days to be skipped.
|
||||
|
||||
Examples:
|
||||
- Monday to Wednesday with Tuesday as business day: returns 1
|
||||
- Monday to Tuesday (consecutive days): returns 0
|
||||
- Friday to Sunday with Saturday as holiday: returns 0
|
||||
- Same date: returns 0
|
||||
|
||||
=head2 next_open_days
|
||||
|
||||
$datetime = $calendar->next_open_days($duedate_dt, $to_add)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Copyright 2025 Koha Development team
|
||||
#
|
||||
# This file is part of Koha
|
||||
#
|
||||
# Koha is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Koha is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Koha; if not, see <http://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use Test::More tests => 3;
|
||||
use Test::Exception;
|
||||
use Test::NoWarnings;
|
||||
|
||||
use Koha::Database;
|
||||
use Koha::DateUtils qw( dt_from_string );
|
||||
use t::lib::TestBuilder;
|
||||
|
||||
BEGIN {
|
||||
use_ok('Koha::Calendar');
|
||||
}
|
||||
|
||||
my $schema = Koha::Database->schema;
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
|
||||
subtest 'has_business_days_between' => sub {
|
||||
|
||||
plan tests => 6;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $library = $builder->build_object( { class => 'Koha::Libraries' } );
|
||||
my $branchcode = $library->branchcode;
|
||||
|
||||
# Create test dates
|
||||
my $monday = dt_from_string('2024-01-01'); # Monday
|
||||
my $tuesday = dt_from_string('2024-01-02'); # Tuesday
|
||||
my $wednesday = dt_from_string('2024-01-03'); # Wednesday
|
||||
my $thursday = dt_from_string('2024-01-04'); # Thursday
|
||||
my $friday = dt_from_string('2024-01-05'); # Friday
|
||||
my $saturday = dt_from_string('2024-01-06'); # Saturday
|
||||
my $sunday = dt_from_string('2024-01-07'); # Sunday
|
||||
|
||||
# Make Wednesday a holiday
|
||||
my $wednesday_holiday = $builder->build(
|
||||
{
|
||||
source => 'SpecialHoliday',
|
||||
value => {
|
||||
branchcode => $branchcode,
|
||||
day => $wednesday->day,
|
||||
month => $wednesday->month,
|
||||
year => $wednesday->year,
|
||||
title => 'Wednesday Holiday',
|
||||
isexception => 0
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
# Make Saturday and Sunday holidays (weekend)
|
||||
my $saturday_holiday = $builder->build(
|
||||
{
|
||||
source => 'SpecialHoliday',
|
||||
value => {
|
||||
branchcode => $branchcode,
|
||||
day => $saturday->day,
|
||||
month => $saturday->month,
|
||||
year => $saturday->year,
|
||||
title => 'Saturday Holiday',
|
||||
isexception => 0
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
my $sunday_holiday = $builder->build(
|
||||
{
|
||||
source => 'SpecialHoliday',
|
||||
value => {
|
||||
branchcode => $branchcode,
|
||||
day => $sunday->day,
|
||||
month => $sunday->month,
|
||||
year => $sunday->year,
|
||||
title => 'Sunday Holiday',
|
||||
isexception => 0
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
my $calendar = Koha::Calendar->new( branchcode => $branchcode );
|
||||
|
||||
# Test 1: Business day between two business days
|
||||
is(
|
||||
$calendar->has_business_days_between( $monday, $wednesday ), 1,
|
||||
'Should find business day (Tuesday) between Monday and Wednesday'
|
||||
);
|
||||
|
||||
# Test 2: No business days between consecutive business days
|
||||
is(
|
||||
$calendar->has_business_days_between( $monday, $tuesday ), 0,
|
||||
'Should find no business days between consecutive days'
|
||||
);
|
||||
|
||||
# Test 3: Holiday between two business days
|
||||
is(
|
||||
$calendar->has_business_days_between( $tuesday, $thursday ), 0,
|
||||
'Should find no business days when only holiday (Wednesday) is between'
|
||||
);
|
||||
|
||||
# Test 4: Multiple days with business days
|
||||
is(
|
||||
$calendar->has_business_days_between( $monday, $friday ), 1,
|
||||
'Should find business days between Monday and Friday'
|
||||
);
|
||||
|
||||
# Test 5: Only holidays between dates
|
||||
is(
|
||||
$calendar->has_business_days_between( $friday, $sunday ), 0,
|
||||
'Should find no business days between Friday and Sunday (Saturday is holiday)'
|
||||
);
|
||||
|
||||
# Test 6: Same date
|
||||
is(
|
||||
$calendar->has_business_days_between( $monday, $monday ), 0,
|
||||
'Should find no business days between same date'
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
Loading…
Reference in New Issue