From 194a271ab20d183e48e4850a0867be9ea07900ff Mon Sep 17 00:00:00 2001 From: Charles Farmer Date: Wed, 4 Sep 2019 14:58:02 -0400 Subject: [PATCH] Bug 17015: Tests for DiscreteCalendar Signed-off-by: Michal Denar Bug 17015: Rebase and tests for discrete calendar This patch is a rebase of all the previous patches in order to show the discrete calendar. TEST PLAN: 1- Apply the patch 2- Run installer/data/mysql/updatedatabase.pl 3- Run misc/cronjobs/add_days_discrete_calendar.pl 4- Check that the max date is today + 1 day 5- Run t/db_dependent/DiscreteCalendar.t (All tests should pass) Signed-off-by: Michal Denar --- C4/Reserves.pm | 3 - t/db_dependent/Calendar.t | 717 ------------------ t/db_dependent/Circulation.t | 75 +- t/db_dependent/Circulation/CalcDateDue.t | 225 +++--- .../Circulation/maxsuspensiondays.t | 9 +- t/db_dependent/DiscreteCalendar.t | 464 ++++++++++++ t/db_dependent/Hold.t | 14 +- t/db_dependent/Holds.t | 1 - t/db_dependent/Holds/WaitingReserves.t | 35 +- t/db_dependent/HoldsQueue.t | 15 +- t/db_dependent/Holidays.t | 340 --------- t/db_dependent/Koha/Charges/Fees.t | 46 +- t/db_dependent/Koha/CurbsidePickups.t | 24 +- t/db_dependent/Koha/ItemTypes.t | 1 - .../Reserves/CancelExpiredReserves.t | 15 +- t/lib/TestBuilder.pm | 6 + 16 files changed, 742 insertions(+), 1248 deletions(-) delete mode 100755 t/db_dependent/Calendar.t create mode 100755 t/db_dependent/DiscreteCalendar.t delete mode 100755 t/db_dependent/Holidays.t diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 6b11a4abbf..88e03e4106 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -35,10 +35,7 @@ use C4::Members; use Koha::Account::Lines; use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue; use Koha::Biblios; -<<<<<<< HEAD use Koha::Cache::Memory::Lite; -======= ->>>>>>> Bug 17015: DiscreteCalendar UI, Back-End and necessary scripts use Koha::CirculationRules; use Koha::Database; use Koha::DateUtils qw( dt_from_string output_pref ); diff --git a/t/db_dependent/Calendar.t b/t/db_dependent/Calendar.t deleted file mode 100755 index 40b99bc795..0000000000 --- a/t/db_dependent/Calendar.t +++ /dev/null @@ -1,717 +0,0 @@ -#!/usr/bin/perl - -# 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 . - -use Modern::Perl; - -use Test::More tests => 6; -use Time::Fake; - -use t::lib::Mocks; -use t::lib::TestBuilder; - -use DateTime; -use DateTime::Duration; -use Koha::Caches; -use Koha::Calendar; -use Koha::Database; -use Koha::DateUtils qw( dt_from_string ); - -my $schema = Koha::Database->new->schema; -my $builder = t::lib::TestBuilder->new; -$schema->storage->txn_begin; - -my $today = dt_from_string(); -my $holiday_dt = $today->clone; -$holiday_dt->add( days => 3 ); - -Koha::Caches->get_instance()->flush_all(); - -subtest 'Original tests from t' => sub { - - # We need to mock the C4::Context->preference method for - # simplicity and re-usability of the session definition. Any - # syspref fits for syspref-agnostic tests. - my $module_context = Test::MockModule->new('C4::Context'); - $module_context->mock( - 'preference', - sub { - return 'Calendar'; - } - ); - - my $mpl = $builder->build_object( { class => 'Koha::Libraries' } )->branchcode; - my $cpl = $builder->build_object( { class => 'Koha::Libraries' } )->branchcode; - my $rows = [ # add weekly holidays - { branchcode => $mpl, weekday => 0 }, # sundays - { branchcode => $mpl, weekday => 6 }, # saturdays - { branchcode => $mpl, day => 1, month => 1 }, # new year's day - { branchcode => $mpl, day => 25, month => 12 }, # chrismas - ]; - $schema->resultset('RepeatableHoliday')->delete_all; - $schema->resultset('RepeatableHoliday')->create( { %$_, description => q{} } ) for @$rows; - - $rows = [ # exception holidays - { branchcode => $mpl, day => 11, month => 11, year => 2012, isexception => 1 }, # sunday exception - { branchcode => $mpl, day => 1, month => 6, year => 2011, isexception => 0 }, - { branchcode => $mpl, day => 4, month => 7, year => 2012, isexception => 0 }, - { branchcode => $cpl, day => 6, month => 8, year => 2012, isexception => 0 }, - { branchcode => $mpl, day => 7, month => 7, year => 2012, isexception => 1 }, # holiday exception - { branchcode => $mpl, day => 7, month => 7, year => 2012, isexception => 0 }, # holiday - ]; - $schema->resultset('SpecialHoliday')->delete_all; - $schema->resultset('SpecialHoliday')->create( { %$_, description => q{} } ) for @$rows; - - my $cache = Koha::Caches->get_instance(); - $cache->clear_from_cache( $mpl . '_holidays' ); - $cache->clear_from_cache( $cpl . '_holidays' ); - - # $mpl branch is arbitrary, is not used at all but is needed for initialization - my $cal = Koha::Calendar->new( branchcode => $mpl ); - - isa_ok( $cal, 'Koha::Calendar', 'Calendar class returned' ); - - my $saturday = DateTime->new( - year => 2012, - month => 11, - day => 24, - ); - - my $sunday = DateTime->new( - year => 2012, - month => 11, - day => 25, - ); - - my $monday = DateTime->new( - year => 2012, - month => 11, - day => 26, - ); - - my $new_year = DateTime->new( - year => 2013, - month => 1, - day => 1, - ); - - my $single_holiday = DateTime->new( - year => 2011, - month => 6, - day => 1, - ); # should be a holiday - - my $notspecial = DateTime->new( - year => 2011, - month => 6, - day => 2 - ); # should NOT be a holiday - - my $sunday_exception = DateTime->new( - year => 2012, - month => 11, - day => 11 - ); - - my $day_after_christmas = DateTime->new( - year => 2012, - month => 12, - day => 26 - ); # for testing negative addDuration - - my $holiday_for_another_branch = DateTime->new( - year => 2012, - month => 8, - day => 6, # This is a monday - ); - - my $holiday_excepted = DateTime->new( - year => 2012, - month => 7, - day => 7, # Both a holiday and exception - ); - - { # Syspref-agnostic tests - is( $saturday->day_of_week, 6, '\'$saturday\' is actually a saturday (6th day of week)' ); - is( $sunday->day_of_week, 7, '\'$sunday\' is actually a sunday (7th day of week)' ); - is( $monday->day_of_week, 1, '\'$monday\' is actually a monday (1st day of week)' ); - is( $cal->is_holiday($saturday), 1, 'Saturday is a closed day' ); - is( $cal->is_holiday($sunday), 1, 'Sunday is a closed day' ); - is( $cal->is_holiday($monday), 0, 'Monday is not a closed day' ); - is( $cal->is_holiday($new_year), 1, 'Month/Day closed day test (New year\'s day)' ); - is( $cal->is_holiday($single_holiday), 1, 'Single holiday closed day test' ); - is( $cal->is_holiday($notspecial), 0, 'Fixed single date that is not a holiday test' ); - is( $cal->is_holiday($sunday_exception), 0, 'Exception holiday is not a closed day test' ); - is( - $cal->is_holiday($holiday_for_another_branch), 0, - 'Holiday defined for another branch should not be defined as an holiday' - ); - is( $cal->is_holiday($holiday_excepted), 0, 'Holiday defined and excepted should not be a holiday' ); - } - - { # Bugzilla #8966 - is_holiday truncates referenced date - my $later_dt = DateTime->new( # Monday - year => 2012, - month => 9, - day => 17, - hour => 17, - minute => 30, - time_zone => 'Europe/London', - ); - - is( $cal->is_holiday($later_dt), 0, 'bz-8966 (1/2) Apply is_holiday for the next test' ); - cmp_ok( $later_dt, 'eq', '2012-09-17T17:30:00', 'bz-8966 (2/2) Date should be the same after is_holiday' ); - } - - { # Bugzilla #8800 - is_holiday should use truncated date for 'contains' call - my $single_holiday_time = DateTime->new( - year => 2011, - month => 6, - day => 1, - hour => 11, - minute => 2 - ); - - is( - $cal->is_holiday($single_holiday_time), - $cal->is_holiday($single_holiday), - 'bz-8800 is_holiday should truncate the date for holiday validation' - ); - } - - my $one_day_dur = DateTime::Duration->new( days => 1 ); - my $two_day_dur = DateTime::Duration->new( days => 2 ); - my $seven_day_dur = DateTime::Duration->new( days => 7 ); - - my $dt = dt_from_string( '2012-07-03', 'iso' ); #tuesday - - my $test_dt = DateTime->new( # Monday - year => 2012, - month => 7, - day => 23, - hour => 11, - minute => 53, - ); - - my $later_dt = DateTime->new( # Monday - year => 2012, - month => 9, - day => 17, - hour => 17, - minute => 30, - time_zone => 'Europe/London', - ); - - { ## 'Datedue' tests - - $cal = Koha::Calendar->new( branchcode => $mpl, days_mode => 'Datedue' ); - - is( - $cal->addDuration( $dt, $one_day_dur, 'days' ), # tuesday - dt_from_string( '2012-07-05', 'iso' ), - 'Single day add (Datedue, matches holiday, shift)' - ); - - is( - $cal->addDuration( $dt, $two_day_dur, 'days' ), - dt_from_string( '2012-07-05', 'iso' ), - 'Two days add, skips holiday (Datedue)' - ); - - cmp_ok( - $cal->addDuration( $test_dt, $seven_day_dur, 'days' ), 'eq', - '2012-07-30T11:53:00', - 'Add 7 days (Datedue)' - ); - - is( - $cal->addDuration( $saturday, $one_day_dur, 'days' )->day_of_week, 1, - 'addDuration skips closed Sunday (Datedue)' - ); - - is( - $cal->addDuration( $day_after_christmas, -1, 'days' )->ymd(), '2012-12-24', - 'Negative call to addDuration (Datedue)' - ); - - ## Note that the days_between API says closed days are not considered. - ## This tests are here as an API test. - cmp_ok( - $cal->days_between( $test_dt, $later_dt )->in_units('days'), - '==', 40, 'days_between calculates correctly (Days)' - ); - - cmp_ok( - $cal->days_between( $later_dt, $test_dt )->in_units('days'), - '==', 40, 'Test parameter order not relevant (Days)' - ); - } - - { ## 'Calendar' tests' - - $cal = Koha::Calendar->new( branchcode => $mpl, days_mode => 'Calendar' ); - - $dt = dt_from_string( '2012-07-03', 'iso' ); - - is( - $cal->addDuration( $dt, $one_day_dur, 'days' ), - dt_from_string( '2012-07-05', 'iso' ), - 'Single day add (Calendar)' - ); - - cmp_ok( - $cal->addDuration( $test_dt, $seven_day_dur, 'days' ), 'eq', - '2012-08-01T11:53:00', - 'Add 7 days (Calendar)' - ); - - is( - $cal->addDuration( $saturday, $one_day_dur, 'days' )->day_of_week, 1, - 'addDuration skips closed Sunday (Calendar)' - ); - - is( - $cal->addDuration( $day_after_christmas, -1, 'days' )->ymd(), '2012-12-24', - 'Negative call to addDuration (Calendar)' - ); - - cmp_ok( - $cal->days_between( $test_dt, $later_dt )->in_units('days'), - '==', 40, 'days_between calculates correctly (Calendar)' - ); - - cmp_ok( - $cal->days_between( $later_dt, $test_dt )->in_units('days'), - '==', 40, 'Test parameter order not relevant (Calendar)' - ); - } - - { ## 'Days' tests - - $cal = Koha::Calendar->new( branchcode => $mpl, days_mode => 'Days' ); - - $dt = dt_from_string( '2012-07-03', 'iso' ); - - is( - $cal->addDuration( $dt, $one_day_dur, 'days' ), - dt_from_string( '2012-07-04', 'iso' ), - 'Single day add (Days)' - ); - - cmp_ok( - $cal->addDuration( $test_dt, $seven_day_dur, 'days' ), 'eq', - '2012-07-30T11:53:00', - 'Add 7 days (Days)' - ); - - is( - $cal->addDuration( $saturday, $one_day_dur, 'days' )->day_of_week, 7, - 'addDuration doesn\'t skip closed Sunday (Days)' - ); - - is( - $cal->addDuration( $day_after_christmas, -1, 'days' )->ymd(), '2012-12-25', - 'Negative call to addDuration (Days)' - ); - - ## Note that the days_between API says closed days are not considered. - ## This tests are here as an API test. - cmp_ok( - $cal->days_between( $test_dt, $later_dt )->in_units('days'), - '==', 40, 'days_between calculates correctly (Days)' - ); - - cmp_ok( - $cal->days_between( $later_dt, $test_dt )->in_units('days'), - '==', 40, 'Test parameter order not relevant (Days)' - ); - - } - - { - $cal = Koha::Calendar->new( branchcode => $cpl ); - is( $cal->is_holiday($single_holiday), 0, 'Single holiday for MPL, not CPL' ); - is( - $cal->is_holiday($holiday_for_another_branch), 1, - 'Holiday defined for CPL should be defined as an holiday' - ); - } - - subtest 'days_mode parameter' => sub { - plan tests => 1; - - t::lib::Mocks::mock_preference( 'useDaysMode', 'Days' ); - - $cal = Koha::Calendar->new( branchcode => $cpl, days_mode => 'Calendar' ); - is( $cal->{days_mode}, 'Calendar', q|If set, days_mode is correctly set| ); - }; - - $cache->clear_from_cache( $mpl . '_holidays' ); - $cache->clear_from_cache( $cpl . '_holidays' ); -}; - -my $library = $builder->build_object( { class => 'Koha::Libraries' } ); -my $calendar = Koha::Calendar->new( branchcode => $library->branchcode, days_mode => 'Calendar' ); -my $holiday = $builder->build( - { - source => 'SpecialHoliday', - value => { - branchcode => $library->branchcode, - day => $holiday_dt->day, - month => $holiday_dt->month, - year => $holiday_dt->year, - title => 'My holiday', - isexception => 0 - }, - } -); - -subtest 'days_forward' => sub { - plan tests => 4; - - my $forwarded_dt = $calendar->days_forward( $today, 2 ); - my $expected = $today->clone->add( days => 2 ); - is( $forwarded_dt->ymd, $expected->ymd, 'With no holiday on the perioddays_forward should add 2 days' ); - - $forwarded_dt = $calendar->days_forward( $today, 5 ); - $expected = $today->clone->add( days => 6 ); - is( - $forwarded_dt->ymd, $expected->ymd, - 'With holiday on the perioddays_forward should add 5 days + 1 day for holiday' - ); - - $forwarded_dt = $calendar->days_forward( $today, 0 ); - is( $forwarded_dt->ymd, $today->ymd, '0 day should return start dt' ); - - $forwarded_dt = $calendar->days_forward( $today, -2 ); - is( $forwarded_dt->ymd, $today->ymd, 'negative day should return start dt' ); -}; - -subtest 'crossing_DST' => sub { - - plan tests => 3; - - my $tz = DateTime::TimeZone->new( name => 'America/New_York' ); - my $start_date = dt_from_string( "2016-03-09 02:29:00", undef, $tz ); - my $end_date = dt_from_string( "2017-01-01 00:00:00", undef, $tz ); - my $days_between = $calendar->days_between( $start_date, $end_date ); - is( $days_between->delta_days, 298, "Days calculated correctly" ); - $days_between = $calendar->days_between( $end_date, $start_date ); - is( $days_between->delta_days, 298, "Swapping returns the same" ); - my $hours_between = $calendar->hours_between( $start_date, $end_date ); - is( - $hours_between->delta_minutes, - 298 * 24 * 60 - 149, - "Hours (in minutes) calculated correctly" - ); -}; - -subtest 'hours_between | days_between' => sub { - - plan tests => 2; - - # November 2019 - # Su Mo Tu We Th Fr Sa - # 1 2 - # 3 4 *5* 6 7 8 9 - # 10 11 12 13 14 15 16 - # 17 18 19 20 21 22 23 - # 24 25 26 27 28 29 30 - - my $now = dt_from_string('2019-11-05 12:34:56'); # Today is 2019 Nov 5th - my $nov_6 = dt_from_string('2019-11-06 12:34:56'); - my $nov_7 = dt_from_string('2019-11-07 12:34:56'); - my $nov_12 = dt_from_string('2019-11-12 12:34:56'); - my $nov_13 = dt_from_string('2019-11-13 12:34:56'); - my $nov_15 = dt_from_string('2019-11-15 12:34:56'); - Time::Fake->offset( $now->epoch ); - - subtest 'No holiday' => sub { - - plan tests => 2; - - my $library = $builder->build_object( { class => 'Koha::Libraries' } ); - my $calendar = Koha::Calendar->new( branchcode => $library->branchcode ); - - subtest 'Same hours' => sub { - - plan tests => 8; - - # Between 5th and 6th - my $diff_hours = $calendar->hours_between( $now, $nov_6 )->hours; - is( $diff_hours, 1 * 24, 'hours: 1 day, no holiday' ); - my $diff_days = $calendar->days_between( $now, $nov_6 )->delta_days; - is( $diff_days, 1, 'days: 1 day, no holiday' ); - - # Between 5th and 7th - $diff_hours = $calendar->hours_between( $now, $nov_7 )->hours; - is( $diff_hours, 2 * 24, 'hours: 2 days, no holiday' ); - $diff_days = $calendar->days_between( $now, $nov_7 )->delta_days; - is( $diff_days, 2, 'days: 2 days, no holiday' ); - - # Between 5th and 12th - $diff_hours = $calendar->hours_between( $now, $nov_12 )->hours; - is( $diff_hours, 7 * 24, 'hours: 7 days, no holiday' ); - $diff_days = $calendar->days_between( $now, $nov_12 )->delta_days; - is( $diff_days, 7, 'days: 7 days, no holiday' ); - - # Between 5th and 15th - $diff_hours = $calendar->hours_between( $now, $nov_15 )->hours; - is( $diff_hours, 10 * 24, 'hours: 10 days, no holiday' ); - $diff_days = $calendar->days_between( $now, $nov_15 )->delta_days; - is( $diff_days, 10, 'days: 10 days, no holiday' ); - }; - - subtest 'Different hours' => sub { - - plan tests => 10; - - # Between 5th and 5th (Same day short hours loan) - my $diff_hours = $calendar->hours_between( $now, $now->clone->add( hours => 3 ) )->hours; - is( $diff_hours, 3, 'hours: 3 hours, no holidays' ); - my $diff_days = $calendar->days_between( $now, $now->clone->add( hours => 3 ) )->delta_days; - is( $diff_days, 0, 'days: 3 hours, no holidays' ); - - # Between 5th and 6th - $diff_hours = $calendar->hours_between( $now, $nov_6->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 1 * 24 - 3, 'hours: 21 hours, no holidays' ); - $diff_days = $calendar->days_between( $now, $nov_6->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 1, 'days: 21 hours, no holidays' ); - - # Between 5th and 7th - $diff_hours = $calendar->hours_between( $now, $nov_7->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 2 * 24 - 3, 'hours: 45 hours, no holidays' ); - $diff_days = $calendar->days_between( $now, $nov_7->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 2, 'days: 45 hours, no holidays' ); - - # Between 5th and 12th - $diff_hours = $calendar->hours_between( $now, $nov_12->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 7 * 24 - 3, 'hours: 165 hours, no holidays' ); - $diff_days = $calendar->days_between( $now, $nov_12->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 7, 'days: 165 hours, no holidays' ); - - # Between 5th and 15th - $diff_hours = $calendar->hours_between( $now, $nov_15->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 10 * 24 - 3, 'hours: 237 hours, no holidays' ); - $diff_days = $calendar->days_between( $now, $nov_15->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 10, 'days: 237 hours, no holidays' ); - }; - }; - - subtest 'With holiday' => sub { - plan tests => 2; - - my $library = $builder->build_object( { class => 'Koha::Libraries' } ); - - # Wednesdays are closed - my $dbh = C4::Context->dbh; - $dbh->do( - q| - INSERT INTO repeatable_holidays (branchcode,weekday,day,month,title,description) - VALUES ( ?, ?, NULL, NULL, ?, '' ) - |, undef, $library->branchcode, 3, 'Closed on Wednesday' - ); - - my $calendar = Koha::Calendar->new( branchcode => $library->branchcode ); - - subtest 'Same hours' => sub { - plan tests => 12; - - my ( $diff_hours, $diff_days ); - - # Between 5th and 6th (This case should never happen in real code, one cannot return on a closed day) - $diff_hours = $calendar->hours_between( $now, $nov_6 )->hours; - is( $diff_hours, 0 * 24, 'hours: 1 day, end_dt = holiday' ); # FIXME Is this really should be 0? - $diff_days = $calendar->days_between( $now, $nov_6 )->delta_days; - is( $diff_days, 0, 'days: 1 day, end_dt = holiday' ); # FIXME Is this really should be 0? - - # Between 6th and 7th (This case should never happen in real code, one cannot issue on a closed day) - $diff_hours = $calendar->hours_between( $nov_6, $nov_7 )->hours; - is( $diff_hours, 0 * 24, 'hours: 1 day, start_dt = holiday' ); # FIXME Is this really should be 0? - $diff_days = $calendar->days_between( $nov_6, $nov_7 )->delta_days; - is( $diff_days, 0, 'days: 1 day, start_dt = holiday' ); # FIXME Is this really should be 0? - - # Between 5th and 7th - $diff_hours = $calendar->hours_between( $now, $nov_7 )->hours; - is( $diff_hours, 2 * 24 - 1 * 24, 'hours: 2 days, 1 holiday' ); - $diff_days = $calendar->days_between( $now, $nov_7 )->delta_days; - is( $diff_days, 2 - 1, 'days: 2 days, 1 holiday' ); - - # Between 5th and 12th - $diff_hours = $calendar->hours_between( $now, $nov_12 )->hours; - is( $diff_hours, 7 * 24 - 1 * 24, 'hours: 7 days, 1 holiday' ); - $diff_days = $calendar->days_between( $now, $nov_12 )->delta_days; - is( $diff_days, 7 - 1, 'day: 7 days, 1 holiday' ); - - # Between 5th and 13th - $diff_hours = $calendar->hours_between( $now, $nov_13 )->hours; - is( $diff_hours, 8 * 24 - 2 * 24, 'hours: 8 days, 2 holidays' ); - $diff_days = $calendar->days_between( $now, $nov_13 )->delta_days; - is( $diff_days, 8 - 2, 'days: 8 days, 2 holidays' ); - - # Between 5th and 15th - $diff_hours = $calendar->hours_between( $now, $nov_15 )->hours; - is( $diff_hours, 10 * 24 - 2 * 24, 'hours: 10 days, 2 holidays' ); - $diff_days = $calendar->days_between( $now, $nov_15 )->delta_days; - is( $diff_days, 10 - 2, 'days: 10 days, 2 holidays' ); - }; - - subtest 'Different hours' => sub { - plan tests => 14; - - my ( $diff_hours, $diff_days ); - - # Between 5th and 5th (Same day short hours loan) - # No test - Tested above as 5th is an open day - - # Between 5th and 6th (This case should never happen in real code, one cannot return on a closed day) - my $duration = $calendar->hours_between( $now, $nov_6->clone->subtract( hours => 3 ) ); - is( $duration->hours, abs( 0 * 24 - 3 ), 'hours: 21 hours, end_dt = holiday' ) - ; # FIXME $duration->hours always return a abs - is( $duration->is_negative, 1, '? is negative ?' ) - ; # FIXME Do really test for that case in our calls to hours_between? - $duration = $calendar->days_between( $now, $nov_6->clone->subtract( hours => 3 ) ); - is( $duration->hours, abs(0), 'days: 21 hours, end_dt = holiday' ); # FIXME Is this correct? - - # Between 6th and 7th (This case should never happen in real code, one cannot issue on a closed day) - $duration = $calendar->hours_between( $nov_6, $nov_7->clone->subtract( hours => 3 ) ); - is( $duration->hours, abs( 0 * 24 - 3 ), 'hours: 21 hours, start_dt = holiday' ) - ; # FIXME $duration->hours always return a abs - is( $duration->is_negative, 1, '? is negative ?' ) - ; # FIXME Do really test for that case in our calls to hours_between? - $duration = $calendar->days_between( $nov_6, $nov_7->clone->subtract( hours => 3 ) ); - is( $duration->hours, abs(0), 'days: 21 hours, start_dt = holiday' ); # FIXME Is this correct? - - # Between 5th and 7th - $diff_hours = $calendar->hours_between( $now, $nov_7->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 2 * 24 - 1 * 24 - 3, 'hours: 45 hours, 1 holiday' ); - $diff_days = $calendar->days_between( $now, $nov_7->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 2 - 1, 'days: 45 hours, 1 holiday' ); - - # Between 5th and 12th - $diff_hours = $calendar->hours_between( $now, $nov_12->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 7 * 24 - 1 * 24 - 3, 'hours: 165 hours, 1 holiday' ); - $diff_days = $calendar->days_between( $now, $nov_12->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 7 - 1, 'days: 165 hours, 1 holiday' ); - - # Between 5th and 13th - $diff_hours = $calendar->hours_between( $now, $nov_13->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 8 * 24 - 2 * 24 - 3, 'hours: 289 hours, 2 holidays ' ); - $diff_days = $calendar->days_between( $now, $nov_13->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 8 - 1, 'days: 289 hours, 2 holidays' ); - - # Between 5th and 15th - $diff_hours = $calendar->hours_between( $now, $nov_15->clone->subtract( hours => 3 ) )->hours; - is( $diff_hours, 10 * 24 - 2 * 24 - 3, 'hours: 237 hours, 2 holidays' ); - $diff_days = $calendar->days_between( $now, $nov_15->clone->subtract( hours => 3 ) )->delta_days; - is( $diff_days, 10 - 2, 'days: 237 hours, 2 holidays' ); - }; - - }; - - Time::Fake->reset; -}; - -subtest 'is_holiday' => sub { - plan tests => 1; - - subtest 'weekday holidays' => sub { - plan tests => 7; - - my $library = $builder->build_object( { class => 'Koha::Libraries' } ); - - my $day = dt_from_string(); - my $dow = scalar $day->day_of_week; - $dow = 0 if $dow == 7; - - # Closed this day of the week - my $dbh = C4::Context->dbh; - $dbh->do( - q| - INSERT INTO repeatable_holidays (branchcode,weekday,day,month,title,description) - VALUES ( ?, ?, NULL, NULL, ?, '' ) - |, undef, $library->branchcode, $dow, "TEST" - ); - - # Iterate 7 days - my $sth = $dbh->prepare("UPDATE repeatable_holidays SET weekday = ? WHERE branchcode = ? AND title = 'TEST'"); - for my $i ( 0 .. 6 ) { - my $calendar = Koha::Calendar->new( branchcode => $library->branchcode ); - - is( $calendar->is_holiday($day), 1, $day->day_name() . " works as a repeatable holiday" ); - - # Increment the date and holiday day - $day->add( days => 1 ); - $dow++; - $dow = 0 if $dow == 7; - $sth->execute( $dow, $library->branchcode ); - } - }; -}; - -subtest 'get_push_amt' => sub { - plan tests => 1; - - t::lib::Mocks::mock_preference( 'useDaysMode', 'Dayweek' ); - - subtest 'weekday holidays' => sub { - plan tests => 7; - - my $library = $builder->build_object( { class => 'Koha::Libraries' } ); - - my $day = dt_from_string(); - my $dow = scalar $day->day_of_week; - $dow = 0 if $dow == 7; - - # Closed this day of the week - my $dbh = C4::Context->dbh; - $dbh->do( - q| - INSERT INTO repeatable_holidays (branchcode,weekday,day,month,title,description) - VALUES ( ?, ?, NULL, NULL, ?, '' ) - |, undef, $library->branchcode, $dow, "TEST" - ); - - # Iterate 7 days - my $sth = $dbh->prepare("UPDATE repeatable_holidays SET weekday = ? WHERE branchcode = ? AND title = 'TEST'"); - for my $i ( 0 .. 6 ) { - my $calendar = Koha::Calendar->new( branchcode => $library->branchcode, days_mode => 'Dayweek' ); - - my $npa; - eval { - local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required - alarm 2; - $npa = $calendar->next_open_days( $day, 0 ); - alarm 0; - }; - if ($@) { - die unless $@ eq "alarm\n"; # propagate unexpected errors - # timed out - ok( 0, "next_push_amt succeeded for " . $day->day_name() . " weekday holiday" ); - } else { - ok( $npa, "next_push_amt succeeded for " . $day->day_name() . " weekday holiday" ); - } - - # Increment the date and holiday day - $day->add( days => 1 ); - $dow++; - $dow = 0 if $dow == 7; - $sth->execute( $dow, $library->branchcode ); - } - }; -}; - -$schema->storage->txn_rollback(); diff --git a/t/db_dependent/Circulation.t b/t/db_dependent/Circulation.t index fcd68e9bbe..45065b9f02 100755 --- a/t/db_dependent/Circulation.t +++ b/t/db_dependent/Circulation.t @@ -32,7 +32,6 @@ use t::lib::Mocks; use t::lib::TestBuilder; use C4::Accounts; -use C4::Calendar qw( new insert_single_holiday insert_week_day_holiday delete_holiday ); use C4::Circulation qw( AddIssue AddReturn CanBookBeRenewed GetIssuingCharges AddRenewal GetSoonestRenewDate GetLatestAutoRenewDate LostItem GetUpcomingDueIssues CanBookBeIssued AddIssuingCharge MarkIssueReturned ProcessOfflinePayment transferbook updateWrongTransfer ); use C4::Biblio; use C4::Items qw( ModItemTransfer ); @@ -42,6 +41,7 @@ use C4::Overdues qw( CalcFine UpdateFine get_chargeable_units ); use C4::Members::Messaging qw( SetMessagingPreference ); use Koha::DateUtils qw( dt_from_string output_pref ); use Koha::Database; +use Koha::DiscreteCalendar; use Koha::Items; use Koha::Item::Transfers; use Koha::Checkouts; @@ -115,8 +115,7 @@ my $mocked_datetime = Test::MockModule->new('DateTime'); $mocked_datetime->mock( 'now', sub { return $now_value->clone; } ); my $cache = Koha::Caches->get_instance(); -$dbh->do(q|DELETE FROM special_holidays|); -$dbh->do(q|DELETE FROM repeatable_holidays|); +$dbh->do(q|DELETE FROM discrete_calendar|); my $branches = Koha::Libraries->search(); for my $branch ( $branches->next ) { my $key = $branch->branchcode . "_holidays"; @@ -2867,15 +2866,16 @@ subtest 'AddReturn + suspension_chargeperiod' => sub { t::lib::Mocks::mock_preference('SuspensionsCalendar', 'noSuspensionsWhenClosed'); # Adding a holiday 2 days ago - my $calendar = C4::Calendar->new(branchcode => $library->{branchcode}); + my $calendar = Koha::DiscreteCalendar->new({ branchcode => $library->{branchcode} }); my $two_days_ago = $now->clone->subtract( days => 2 ); - $calendar->insert_single_holiday( - day => $two_days_ago->day, - month => $two_days_ago->month, - year => $two_days_ago->year, + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $two_days_ago, + end_date => $two_days_ago, title => 'holidayTest-2d', description => 'holidayDesc 2 days ago' - ); + }); # With 5 days of overdue, only 4 (x finedays=2) days must charged (one was an holiday) $expected_expiration = $now->clone->add( days => floor( ( ( 5 - 0 - 1 ) / 1 ) * 2 ) ); test_debarment_on_checkout( @@ -2890,13 +2890,13 @@ subtest 'AddReturn + suspension_chargeperiod' => sub { # Adding a holiday 2 days ahead, with finesCalendar=noFinesWhenClosed it should be skipped my $two_days_ahead = $now->clone->add( days => 2 ); - $calendar->insert_single_holiday( - day => $two_days_ahead->day, - month => $two_days_ahead->month, - year => $two_days_ahead->year, + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $two_days_ahead, + end_date => $two_days_ahead, title => 'holidayTest+2d', description => 'holidayDesc 2 days ahead' - ); + }); # Same as above, but we should skip D+2 $expected_expiration = $now->clone->add( days => floor( ( ( 5 - 0 - 1 ) / 1 ) * 2 ) + 1 ); @@ -2912,13 +2912,13 @@ subtest 'AddReturn + suspension_chargeperiod' => sub { # Adding another holiday, day of expiration date my $expected_expiration_dt = dt_from_string($expected_expiration); - $calendar->insert_single_holiday( - day => $expected_expiration_dt->day, - month => $expected_expiration_dt->month, - year => $expected_expiration_dt->year, + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $expected_expiration_dt, + end_date => $expected_expiration_dt, title => 'holidayTest_exp', description => 'holidayDesc on expiration date' - ); + }); # Expiration date will be the day after test_debarment_on_checkout( { @@ -2993,6 +2993,15 @@ subtest 'AddReturn + suspension_chargeperiod' => sub { AddIssue( $patron, $item_1->barcode, $now->clone->subtract( days => 1 ) ); (undef, $message) = AddReturn( $item_1->barcode, $library->{branchcode}, undef, $now ); is( $message->{WasReturned} && exists $message->{PrevDebarred}, 1, 'Previously debarred message for Addreturn when overdue'); + + # delete holidays + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date => $two_days_ago, + end_date => $expected_expiration_dt, + title => '', + description => '' + }); }; subtest 'CanBookBeIssued + AutoReturnCheckedOutItems' => sub { @@ -4901,18 +4910,20 @@ subtest 'Incremented fee tests' => sub { $accountline->delete(); $issue->delete(); - my $calendar = C4::Calendar->new( branchcode => $library->id ); - # DateTime 1..7 (Mon..Sun), C4::Calender 0..6 (Sun..Sat) + my $calendar = Koha::DiscreteCalendar->new({ branchcode => $library->id }); + # DateTime 1..7 (Mon..Sun), Koha::DiscreteCalender 1..7 (Sun..Sat) my $closed_day = - ( $dt_from->day_of_week == 6 ) ? 0 - : ( $dt_from->day_of_week == 7 ) ? 1 - : $dt_from->day_of_week + 1; + ( $dt_from->day_of_week == 7 ) ? 1 + : $dt_from->day_of_week + 1; my $closed_day_name = $dt_from->clone->add(days => 1)->day_name; - $calendar->insert_week_day_holiday( + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, weekday => $closed_day, + start_date => $dt_from, + end_date => $dt_from, title => 'Test holiday', description => 'Test holiday' - ); + }); $issue = AddIssue( $patron, $item->barcode, $dt_to, undef, $dt_from ); $accountline = Koha::Account::Lines->find( { itemnumber => $item->id } ); @@ -5037,7 +5048,17 @@ subtest 'Incremented fee tests' => sub { $accountline->delete(); $issue->delete(); - $calendar->delete_holiday( weekday => $closed_day ); + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + delete_type => 1, + override => 1, + weekday => $closed_day, + start_date => $dt_from, + end_date => $dt_from, + title => '', + description => '', + }); + $issue = AddIssue( $patron, $item->barcode, $dt_to, undef, $dt_from ); $accountline = Koha::Account::Lines->find( { itemnumber => $item->id } ); diff --git a/t/db_dependent/Circulation/CalcDateDue.t b/t/db_dependent/Circulation/CalcDateDue.t index 215e2e7e88..351e360941 100755 --- a/t/db_dependent/Circulation/CalcDateDue.t +++ b/t/db_dependent/Circulation/CalcDateDue.t @@ -8,7 +8,8 @@ use DBI; use DateTime; use t::lib::Mocks; use t::lib::TestBuilder; -use C4::Calendar qw( new insert_single_holiday delete_holiday insert_week_day_holiday ); +use Koha::DateUtils qw(dt_from_string); +use Koha::DiscreteCalendar; use Koha::CirculationRules; @@ -77,23 +78,25 @@ is($date, $dateexpiry . 'T23:59:00', 'date expiry with useDaysMode to noDays'); # Let's add a special holiday on 2013-01-01. With ReturnBeforeExpiry and # useDaysMode different from 'Days', return should forward the dateexpiry. -my $calendar = C4::Calendar->new(branchcode => $branchcode); -$calendar->insert_single_holiday( - day => 1, - month => 1, - year => 2013, +my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branchcode }); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => dt_from_string($dateexpiry, 'iso'), + end_date => dt_from_string($dateexpiry, 'iso'), title =>'holidayTest', description => 'holidayDesc' -); +}); $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower ); is($date, '2012-12-31T23:59:00', 'date expiry should be 2013-01-01 -1 day'); -$calendar->insert_single_holiday( - day => 31, - month => 12, - year => 2012, +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => dt_from_string('2012-12-31', 'iso'), + end_date => dt_from_string('2012-12-31', 'iso'), title =>'holidayTest', description => 'holidayDesc' -); +}); $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower ); is($date, '2012-12-30T23:59:00', 'date expiry should be 2013-01-01 -2 day'); @@ -132,38 +135,49 @@ is($date, '2013-02-' . (9 + $renewalperiod) . 'T23:59:00', "useDaysMode = Daywee # Now let's add a closed day on the expected renewal date, it should # roll forward as per Datedue (i.e. one day at a time) # For issues... -$calendar->insert_single_holiday( - day => 9 + $issuelength, - month => 2, - year => 2013, +my $issue_date = dt_from_string('2013-02-' . (9 + $issuelength), 'iso'); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $issue_date, + end_date => $issue_date, title =>'DayweekTest1', description => 'DayweekTest1' -); +}); + $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower ); is($date, '2013-02-' . (9 + $issuelength + 1) . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 10 day loan (should not trigger 7 day roll forward), issue date expiry ( start + $issuelength + 1 )"); # Remove the holiday we just created -$calendar->delete_holiday( - day => 9 + $issuelength, - month => 2, - year => 2013 -); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + override => 1, + start_date => $issue_date, + end_date => $issue_date, + title => '', + description => '', +}); # ...and for renewals... -$calendar->insert_single_holiday( - day => 9 + $renewalperiod, - month => 2, - year => 2013, +my $renewal_date = dt_from_string('2013-02-' . (9 + $renewalperiod), 'iso'); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $renewal_date, + end_date => $renewal_date, title =>'DayweekTest2', description => 'DayweekTest2' -); +}); $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 ); is($date, '2013-02-' . (9 + $renewalperiod + 1) . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 5 day renewal (should not trigger 7 day roll forward), renewal date expiry ( start + $renewalperiod + 1 )"); # Remove the holiday we just created -$calendar->delete_holiday( - day => 9 + $renewalperiod, - month => 2, - year => 2013, -); +$calendar->edit_holiday({ + title => '', + description => '', + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date => $renewal_date, + end_date => $renewal_date, + override => 1, +}); # Now we test it does the right thing if the loan and renewal periods # are a multiple of 7 days @@ -198,43 +212,55 @@ my $dayweek_borrower = $builder->build_object( # For issues... $start_date = DateTime->new({year => 2013, month => 2, day => 9}); -$calendar->insert_single_holiday( - day => 9 + $dayweek_issuelength, - month => 2, - year => 2013, +my $holiday_date = $start_date->clone(); +$holiday_date->add(days => $dayweek_issuelength); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $holiday_date, + end_date => $holiday_date, title =>'DayweekTest3', description => 'DayweekTest3' -); +}); $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower ); my $issue_should_add = $dayweek_issuelength + 7; my $dayweek_issue_expected = $start_date->add( days => $issue_should_add ); is($date, $dayweek_issue_expected->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 14 day loan (should trigger 7 day roll forward), issue date expiry ( start + $issue_should_add )"); # Remove the holiday we just created -$calendar->delete_holiday( - day => 9 + $dayweek_issuelength, - month => 2, - year => 2013, -); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + override => 1, + start_date => $holiday_date, + end_date => $holiday_date, + title => '', + description => '', +}); # ...and for renewals... $start_date = DateTime->new({year => 2013, month => 2, day => 9}); -$calendar->insert_single_holiday( - day => 9 + $dayweek_renewalperiod, - month => 2, - year => 2013, +$holiday_date = $start_date->clone(); +$holiday_date->add(days => $dayweek_renewalperiod); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $holiday_date, + end_date => $holiday_date, title => 'DayweekTest4', description => 'DayweekTest4' -); +}); $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower, 1 ); my $renewal_should_add = $dayweek_renewalperiod + 7; my $dayweek_renewal_expected = $start_date->add( days => $renewal_should_add ); is($date, $dayweek_renewal_expected->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 7 day renewal (should trigger 7 day roll forward), renewal date expiry ( start + $renewal_should_add )"); # Remove the holiday we just created -$calendar->delete_holiday( - day => 9 + $dayweek_renewalperiod, - month => 2, - year => 2013, -); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + override => 1, + start_date => $holiday_date, + end_date => $holiday_date, + title => '', + description => '', +}); # Now test it continues to roll forward by 7 days until it finds # an open day, so we create a 3 week period of closed Saturdays @@ -242,29 +268,32 @@ $start_date = DateTime->new({year => 2013, month => 2, day => 9}); my $expected_rolled_date = DateTime->new({year => 2013, month => 3, day => 9}); my $holiday = $start_date->clone(); $holiday->add(days => 7); -$calendar->insert_single_holiday( - day => $holiday->day, - month => $holiday->month, - year => 2013, +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $holiday, + end_date => $holiday, title =>'DayweekTest5', description => 'DayweekTest5' -); +}); $holiday->add(days => 7); -$calendar->insert_single_holiday( - day => $holiday->day, - month => $holiday->month, - year => 2013, +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $holiday, + end_date => $holiday, title =>'DayweekTest6', description => 'DayweekTest6' -); +}); $holiday->add(days => 7); -$calendar->insert_single_holiday( - day => $holiday->day, - month => $holiday->month, - year => 2013, +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $holiday, + end_date => $holiday, title =>'DayweekTest7', description => 'DayweekTest7' -); +}); # For issues... $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower ); $dayweek_issue_expected = $start_date->add( days => $issue_should_add ); @@ -278,33 +307,46 @@ is($date, $expected_rolled_date->strftime('%F') . 'T23:59:00', "useDaysMode = Da $start_date = DateTime->new({year => 2013, month => 2, day => 9}); my $del_holiday = $start_date->clone(); $del_holiday->add(days => 7); -$calendar->delete_holiday( - day => $del_holiday->day, - month => $del_holiday->month, - year => 2013 -); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + override => 1, + start_date => $del_holiday, + end_date => $del_holiday, + title => '', + description => '', +}); $del_holiday->add(days => 7); -$calendar->delete_holiday( - day => $del_holiday->day, - month => $del_holiday->month, - year => 2013 -); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + override => 1, + start_date => $del_holiday, + end_date => $del_holiday, + title => '', + description => '', +}); $del_holiday->add(days => 7); -$calendar->delete_holiday( - day => $del_holiday->day, - month => $del_holiday->month, - year => 2013 -); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + override => 1, + start_date => $del_holiday, + end_date => $del_holiday, + title => '', + description => '', +}); # Now test that useDaysMode "Dayweek" doesn't try to roll forward onto # a permanently closed day and instead rolls forward just one day $start_date = DateTime->new({year => 2013, month => 2, day => 9}); # Our tests are concerned with Saturdays, so let's close on Saturdays -$calendar->insert_week_day_holiday( - weekday => 6, +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, + weekday => 7, + override => 1, + start_date => $start_date, + end_date => $start_date, title => "Saturday closure", description => "Closed on Saturdays" -); +}); # For issues... $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower ); $dayweek_issue_expected = $start_date->add( days => $dayweek_issuelength + 1 ); @@ -315,9 +357,16 @@ $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayw $dayweek_renewal_expected = $start_date->add( days => $dayweek_renewalperiod + 1 ); is($date, $dayweek_renewal_expected->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, due on Saturday, closed on Saturdays, 7 day renewal (should trigger 1 day roll forward), issue date expiry ( start + 8 )"); # Remove the holiday we just created -$calendar->delete_holiday( - weekday => 6 -); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + weekday => 7, + override => 1, + delete_type => 1, + start_date => $start_date, + end_date => $start_date, + title => "", + description => "" +}); # Renewal period of 0 is valid Koha::CirculationRules->search()->delete(); diff --git a/t/db_dependent/Circulation/maxsuspensiondays.t b/t/db_dependent/Circulation/maxsuspensiondays.t index 614a32303a..81e6e03692 100755 --- a/t/db_dependent/Circulation/maxsuspensiondays.t +++ b/t/db_dependent/Circulation/maxsuspensiondays.t @@ -20,6 +20,10 @@ $schema->storage->txn_begin; my $builder = t::lib::TestBuilder->new; my $dbh = C4::Context->dbh; +# clear any holidays to avoid throwing off the suspension day +# calculations +$dbh->do('DELETE FROM discrete_calendar'); + my $branchcode = $builder->build({ source => 'Branch' })->{branchcode}; my $itemtype = $builder->build({ source => 'Itemtype' })->{itemtype}; my $patron_category = $builder->build({ source => 'Category' }); @@ -65,11 +69,6 @@ my $itemnumber = Koha::Item->new({ itype => $itemtype })->store->itemnumber; -# clear any holidays to avoid throwing off the suspension day -# calculations -$dbh->do('DELETE FROM special_holidays'); -$dbh->do('DELETE FROM repeatable_holidays'); - my $daysago20 = dt_from_string->add_duration(DateTime::Duration->new(days => -20)); my $daysafter40 = dt_from_string->add_duration(DateTime::Duration->new(days => 40)); diff --git a/t/db_dependent/DiscreteCalendar.t b/t/db_dependent/DiscreteCalendar.t new file mode 100755 index 0000000000..7c717c1cb4 --- /dev/null +++ b/t/db_dependent/DiscreteCalendar.t @@ -0,0 +1,464 @@ +#!/usr/bin/perl + +# Copyright 2015 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 . + +use Modern::Perl; +use Test::More tests => 50; +use Test::MockModule; + +use t::lib::TestBuilder; + +use C4::Context; +use C4::Output; +use Koha::DateUtils qw ( dt_from_string ); +use Koha::DiscreteCalendar; + + +my $module_context = Test::MockModule->new('C4::Context'); +my $today = DateTime->today; +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new; + +my $branch1 = $builder->build( { source => 'Branch' } )->{branchcode}; +my $branch2 = $builder->build( { source => 'Branch' } )->{branchcode}; + +$builder->fill_discrete_calendar({ branchcode => $branch1, days => 365 }); + +$schema->resultset('DiscreteCalendar')->search({ + branchcode => $branch1 +})->update_all({ + is_opened => 1, + holiday_type => '', + note => '', + open_hour => '08:00:00', + close_hour => '16:00:00' +}); + +isnt($branch1,'', "First branch to do tests. BranchCode => $branch1"); +isnt($branch2,'', "Second branch to do tests. BranchCode => $branch2"); + +#2 Calendars to make sure branches are treated separately. +my $calendar = Koha::DiscreteCalendar->new({branchcode => $branch1}); +my $calendar2 = Koha::DiscreteCalendar->new({branchcode => $branch2}); + +my $unique_holiday = DateTime->today; +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type=> $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date=>$unique_holiday, + end_date=>$unique_holiday +}); +is($calendar->is_opened($unique_holiday), 0, "Branch closed today : $unique_holiday"); + +my @unique_holidays = $calendar->get_unique_holidays(); +is(scalar @unique_holidays, 1, "Set of exception holidays at 1"); + +my $yesterday = DateTime->today->subtract(days => 1); +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $yesterday, + end_date => $yesterday +}); +is($calendar->is_opened($yesterday), 1, "Cannot edit dates in the past without override : $yesterday is not a holiday"); + +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $yesterday, + end_date => $yesterday, + override => 1 +}); +is($calendar->is_opened($yesterday), 0, "Can edit dates in the past without override : $yesterday is a holiday"); + + +my $days_between_start = DateTime->today; +my $days_between_end = DateTime->today->add(days => 6); +my $days_between = $calendar->days_between($days_between_start, $days_between_end)->in_units('days'); +is($days_between, 5, "Days between skips holiday"); + +my $repeatable_holiday = DateTime->today->add(days => 1); +$calendar->edit_holiday({ + title => "repeatable", + holiday_type=> $Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE}, + start_date=>$repeatable_holiday, + end_date=>$repeatable_holiday +}); +is($calendar->is_opened($repeatable_holiday), 0, "Branch not opened on $repeatable_holiday"); + +my @repeatable_holidays = $calendar->get_repeatable_holidays(); +is(scalar @repeatable_holidays, 1, "Set of repeatable holidays at 1"); + +# 1 being mysql DAYOFWEEK() for Sunday +$calendar->edit_holiday({ + title => "Weekly", + weekday=>1, + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, + start_date=>$today, + end_date=>$today +}); +my @weekly_holidays = $calendar->get_week_days_holidays(); +is(scalar @weekly_holidays, 1, "Set of weekly holidays at 1"); + +my $sunday = DateTime->today->add(days =>( 7 - $today->day_of_week)); +is($calendar->is_opened($sunday), 0, "Branch not opened on " . $sunday->day_name ."s"); + +my $unique_holiday_range_start = DateTime->today->add(days => 2); +my $unique_holiday_range_end = DateTime->today->add(days => 7); +$calendar->edit_holiday({ + title => "Single holiday range", + holiday_type=>"E", + start_date=>$unique_holiday_range_start, + end_date=>$unique_holiday_range_end +}); +@unique_holidays = $calendar->get_unique_holidays(); +is(scalar @unique_holidays, 7, "Set of exception holidays at 7"); + +my $repeatable_holiday_range_start = DateTime->today->add(days => 8); +my $repeatable_holiday_range_end = DateTime->today->add(days => 13); +$calendar->edit_holiday({ + title => "Repeatable holiday range", + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE}, + start_date=>$repeatable_holiday_range_start, + end_date=>$repeatable_holiday_range_end +}); +@repeatable_holidays = $calendar->get_repeatable_holidays(); +is(scalar @repeatable_holidays, 7, "Set of repeatable holidays at 7"); + +#Hourly loan +# ex : +# item due : 2017-01-24 11:00:00 +# item returned : 2017-01-26 10:00:00 +# Branch closed : 2017-01-25 +# Open/close hours : 08:00 to 16:00 (8h day) +# Hours due : 5 hours on 2017-01-24 + 2 hours on 2017-01-26 = 7hours + +my $open_hours_since_start = dt_from_string->truncate(to => 'day')->add(days => 40, hours => 11); +my $open_hours_since_end = dt_from_string->truncate(to => 'day')->add(days => 42, hours => 10); +my $holiday_between = dt_from_string->truncate(to => 'day')->add(days => 41); +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date=>$open_hours_since_start, + end_date=>$open_hours_since_end +}); + +$calendar->edit_holiday({ + title => "Single holiday", + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date=> $holiday_between, + end_date=>$holiday_between +}); +my $open_hours_between = $calendar->open_hours_between($open_hours_since_start, $open_hours_since_end); +is($open_hours_between, 7, "7 Hours open between $open_hours_since_start and $open_hours_since_end"); + +my $christmas = DateTime->new( + year => $today->year(), + month => 12, + day => 25, +); +$calendar->edit_holiday({ + title => "Christmas", + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE}, + start_date=>$christmas, + end_date=>$christmas, + override => 1, # necessary if unit tests are run between Christmas and the first of the year +}); +is($calendar->is_opened($christmas), 0, "Branch closed on Christmas : $christmas"); + +my $newyear = DateTime->new( + year => $today->year() +1, + month => 1, + day => 1, +); + +$calendar->edit_holiday({ + title => "New Year", + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE}, + start_date=>$newyear, + end_date=>$newyear +}); +is($calendar->is_opened($newyear), 0, "Branch closed on New Year : $newyear"); + +#Hours between : +my $date_due = DateTime->today->add(days => 1); +my $date_returned = DateTime->today->add(hours => 8); +my $hours_between = $calendar->hours_between($date_due, $date_returned); + +is($hours_between->in_units('hours'), 16, "Date due $date_due, returned $date_returned, 16 hours in advance"); + +$date_due = DateTime->today->add(days => 1); +$date_returned = DateTime->today->add(days => 1, hours => 16); +$hours_between = $calendar->hours_between($date_due, $date_returned); + +is($hours_between->in_units('hours'), 16, "Date due $date_due, returned $date_returned, 16 hours late"); + + +#delete holidays +is($calendar->is_opened($today), 0, "Today is closed"); +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date=>$unique_holiday, + end_date=>$unique_holiday +}); +is($calendar->is_opened($today), 1, "Today's holiday was removed"); + +$calendar->edit_holiday({ + title => '', + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date => $yesterday, + end_date => $yesterday, + override => 1 +}); +is($calendar->is_opened($yesterday), 1, "Yesterdays's holiday was removed with override"); + +my $new_open_hours = '08:00'; +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + open_hour=>$new_open_hours, + close_hour=>'', + start_date=>$today, + end_date=>$today +}); +is($calendar->get_date_info($today, $branch1)->{open_hour}, '08:00:00', "Open hour changed to 08:00:00"); + +isnt($calendar->get_date_info($today, $branch1)->{close_hour}, '', "Close hour not removed"); + +my $delete_range_end = DateTime->today->add(days => 30); +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date=>$today, + end_date=>$delete_range_end +}); + + +is($calendar->is_opened($today), 1, "Today's holiday was already removed"); +is($calendar->is_opened(DateTime->today->add(days => 1)), 1, "Tomorrow's holiday was removed"); +is($calendar->is_opened($delete_range_end), 1, "End of range holiday was removed"); + +#Check if other branch was affected +my @unique_holidays_branch2 = $calendar2->get_unique_holidays(); +is(scalar @unique_holidays_branch2, 0, "Set of exception holidays at 0 for branch => $branch2"); +my @repeatable_holidays_branch2 = $calendar2->get_repeatable_holidays(); +is(scalar @repeatable_holidays_branch2, 0, "Set of repeatable holidays at 0 for branch => $branch2"); +my @weekly_holidays_branch2 = $calendar2->get_week_days_holidays(); +is(scalar @weekly_holidays_branch2, 0, "Set of weekly holidays at 0 for branch => $branch2"); + + +#Tests for addDate() + +my $one_day_dur = DateTime::Duration->new( days => 1 ); +my $negative_one_day_dur = DateTime::Duration->new( days => - 1 ); +my $two_day_dur = DateTime::Duration->new( days => 2 ); +my $seven_day_dur = DateTime::Duration->new( days => 7 ); + +#Preference useDaysMode Calendar +$calendar->{days_mode} = 'Calendar'; +$unique_holiday->add(days => 1); +my $tomorrow = DateTime->today->add(days => 1); +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date=>$tomorrow, + end_date=>$tomorrow +}); + +is($calendar->addDuration( $today, $one_day_dur, 'days' )->ymd(), + $today->add(days => 2)->ymd(), + 'Single day add (Calendar)' ); + +is($calendar->addDuration( $today, $two_day_dur, 'days' )->ymd(), + $today->add(days => 2)->ymd(), + 'Two days add, skips holiday (Calendar)' ); + +cmp_ok($calendar->addDuration( $today, $seven_day_dur, 'days' )->ymd(), 'eq', + $today->add(days => 7)->ymd(), + 'Add 7 days (Calendar)' ); +#Closed Sunday +$calendar->edit_holiday({ + title => "Weekly", + weekday=>1, + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, + start_date=>$today, + end_date=>$today +}); +is( $calendar->addDuration( $sunday, $one_day_dur, 'days' )->day_of_week, 1, + 'addDate skips closed Sunday (Calendar)' ); +#to remove the closed sundays +$today = DateTime->today; +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date=>$today, + end_date=>$delete_range_end +}); + +is( $calendar->addDuration($today, $negative_one_day_dur , 'days')->ymd(), + $today->add(days => - 1)->ymd(), + 'Negative call to addDate (Calendar)' ); + +#Preference useDaysMode DateDue +$calendar->{days_mode} = 'Datedue'; +#clean everything +$today = DateTime->today; +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date=>$today, + end_date=>$delete_range_end +}); +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date=>$tomorrow, + end_date=>$tomorrow +}); + +is($calendar->addDuration( $today, $one_day_dur, 'days' )->ymd(), + $today->add(days => 2)->ymd(), + 'Single day add' ); + +is($calendar->addDuration( $today, $two_day_dur, 'days' )->ymd(), + $today->add(days => 2)->ymd(), + 'Two days add, skips holiday (Datedue)' ); + +cmp_ok($calendar->addDuration( $today, $seven_day_dur, 'days' )->ymd(), 'eq', + $today->add(days => 7)->ymd(), + 'Add 7 days (Datedue)' ); +#Closed Sunday +$calendar->edit_holiday({ + title => "Weekly", + weekday=>1, + holiday_type=> $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, + start_date=>$today, + end_date=>$today +}); +is( $calendar->addDuration( $sunday, $one_day_dur, 'days' )->day_of_week, 1, + 'addDate skips closed Sunday (Datedue)' ); +#to remove the closed sundays +$today = DateTime->today; +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date=>$today, + end_date=>$delete_range_end +}); + +is( $calendar->addDuration($today, $negative_one_day_dur , 'days')->ymd(), + $today->add(days => - 1)->ymd(), + 'Negative call to addDate (Datedue)' ); + +#Preference useDaysMode Days +$calendar->{days_mode} = 'Days'; +#clean everything +$today = DateTime->today; +$calendar->edit_holiday({ + title => '', + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date=>$today, + end_date=>$delete_range_end +}); +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date=>$tomorrow, + end_date=>$tomorrow +}); +is($calendar->addDuration( $today, $one_day_dur, 'days' )->ymd(), + $today->add(days => 1)->ymd(), + 'Single day add' ); + +is($calendar->addDuration( $today, $two_day_dur, 'days' )->ymd(), + $today->add(days => 2)->ymd(), + 'Two days add, skips holiday (Days)' ); + +cmp_ok($calendar->addDuration( $today, $seven_day_dur, 'days' )->ymd(), 'eq', + $today->add(days => 7)->ymd(), + 'Add 7 days (Days)' ); +#Closed Sunday +$calendar->edit_holiday({ + title => "Weekly", + weekday => 1, + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, + start_date => $today, + end_date => $today +}); +is( $calendar->addDuration( $sunday, $one_day_dur, 'days' )->day_of_week, 1, + 'addDate skips closed Sunday (Days)' ); + +is( $calendar->addDuration($today, $negative_one_day_dur , 'days')->ymd(), + $today->add(days => - 1)->ymd(), + 'Negative call to addDate (Days)' ); + +#Days_forward + +#clean the range +$today = DateTime->today; +$calendar->edit_holiday({ + title => '', + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + start_date => $today, + end_date => DateTime->today->add(days => 20) +}); +my $forwarded_dt = $calendar->days_forward($today, 10); + +my $expected = $today->clone; +$expected->add(days => 10); +is($forwarded_dt->ymd, $expected->ymd, 'With no holiday on the perioddays_forward should add 10 days'); + +#Added a holiday +$unique_holiday = DateTime->today->add(days => 15); +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $unique_holiday, + end_date => $unique_holiday +}); +$forwarded_dt = $calendar->days_forward($today, 20); + +$expected->add(days => 11); +is($forwarded_dt->ymd, $expected->ymd, 'With holiday on the perioddays_forward should add 20 days + 1 day for holiday'); + +$forwarded_dt = $calendar->days_forward($today, 0); +is($forwarded_dt->ymd, $today->ymd, '0 day should return start dt'); + +$forwarded_dt = $calendar->days_forward($today, -2); +is($forwarded_dt->ymd, $today->ymd, 'negative day should return start dt'); + +#copying a branch to an other +is($calendar2->is_opened($tomorrow), 1, "$branch2 opened tomorrow"); +#Added a goliday tomorrow for branch1 +$calendar->edit_holiday({ + title => "Single holiday Today", + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $tomorrow, + end_date => $tomorrow +}); +#Copy dates from branch1 to branch2 +$calendar->copy_to_branch($branch2); +#Check if branch2 is also closed tomorrow after copying from branch1 +is($calendar2->is_opened($tomorrow), 0, "$branch2 close tomorrow after copying from $branch1"); + +$schema->storage->txn_rollback; + +1; diff --git a/t/db_dependent/Hold.t b/t/db_dependent/Hold.t index 73007c18a0..b96a917773 100755 --- a/t/db_dependent/Hold.t +++ b/t/db_dependent/Hold.t @@ -22,7 +22,7 @@ use C4::Context; use C4::Biblio qw( AddBiblio ); use Koha::Database; use Koha::Libraries; -use C4::Calendar qw( new insert_single_holiday ); +use Koha::DiscreteCalendar; use Koha::Patrons; use Koha::Holds; use Koha::Item; @@ -77,8 +77,16 @@ my $hold = Koha::Hold->new( ); $hold->store(); -my $b1_cal = C4::Calendar->new( branchcode => $branches[1]->{branchcode} ); -$b1_cal->insert_single_holiday( day => 2, month => 1, year => 2017, title => "Morty Day", description => "Rick" ); #Add a holiday +my $b1_cal = Koha::DiscreteCalendar->new({ branchcode => $branches[1]->{branchcode} }); +my $holiday = dt_from_string('2017-01-02', 'iso'); +$b1_cal->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + override => 1, + start_date => $holiday, + end_date => $holiday, + title => "Morty Day", + description => "Rick", +}); #Add a holiday my $today = dt_from_string; is( $hold->age(), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days') , "Age of hold is days from reservedate to now if calendar ignored"); is( $hold->age(1), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days' ) - 1 , "Age of hold is days from reservedate to now minus 1 if calendar used"); diff --git a/t/db_dependent/Holds.t b/t/db_dependent/Holds.t index 39224e9905..1441853ac4 100755 --- a/t/db_dependent/Holds.t +++ b/t/db_dependent/Holds.t @@ -13,7 +13,6 @@ use Test::Exception; use MARC::Record; use C4::Biblio; -use C4::Calendar; use C4::Items; use C4::Reserves qw( AddReserve CalculatePriority ModReserve ToggleSuspend AutoUnsuspendReserves SuspendAll ModReserveMinusPriority AlterPriority CanItemBeReserved CheckReserves ); use C4::Circulation qw( CanBookBeRenewed ); diff --git a/t/db_dependent/Holds/WaitingReserves.t b/t/db_dependent/Holds/WaitingReserves.t index 111bcfa70f..73b025075a 100755 --- a/t/db_dependent/Holds/WaitingReserves.t +++ b/t/db_dependent/Holds/WaitingReserves.t @@ -16,8 +16,7 @@ my $schema = Koha::Database->new->schema; $schema->storage->txn_begin; my $dbh = C4::Context->dbh; -$dbh->do(q{DELETE FROM special_holidays}); -$dbh->do(q{DELETE FROM repeatable_holidays}); +$dbh->do(q{DELETE FROM discrete_calendar}); $dbh->do("DELETE FROM reserves"); my $builder = t::lib::TestBuilder->new(); @@ -36,6 +35,8 @@ $builder->build({ }, }); +my $calendar = Koha::DiscreteCalendar->new({ branchcode => 'LIB1' }); + $builder->build({ source => 'Branch', value => { @@ -138,31 +139,21 @@ my $reserve3 = $builder->build({ my $special_holiday1_dt = $today->clone; $special_holiday1_dt->add(days => 2); -my $holiday = $builder->build({ - source => 'SpecialHoliday', - value => { - branchcode => 'LIB1', - day => $special_holiday1_dt->day, - month => $special_holiday1_dt->month, - year => $special_holiday1_dt->year, - title => 'My special holiday', - isexception => 0 - }, +$calendar->edit_holiday({ + title => "My special holiday", + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $special_holiday1_dt, + end_date => $special_holiday1_dt, }); my $special_holiday2_dt = $today->clone; $special_holiday2_dt->add(days => 4); -my $holiday2 = $builder->build({ - source => 'SpecialHoliday', - value => { - branchcode => 'LIB1', - day => $special_holiday2_dt->day, - month => $special_holiday2_dt->month, - year => $special_holiday2_dt->year, - title => 'My special holiday 2', - isexception => 0 - }, +$calendar->edit_holiday({ + title => "My special holiday 2", + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $special_holiday2_dt, + end_date => $special_holiday2_dt, }); Koha::Caches->get_instance->flush_all; diff --git a/t/db_dependent/HoldsQueue.t b/t/db_dependent/HoldsQueue.t index 7875c69eed..d37a526582 100755 --- a/t/db_dependent/HoldsQueue.t +++ b/t/db_dependent/HoldsQueue.t @@ -11,7 +11,7 @@ use Modern::Perl; use Test::More tests => 61; use Data::Dumper; -use C4::Calendar qw( new insert_single_holiday ); +use Koha::DiscreteCalendar; use C4::Context; use C4::Members; use C4::Circulation qw( AddIssue AddReturn ); @@ -327,16 +327,17 @@ is( $holds_queue->[1]->{cardnumber}, $borrower2->{cardnumber}, "Holds queue fill # have 1 row in the holds queue t::lib::Mocks::mock_preference('HoldsQueueSkipClosed', 1); my $today = dt_from_string(); -C4::Calendar->new( branchcode => $branchcodes[0] )->insert_single_holiday( - day => $today->day(), - month => $today->month(), - year => $today->year(), +my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branchcodes[0] }); +$calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $today, + end_date => $today, title => "$today", description => "$today", -); +}); # If the test below is removed, aother tests using the holiday will fail. For some reason if we call is_holiday now # the holiday will get set in cache correctly, but not if we let C4::HoldsQueue call is_holiday instead. -is( Koha::Calendar->new( branchcode => $branchcodes[0] )->is_holiday( $today ), 1, 'Is today a holiday for pickup branch' ); +is( $calendar->is_holiday( $today ), 1, 'Is today a holiday for pickup branch' ); C4::HoldsQueue::CreateQueue(); $holds_queue = $dbh->selectall_arrayref("SELECT * FROM tmp_holdsqueue", { Slice => {} }); is( scalar( @$holds_queue ), 1, "Holds not filled with items from closed libraries" ); diff --git a/t/db_dependent/Holidays.t b/t/db_dependent/Holidays.t deleted file mode 100755 index db169e8e2a..0000000000 --- a/t/db_dependent/Holidays.t +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/perl - -# 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 . - -use Modern::Perl; - -use Test::More tests => 14; -use Test::Exception; - -use DateTime; -use DateTime::TimeZone; - -use t::lib::TestBuilder; -use C4::Context; -use Koha::Database; -use Koha::DateUtils qw( dt_from_string ); - -BEGIN { - use_ok('Koha::Calendar'); - use_ok('C4::Calendar', qw( insert_exception_holiday insert_week_day_holiday insert_day_month_holiday insert_single_holiday copy_to_branch get_exception_holidays isHoliday )); -} - -my $schema = Koha::Database->new->schema; -my $dbh = C4::Context->dbh; -my $builder = t::lib::TestBuilder->new; - -subtest 'is_holiday timezone tests' => sub { - - plan tests => 1; - - $schema->storage->txn_begin; - - $dbh->do("DELETE FROM special_holidays"); - # Clear cache - Koha::Caches->get_instance->flush_all; - - # Artificially set timezone - my $timezone = 'America/Santiago'; - $ENV{TZ} = $timezone; - use POSIX qw(tzset); - tzset; - - my $branch = $builder->build( { source => 'Branch' } )->{branchcode}; - my $calendar = Koha::Calendar->new( branchcode => $branch ); - - C4::Calendar->new( branchcode => $branch )->insert_exception_holiday( - day => 6, - month => 9, - year => 2015, - title => 'Invalid date', - description => 'Invalid date description', - ); - - my $exception_holiday = DateTime->new( day => 6, month => 9, year => 2015 ); - my $now_dt = DateTime->now; - - my $diff; - eval { $diff = $calendar->days_between( $now_dt, $exception_holiday ) }; - unlike( - $@, - qr/Invalid local time for date in time zone: America\/Santiago/, - 'Avoid invalid datetime due to DST' - ); - - $schema->storage->txn_rollback; -}; - -$schema->storage->txn_begin; - -# Create two fresh branches for the tests -my $branch_1 = $builder->build({ source => 'Branch' })->{ branchcode }; -my $branch_2 = $builder->build({ source => 'Branch' })->{ branchcode }; - -C4::Calendar->new( branchcode => $branch_1 )->insert_week_day_holiday( - weekday => 0, - title => '', - description => 'Sundays', -); - -my $holiday2add = dt_from_string("2015-01-01"); -C4::Calendar->new( branchcode => $branch_1 )->insert_day_month_holiday( - day => $holiday2add->day(), - month => $holiday2add->month(), - year => $holiday2add->year(), - title => '', - description => "New Year's Day", -); -$holiday2add = dt_from_string("2014-12-25"); -C4::Calendar->new( branchcode => $branch_1 )->insert_day_month_holiday( - day => $holiday2add->day(), - month => $holiday2add->month(), - year => $holiday2add->year(), - title => '', - description => 'Christmas', -); - -my $koha_calendar = Koha::Calendar->new( branchcode => $branch_1 ); -my $c4_calendar = C4::Calendar->new( branchcode => $branch_1 ); - -isa_ok( $koha_calendar, 'Koha::Calendar', 'Koha::Calendar class returned' ); -isa_ok( $c4_calendar, 'C4::Calendar', 'C4::Calendar class returned' ); - -my $sunday = DateTime->new( - year => 2011, - month => 6, - day => 26, -); -my $monday = DateTime->new( - year => 2011, - month => 6, - day => 27, -); -my $christmas = DateTime->new( - year => 2032, - month => 12, - day => 25, -); -my $newyear = DateTime->new( - year => 2035, - month => 1, - day => 1, -); - -is( $koha_calendar->is_holiday($sunday), 1, 'Sunday is a closed day' ); -is( $koha_calendar->is_holiday($monday), 0, 'Monday is not a closed day' ); -is( $koha_calendar->is_holiday($christmas), 1, 'Christmas is a closed day' ); -is( $koha_calendar->is_holiday($newyear), 1, 'New Years day is a closed day' ); - -$dbh->do("DELETE FROM repeatable_holidays"); -$dbh->do("DELETE FROM special_holidays"); - -my $custom_holiday = DateTime->new( - year => 2013, - month => 11, - day => 12, -); - -my $today = dt_from_string(); -C4::Calendar->new( branchcode => $branch_2 )->insert_single_holiday( - day => $today->day(), - month => $today->month(), - year => $today->year(), - title => "$today", - description => "$today", -); - -is( Koha::Calendar->new( branchcode => $branch_2 )->is_holiday( $today ), 1, "Today is a holiday for $branch_2" ); -is( Koha::Calendar->new( branchcode => $branch_1 )->is_holiday( $today ), 0, "Today is not a holiday for $branch_1"); - -$schema->storage->txn_rollback; - -subtest 'copy_to_branch' => sub { - - plan tests => 8; - - $schema->storage->txn_begin; - - my $branch1 = $builder->build( { source => 'Branch' } )->{ branchcode }; - my $calendar1 = C4::Calendar->new( branchcode => $branch1 ); - my $sunday = dt_from_string("2020-03-15"); - $calendar1->insert_week_day_holiday( - weekday => 0, - title => '', - description => 'Sundays', - ); - - my $day_month = dt_from_string("2020-03-17"); - $calendar1->insert_day_month_holiday( - day => $day_month->day(), - month => $day_month->month(), - year => $day_month->year(), - title => '', - description => "", - ); - - my $future_date = dt_from_string("9999-12-31"); - $calendar1->insert_single_holiday( - day => $future_date->day(), - month => $future_date->month(), - year => $future_date->year(), - title => "", - description => "", - ); - - my $future_exception = dt_from_string("9999-12-30"); - $calendar1->insert_exception_holiday( - day => $future_exception->day(), - month => $future_exception->month(), - year => $future_exception->year(), - title => "", - description => "", - ); - - my $past_date = dt_from_string("2019-11-20"); - $calendar1->insert_single_holiday( - day => $past_date->day(), - month => $past_date->month(), - year => $past_date->year(), - title => "", - description => "", - ); - - my $past_exception = dt_from_string("2020-03-09"); - $calendar1->insert_exception_holiday( - day => $past_exception->day(), - month => $past_exception->month(), - year => $past_exception->year(), - title => "", - description => "", - ); - - my $branch2 = $builder->build( { source => 'Branch' } )->{branchcode}; - - C4::Calendar->new( branchcode => $branch1 )->copy_to_branch( $branch2 ); - - my $calendar2 = C4::Calendar->new( branchcode => $branch2 ); - my $exceptions = $calendar2->get_exception_holidays; - - is( $calendar2->isHoliday( $sunday->day, $sunday->month, $sunday->year ), 1, "Weekday holiday copied to branch 2" ); - is( $calendar2->isHoliday( $day_month->day, $day_month->month, $day_month->year ), 1, "Day/month holiday copied to branch 2" ); - is( $calendar2->isHoliday( $future_date->day, $future_date->month, $future_date->year ), 1, "Single holiday copied to branch 2" ); - is( ( grep { $_->{date} eq "9999-12-30"} values %$exceptions ), 1, "Exception holiday copied to branch 2" ); - is( $calendar2->isHoliday( $past_date->day, $past_date->month, $past_date->year ), 0, "Don't copy past single holidays" ); - is( ( grep { $_->{date} eq "2020-03-09"} values %$exceptions ), 0, "Don't copy past exception holidays " ); - - C4::Calendar->new( branchcode => $branch1 )->copy_to_branch( $branch2 ); - - #Select all rows with same values from database - my $dbh = C4::Context->dbh; - my $get_repeatable_holidays = "SELECT a.* FROM repeatable_holidays a - JOIN (SELECT branchcode, weekday, day, month, COUNT(*) - FROM repeatable_holidays - GROUP BY branchcode, weekday, day, month HAVING count(*) > 1) b - ON a.branchcode = b.branchcode - AND ( a.weekday = b.weekday OR (a.day = b.day AND a.month = b.month)) - ORDER BY a.branchcode;"; - my $sth = $dbh->prepare($get_repeatable_holidays); - $sth->execute; - - my @repeatable_holidays; - while(my $row = $sth->fetchrow_hashref){ - push @repeatable_holidays, $row - } - - is( scalar(@repeatable_holidays), 0, "None of the repeatable holidays were doubled"); - - my $get_special_holidays = "SELECT a.* FROM special_holidays a - JOIN (SELECT branchcode, day, month, year, isexception, COUNT(*) - FROM special_holidays - GROUP BY branchcode, day, month, year, isexception HAVING count(*) > 1) b - ON a.branchcode = b.branchcode - AND a.day = b.day AND a.month = b.month AND a.year = b.year AND a.isexception = b.isexception - ORDER BY a.branchcode;"; - $sth = $dbh->prepare($get_special_holidays); - $sth->execute; - - my @special_holidays; - while(my $row = $sth->fetchrow_hashref){ - push @special_holidays, $row - } - - is( scalar(@special_holidays), 0, "None of the special holidays were doubled"); - - $schema->storage->txn_rollback; - -}; - -subtest 'with a library that is never open' => sub { - plan tests => 2; - - $schema->storage->txn_begin; - - my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; - my $calendar = C4::Calendar->new( branchcode => $branchcode ); - foreach my $weekday ( 0 .. 6 ) { - $calendar->insert_week_day_holiday( weekday => $weekday, title => '', description => '' ); - } - - my $now = dt_from_string; - - subtest 'next_open_days should throw an exception' => sub { - my $kcalendar = Koha::Calendar->new( branchcode => $branchcode, days_mode => 'Calendar' ); - throws_ok { $kcalendar->next_open_days( $now, 1 ) } 'Koha::Exceptions::Calendar::NoOpenDays'; - }; - - subtest 'prev_open_days should throw an exception' => sub { - my $kcalendar = Koha::Calendar->new( branchcode => $branchcode, days_mode => 'Calendar' ); - throws_ok { $kcalendar->prev_open_days( $now, 1 ) } 'Koha::Exceptions::Calendar::NoOpenDays'; - }; - - $schema->storage->txn_rollback; -}; - -subtest 'with a library that is *almost* never open' => sub { - plan tests => 2; - - $schema->storage->txn_begin; - - my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; - my $calendar = C4::Calendar->new( branchcode => $branchcode ); - foreach my $weekday ( 0 .. 6 ) { - $calendar->insert_week_day_holiday( weekday => $weekday, title => '', description => '' ); - } - - my $now = dt_from_string; - my $open_day_in_the_future = $now->clone()->add( years => 1 ); - my $open_day_in_the_past = $now->clone()->subtract( years => 1 ); - $calendar->insert_exception_holiday( date => $open_day_in_the_future->ymd, title => '', description => '' ); - $calendar->insert_exception_holiday( date => $open_day_in_the_past->ymd, title => '', description => '' ); - - subtest 'next_open_days should find the open day' => sub { - my $kcalendar = Koha::Calendar->new( branchcode => $branchcode, days_mode => 'Calendar' ); - my $next_open_day = $kcalendar->next_open_days( $now, 1 ); - is( $next_open_day->ymd, $open_day_in_the_future->ymd ); - }; - - subtest 'prev_open_days should find the open day' => sub { - my $kcalendar = Koha::Calendar->new( branchcode => $branchcode, days_mode => 'Calendar' ); - my $prev_open_day = $kcalendar->prev_open_days( $now, 1 ); - is( $prev_open_day->ymd, $open_day_in_the_past->ymd ); - }; - - $schema->storage->txn_rollback; -}; - -# Clear cache -Koha::Caches->get_instance->flush_all; diff --git a/t/db_dependent/Koha/Charges/Fees.t b/t/db_dependent/Koha/Charges/Fees.t index 2f2af9d876..93d202d906 100755 --- a/t/db_dependent/Koha/Charges/Fees.t +++ b/t/db_dependent/Koha/Charges/Fees.t @@ -28,7 +28,7 @@ use t::lib::TestBuilder; use t::lib::Dates; use Time::Fake; -use C4::Calendar qw( new insert_week_day_holiday delete_holiday ); +use Koha::DiscreteCalendar; use Koha::DateUtils qw(dt_from_string); BEGIN { @@ -357,26 +357,29 @@ subtest 'accumulate_rentalcharge tests' => sub { ); $itemtype->rentalcharge_daily_calendar(1)->store(); - my $calendar = C4::Calendar->new( branchcode => $library->id ); - # DateTime 1..7 (Mon..Sun), C4::Calender 0..6 (Sun..Sat) + my $calendar = Koha::DiscreteCalendar->new({ branchcode => $library->id }); + # DateTime 1..7 (Mon..Sun), Koha::DiscreteCalendar 1..7 (Sun..Sat) my $closed_day = - ( $dt_from->day_of_week == 6 ) ? 0 - : ( $dt_from->day_of_week == 7 ) ? 1 - : $dt_from->day_of_week + 1; - $calendar->insert_week_day_holiday( - weekday => $closed_day, + ( $dt_from->day_of_week == 7 ) ? 1 + : $dt_from->day_of_week + 1; + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, + weekday => $closed_day, + override => 1, + start_date => $dt_from, + end_date => $dt_from, title => 'Test holiday', description => 'Test holiday' - ); + }); $charge = $fees->accumulate_rentalcharge(); my $day_names = { - 0 => 'Sunday', - 1 => 'Monday', - 2 => 'Tuesday', - 3 => 'Wednesday', - 4 => 'Thursday', - 5 => 'Friday', - 6 => 'Saturday' + 1 => 'Sunday', + 2 => 'Monday', + 3 => 'Tuesday', + 4 => 'Wednesday', + 5 => 'Thursday', + 6 => 'Friday', + 7 => 'Saturday' }; my $dayname = $day_names->{$closed_day}; is( $charge, 5.00, @@ -426,7 +429,16 @@ subtest 'accumulate_rentalcharge tests' => sub { ); $itemtype->rentalcharge_hourly_calendar(1)->store(); - $calendar->delete_holiday( weekday => $closed_day ); + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + weekday => $closed_day, + override => 1, + delete_type => 1, + start_date => $dt_from, + end_date => $dt_from, + title => '', + description => '', + }); $charge = $fees->accumulate_rentalcharge(); is( $charge, 24.00, 'Hourly rental charge calculated correctly with finesCalendar = noFinesWhenClosed (96h - 0h * 0.25u)' ); }; diff --git a/t/db_dependent/Koha/CurbsidePickups.t b/t/db_dependent/Koha/CurbsidePickups.t index 3b98bef472..5c7e8bcfef 100755 --- a/t/db_dependent/Koha/CurbsidePickups.t +++ b/t/db_dependent/Koha/CurbsidePickups.t @@ -20,10 +20,9 @@ use Modern::Perl; use Test::More tests => 4; use Test::Exception; -use C4::Calendar; use Koha::CurbsidePickups; use Koha::CurbsidePickupPolicies; -use Koha::Calendar; +use Koha::DiscreteCalendar; use Koha::Database; use Koha::DateUtils qw( dt_from_string ); @@ -154,19 +153,30 @@ subtest 'Create a pickup' => sub { # Day is a holiday Koha::Caches->get_instance->flush_all; - C4::Calendar->new( branchcode => $library->branchcode )->insert_week_day_holiday( - weekday => 1, + my $calendar = Koha::DiscreteCalendar->new({ branchcode => $library->branchcode }); + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY}, + weekday => 2, + start_date => $schedule_dt, + end_date => $schedule_dt, title => '', description => 'Mondays', - ); - my $calendar = Koha::Calendar->new( branchcode => $library->branchcode ); + }); throws_ok { Koha::CurbsidePickup->new({%$params, scheduled_pickup_datetime => $schedule_dt})->store; } 'Koha::Exceptions::CurbsidePickup::LibraryIsClosed', 'Cannot create a pickup on a holiday'; - C4::Context->dbh->do(q{DELETE FROM repeatable_holidays}); + $calendar->edit_holiday({ + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, + weekday => 2, + delete_type => 1, + start_date => $schedule_dt, + end_date => $schedule_dt, + description => '', + }); + Koha::Caches->get_instance->flush_all; }; diff --git a/t/db_dependent/Koha/ItemTypes.t b/t/db_dependent/Koha/ItemTypes.t index d62cf05e48..39d881ee44 100755 --- a/t/db_dependent/Koha/ItemTypes.t +++ b/t/db_dependent/Koha/ItemTypes.t @@ -24,7 +24,6 @@ use Test::More tests => 15; use t::lib::Mocks; use t::lib::TestBuilder; -use C4::Calendar qw( new ); use Koha::Biblioitems; use Koha::Libraries; use Koha::Database; diff --git a/t/db_dependent/Reserves/CancelExpiredReserves.t b/t/db_dependent/Reserves/CancelExpiredReserves.t index 4b6886989a..b8d8aaeb8d 100755 --- a/t/db_dependent/Reserves/CancelExpiredReserves.t +++ b/t/db_dependent/Reserves/CancelExpiredReserves.t @@ -81,16 +81,11 @@ subtest 'CancelExpiredReserves tests incl. holidays' => sub { }); Koha::Caches->get_instance()->flush_all(); - my $holiday = $builder->build({ - source => 'SpecialHoliday', - value => { - branchcode => 'LIB1', - day => $today->day, - month => $today->month, - year => $today->year, - title => 'My holiday', - isexception => 0 - }, + my $calendar = Koha::DiscreteCalendar->new({ branchcode => 'LIB1' })->edit_holiday({ + title => "My holiday", + holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, + start_date => $today, + end_date => $today, }); CancelExpiredReserves(); diff --git a/t/lib/TestBuilder.pm b/t/lib/TestBuilder.pm index ff2450852b..fa35218c1a 100644 --- a/t/lib/TestBuilder.pm +++ b/t/lib/TestBuilder.pm @@ -467,6 +467,7 @@ sub _gen_type { decimal => \&_gen_real, double_precision => \&_gen_real, + time => \&_gen_time, timestamp => \&_gen_datetime, datetime => \&_gen_datetime, date => \&_gen_date, @@ -536,6 +537,11 @@ sub _gen_datetime { return $self->schema->storage->datetime_parser->format_datetime(dt_from_string); } +sub _gen_time { + my ($self, $params) = @_; + return $self->schema->storage->datetime_parser->format_time(dt_from_string); +} + sub _gen_text { my ($self, $params) = @_; # From perldoc String::Random -- 2.34.1