View | Details | Raw Unified | Return to bug 17015
Collapse All | Expand All

(-)a/t/Calendar.t (-324 lines)
Lines 1-324 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More;
21
use Test::MockModule;
22
23
use DateTime;
24
use DateTime::Duration;
25
use Koha::Caches;
26
use Koha::DateUtils qw( dt_from_string );
27
28
use t::lib::Mocks;
29
30
use Module::Load::Conditional qw/check_install/;
31
32
BEGIN {
33
    if ( check_install( module => 'Test::DBIx::Class' ) ) {
34
        plan tests => 40;
35
    } else {
36
        plan skip_all => "Need Test::DBIx::Class"
37
    }
38
}
39
40
use_ok('Koha::Calendar');
41
42
use Test::DBIx::Class;
43
44
my $db = Test::MockModule->new('Koha::Database');
45
$db->mock(
46
    _new_schema => sub { return Schema(); }
47
);
48
49
# We need to mock the C4::Context->preference method for
50
# simplicity and re-usability of the session definition. Any
51
# syspref fits for syspref-agnostic tests.
52
my $module_context = Test::MockModule->new('C4::Context');
53
$module_context->mock(
54
    'preference',
55
    sub {
56
        return 'Calendar';
57
    }
58
);
59
60
fixtures_ok [
61
    # weekly holidays
62
    RepeatableHoliday => [
63
        [ qw( branchcode day month weekday title description) ],
64
        [ 'MPL', undef, undef, 0, '', '' ], # sundays
65
        [ 'MPL', undef, undef, 6, '', '' ],# saturdays
66
        [ 'MPL', 1, 1, undef, '', ''], # new year's day
67
        [ 'MPL', 25, 12, undef, '', ''], # chrismas
68
    ],
69
    # exception holidays
70
    SpecialHoliday => [
71
        [qw( branchcode day month year title description isexception )],
72
        [ 'MPL', 11, 11, 2012, '', '', 1 ],    # sunday exception
73
        [ 'MPL', 1,  6,  2011, '', '', 0 ],
74
        [ 'MPL', 4,  7,  2012, '', '', 0 ],
75
        [ 'CPL', 6,  8,  2012, '', '', 0 ],
76
        [ 'MPL', 7,  7,  2012, '', '', 1 ], # holiday exception
77
        [ 'MPL', 7,  7,  2012, '', '', 0 ], # holiday
78
      ],
79
], "add fixtures";
80
81
my $cache = Koha::Caches->get_instance();
82
$cache->clear_from_cache('MPL_holidays');
83
$cache->clear_from_cache('CPL_holidays');
84
85
# 'MPL' branch is arbitrary, is not used at all but is needed for initialization
86
my $cal = Koha::Calendar->new( branchcode => 'MPL' );
87
88
isa_ok( $cal, 'Koha::Calendar', 'Calendar class returned' );
89
90
my $saturday = DateTime->new(
91
    year      => 2012,
92
    month     => 11,
93
    day       => 24,
94
);
95
96
my $sunday = DateTime->new(
97
    year      => 2012,
98
    month     => 11,
99
    day       => 25,
100
);
101
102
my $monday = DateTime->new(
103
    year      => 2012,
104
    month     => 11,
105
    day       => 26,
106
);
107
108
my $new_year = DateTime->new(
109
    year        => 2013,
110
    month       => 1,
111
    day         => 1,
112
);
113
114
my $single_holiday = DateTime->new(
115
    year      => 2011,
116
    month     => 6,
117
    day       => 1,
118
);    # should be a holiday
119
120
my $notspecial = DateTime->new(
121
    year      => 2011,
122
    month     => 6,
123
    day       => 2
124
);    # should NOT be a holiday
125
126
my $sunday_exception = DateTime->new(
127
    year      => 2012,
128
    month     => 11,
129
    day       => 11
130
);
131
132
my $day_after_christmas = DateTime->new(
133
    year    => 2012,
134
    month   => 12,
135
    day     => 26
136
);  # for testing negative addDuration
137
138
my $holiday_for_another_branch = DateTime->new(
139
    year => 2012,
140
    month => 8,
141
    day => 6, # This is a monday
142
);
143
144
my $holiday_excepted = DateTime->new(
145
    year => 2012,
146
    month => 7,
147
    day => 7, # Both a holiday and exception
148
);
149
150
{   # Syspref-agnostic tests
151
    is ( $saturday->day_of_week, 6, '\'$saturday\' is actually a saturday (6th day of week)');
152
    is ( $sunday->day_of_week, 7, '\'$sunday\' is actually a sunday (7th day of week)');
153
    is ( $monday->day_of_week, 1, '\'$monday\' is actually a monday (1st day of week)');
154
    is ( $cal->is_holiday($saturday), 1, 'Saturday is a closed day' );
155
    is ( $cal->is_holiday($sunday), 1, 'Sunday is a closed day' );
156
    is ( $cal->is_holiday($monday), 0, 'Monday is not a closed day' );
157
    is ( $cal->is_holiday($new_year), 1, 'Month/Day closed day test (New year\'s day)' );
158
    is ( $cal->is_holiday($single_holiday), 1, 'Single holiday closed day test' );
159
    is ( $cal->is_holiday($notspecial), 0, 'Fixed single date that is not a holiday test' );
160
    is ( $cal->is_holiday($sunday_exception), 0, 'Exception holiday is not a closed day test' );
161
    is ( $cal->is_holiday($holiday_for_another_branch), 0, 'Holiday defined for another branch should not be defined as an holiday' );
162
    is ( $cal->is_holiday($holiday_excepted), 0, 'Holiday defined and excepted should not be a holiday' );
163
}
164
165
{   # Bugzilla #8966 - is_holiday truncates referenced date
166
    my $later_dt = DateTime->new(    # Monday
167
        year      => 2012,
168
        month     => 9,
169
        day       => 17,
170
        hour      => 17,
171
        minute    => 30,
172
        time_zone => 'Europe/London',
173
    );
174
175
176
    is( $cal->is_holiday($later_dt), 0, 'bz-8966 (1/2) Apply is_holiday for the next test' );
177
    cmp_ok( $later_dt, 'eq', '2012-09-17T17:30:00', 'bz-8966 (2/2) Date should be the same after is_holiday' );
178
}
179
180
{   # Bugzilla #8800 - is_holiday should use truncated date for 'contains' call
181
    my $single_holiday_time = DateTime->new(
182
        year  => 2011,
183
        month => 6,
184
        day   => 1,
185
        hour  => 11,
186
        minute  => 2
187
    );
188
189
    is( $cal->is_holiday($single_holiday_time),
190
        $cal->is_holiday($single_holiday) ,
191
        'bz-8800 is_holiday should truncate the date for holiday validation' );
192
}
193
194
    my $one_day_dur = DateTime::Duration->new( days => 1 );
195
    my $two_day_dur = DateTime::Duration->new( days => 2 );
196
    my $seven_day_dur = DateTime::Duration->new( days => 7 );
197
198
    my $dt = dt_from_string( '2012-07-03','iso' ); #tuesday
199
200
    my $test_dt = DateTime->new(    # Monday
201
        year      => 2012,
202
        month     => 7,
203
        day       => 23,
204
        hour      => 11,
205
        minute    => 53,
206
    );
207
208
    my $later_dt = DateTime->new(    # Monday
209
        year      => 2012,
210
        month     => 9,
211
        day       => 17,
212
        hour      => 17,
213
        minute    => 30,
214
        time_zone => 'Europe/London',
215
    );
216
217
{    ## 'Datedue' tests
218
219
    $cal = Koha::Calendar->new( branchcode => 'MPL', days_mode => 'Datedue' );
220
221
    is($cal->addDuration( $dt, $one_day_dur, 'days' ), # tuesday
222
        dt_from_string('2012-07-05','iso'),
223
        'Single day add (Datedue, matches holiday, shift)' );
224
225
    is($cal->addDuration( $dt, $two_day_dur, 'days' ),
226
        dt_from_string('2012-07-05','iso'),
227
        'Two days add, skips holiday (Datedue)' );
228
229
    cmp_ok($cal->addDuration( $test_dt, $seven_day_dur, 'days' ), 'eq',
230
        '2012-07-30T11:53:00',
231
        'Add 7 days (Datedue)' );
232
233
    is( $cal->addDuration( $saturday, $one_day_dur, 'days' )->day_of_week, 1,
234
        'addDuration skips closed Sunday (Datedue)' );
235
236
    is( $cal->addDuration($day_after_christmas, -1, 'days')->ymd(), '2012-12-24',
237
        'Negative call to addDuration (Datedue)' );
238
239
    ## Note that the days_between API says closed days are not considered.
240
    ## This tests are here as an API test.
241
    cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
242
                '==', 40, 'days_between calculates correctly (Days)' );
243
244
    cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
245
                '==', 40, 'Test parameter order not relevant (Days)' );
246
}
247
248
{   ## 'Calendar' tests'
249
250
    $cal = Koha::Calendar->new( branchcode => 'MPL', days_mode => 'Calendar' );
251
252
    $dt = dt_from_string('2012-07-03','iso');
253
254
    is($cal->addDuration( $dt, $one_day_dur, 'days' ),
255
        dt_from_string('2012-07-05','iso'),
256
        'Single day add (Calendar)' );
257
258
    cmp_ok($cal->addDuration( $test_dt, $seven_day_dur, 'days' ), 'eq',
259
       '2012-08-01T11:53:00',
260
       'Add 7 days (Calendar)' );
261
262
    is( $cal->addDuration( $saturday, $one_day_dur, 'days' )->day_of_week, 1,
263
            'addDuration skips closed Sunday (Calendar)' );
264
265
    is( $cal->addDuration($day_after_christmas, -1, 'days')->ymd(), '2012-12-24',
266
            'Negative call to addDuration (Calendar)' );
267
268
    cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
269
                '==', 40, 'days_between calculates correctly (Calendar)' );
270
271
    cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
272
                '==', 40, 'Test parameter order not relevant (Calendar)' );
273
}
274
275
276
{   ## 'Days' tests
277
278
    $cal = Koha::Calendar->new( branchcode => 'MPL', days_mode => 'Days' );
279
280
    $dt = dt_from_string('2012-07-03','iso');
281
282
    is($cal->addDuration( $dt, $one_day_dur, 'days' ),
283
        dt_from_string('2012-07-04','iso'),
284
        'Single day add (Days)' );
285
286
    cmp_ok($cal->addDuration( $test_dt, $seven_day_dur, 'days' ),'eq',
287
        '2012-07-30T11:53:00',
288
        'Add 7 days (Days)' );
289
290
    is( $cal->addDuration( $saturday, $one_day_dur, 'days' )->day_of_week, 7,
291
        'addDuration doesn\'t skip closed Sunday (Days)' );
292
293
    is( $cal->addDuration($day_after_christmas, -1, 'days')->ymd(), '2012-12-25',
294
        'Negative call to addDuration (Days)' );
295
296
    ## Note that the days_between API says closed days are not considered.
297
    ## This tests are here as an API test.
298
    cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
299
                '==', 40, 'days_between calculates correctly (Days)' );
300
301
    cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
302
                '==', 40, 'Test parameter order not relevant (Days)' );
303
304
}
305
306
{
307
    $cal = Koha::Calendar->new( branchcode => 'CPL' );
308
    is ( $cal->is_holiday($single_holiday), 0, 'Single holiday for MPL, not CPL' );
309
    is ( $cal->is_holiday($holiday_for_another_branch), 1, 'Holiday defined for CPL should be defined as an holiday' );
310
}
311
312
subtest 'days_mode parameter' => sub {
313
    plan tests => 1;
314
315
    t::lib::Mocks::mock_preference('useDaysMode', 'Days');
316
317
    $cal = Koha::Calendar->new( branchcode => 'CPL', days_mode => 'Calendar' );
318
    is( $cal->{days_mode}, 'Calendar', q|If set, days_mode is correctly set|);
319
};
320
321
END {
322
    $cache->clear_from_cache('MPL_holidays');
323
    $cache->clear_from_cache('CPL_holidays');
324
};
(-)a/t/db_dependent/Calendar.t (-393 lines)
Lines 1-393 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 6;
21
use Time::Fake;
22
23
use t::lib::Mocks;
24
use t::lib::TestBuilder;
25
26
use DateTime;
27
use Koha::Caches;
28
use Koha::DateUtils qw( dt_from_string );
29
30
use_ok('Koha::Calendar');
31
32
my $schema  = Koha::Database->new->schema;
33
$schema->storage->txn_begin;
34
35
my $today = dt_from_string();
36
my $holiday_dt = $today->clone;
37
$holiday_dt->add(days => 3);
38
39
Koha::Caches->get_instance()->flush_all();
40
41
my $builder = t::lib::TestBuilder->new();
42
my $library = $builder->build_object({ class => 'Koha::Libraries' });
43
my $holiday = $builder->build(
44
    {
45
        source => 'SpecialHoliday',
46
        value  => {
47
            branchcode  => $library->branchcode,
48
            day         => $holiday_dt->day,
49
            month       => $holiday_dt->month,
50
            year        => $holiday_dt->year,
51
            title       => 'My holiday',
52
            isexception => 0
53
        },
54
    }
55
);
56
57
my $calendar = Koha::Calendar->new( branchcode => $library->branchcode, days_mode => 'Calendar' );
58
59
subtest 'days_forward' => sub {
60
61
    plan tests => 4;
62
    my $forwarded_dt = $calendar->days_forward( $today, 2 );
63
    my $expected = $today->clone->add( days => 2 );
64
    is( $forwarded_dt->ymd, $expected->ymd, 'With no holiday on the perioddays_forward should add 2 days' );
65
66
    $forwarded_dt = $calendar->days_forward( $today, 5 );
67
    $expected = $today->clone->add( days => 6 );
68
    is( $forwarded_dt->ymd, $expected->ymd, 'With holiday on the perioddays_forward should add 5 days + 1 day for holiday'
69
    );
70
71
    $forwarded_dt = $calendar->days_forward( $today, 0 );
72
    is( $forwarded_dt->ymd, $today->ymd, '0 day should return start dt' );
73
74
    $forwarded_dt = $calendar->days_forward( $today, -2 );
75
    is( $forwarded_dt->ymd, $today->ymd, 'negative day should return start dt' );
76
};
77
78
subtest 'crossing_DST' => sub {
79
80
    plan tests => 3;
81
82
    my $tz = DateTime::TimeZone->new( name => 'America/New_York' );
83
    my $start_date = dt_from_string( "2016-03-09 02:29:00", undef, $tz );
84
    my $end_date   = dt_from_string( "2017-01-01 00:00:00", undef, $tz );
85
    my $days_between = $calendar->days_between( $start_date, $end_date );
86
    is( $days_between->delta_days, 298, "Days calculated correctly" );
87
    $days_between = $calendar->days_between( $end_date, $start_date );
88
    is( $days_between->delta_days, 298, "Swapping returns the same" );
89
    my $hours_between = $calendar->hours_between( $start_date, $end_date );
90
    is(
91
        $hours_between->delta_minutes,
92
        298 * 24 * 60 - 149,
93
        "Hours (in minutes) calculated correctly"
94
    );
95
};
96
97
subtest 'hours_between | days_between' => sub {
98
99
    plan tests => 2;
100
101
    #    November 2019
102
    # Su Mo Tu We Th Fr Sa
103
    #                 1  2
104
    #  3  4 *5* 6  7  8  9
105
    # 10 11 12 13 14 15 16
106
    # 17 18 19 20 21 22 23
107
    # 24 25 26 27 28 29 30
108
109
    my $now    = dt_from_string('2019-11-05 12:34:56'); # Today is 2019 Nov 5th
110
    my $nov_6  = dt_from_string('2019-11-06 12:34:56');
111
    my $nov_7  = dt_from_string('2019-11-07 12:34:56');
112
    my $nov_12 = dt_from_string('2019-11-12 12:34:56');
113
    my $nov_13 = dt_from_string('2019-11-13 12:34:56');
114
    my $nov_15 = dt_from_string('2019-11-15 12:34:56');
115
    Time::Fake->offset($now->epoch);
116
117
    subtest 'No holiday' => sub {
118
119
        plan tests => 2;
120
121
        my $library = $builder->build_object({ class => 'Koha::Libraries' });
122
        my $calendar = Koha::Calendar->new( branchcode => $library->branchcode );
123
124
        subtest 'Same hours' => sub {
125
126
            plan tests => 8;
127
128
            # Between 5th and 6th
129
            my $diff_hours = $calendar->hours_between( $now, $nov_6 )->hours;
130
            is( $diff_hours, 1 * 24, 'hours: 1 day, no holiday' );
131
            my $diff_days = $calendar->days_between( $now, $nov_6 )->delta_days;
132
            is( $diff_days, 1, 'days: 1 day, no holiday' );
133
134
            # Between 5th and 7th
135
            $diff_hours = $calendar->hours_between( $now, $nov_7 )->hours;
136
            is( $diff_hours, 2 * 24, 'hours: 2 days, no holiday' );
137
            $diff_days = $calendar->days_between( $now, $nov_7 )->delta_days;
138
            is( $diff_days, 2, 'days: 2 days, no holiday' );
139
140
            # Between 5th and 12th
141
            $diff_hours = $calendar->hours_between( $now, $nov_12 )->hours;
142
            is( $diff_hours, 7 * 24, 'hours: 7 days, no holiday' );
143
            $diff_days = $calendar->days_between( $now, $nov_12 )->delta_days;
144
            is( $diff_days, 7, 'days: 7 days, no holiday' );
145
146
            # Between 5th and 15th
147
            $diff_hours = $calendar->hours_between( $now, $nov_15 )->hours;
148
            is( $diff_hours, 10 * 24, 'hours: 10 days, no holiday' );
149
            $diff_days = $calendar->days_between( $now, $nov_15 )->delta_days;
150
            is( $diff_days, 10, 'days: 10 days, no holiday' );
151
        };
152
153
        subtest 'Different hours' => sub {
154
155
            plan tests => 10;
156
157
            # Between 5th and 5th (Same day short hours loan)
158
            my $diff_hours = $calendar->hours_between( $now, $now->clone->add(hours => 3) )->hours;
159
            is( $diff_hours, 3, 'hours: 3 hours, no holidays' );
160
            my $diff_days = $calendar->days_between( $now, $now->clone->add(hours => 3) )->delta_days;
161
            is( $diff_days, 0, 'days: 3 hours, no holidays' );
162
163
            # Between 5th and 6th
164
            $diff_hours = $calendar->hours_between( $now, $nov_6->clone->subtract(hours => 3) )->hours;
165
            is( $diff_hours, 1 * 24 - 3, 'hours: 21 hours, no holidays' );
166
            $diff_days = $calendar->days_between( $now, $nov_6->clone->subtract(hours => 3) )->delta_days;
167
            is( $diff_days, 1, 'days: 21 hours, no holidays' );
168
169
            # Between 5th and 7th
170
            $diff_hours = $calendar->hours_between( $now, $nov_7->clone->subtract(hours => 3) )->hours;
171
            is( $diff_hours, 2 * 24 - 3, 'hours: 45 hours, no holidays' );
172
            $diff_days = $calendar->days_between( $now, $nov_7->clone->subtract(hours => 3) )->delta_days;
173
            is( $diff_days, 2, 'days: 45 hours, no holidays' );
174
175
            # Between 5th and 12th
176
            $diff_hours = $calendar->hours_between( $now, $nov_12->clone->subtract(hours => 3) )->hours;
177
            is( $diff_hours, 7 * 24 - 3, 'hours: 165 hours, no holidays' );
178
            $diff_days = $calendar->days_between( $now, $nov_12->clone->subtract(hours => 3) )->delta_days;
179
            is( $diff_days, 7, 'days: 165 hours, no holidays' );
180
181
            # Between 5th and 15th
182
            $diff_hours = $calendar->hours_between( $now, $nov_15->clone->subtract(hours => 3) )->hours;
183
            is( $diff_hours, 10 * 24 - 3, 'hours: 237 hours, no holidays' );
184
            $diff_days = $calendar->days_between( $now, $nov_15->clone->subtract(hours => 3) )->delta_days;
185
            is( $diff_days, 10, 'days: 237 hours, no holidays' );
186
        };
187
    };
188
189
    subtest 'With holiday' => sub {
190
        plan tests => 2;
191
192
        my $library = $builder->build_object({ class => 'Koha::Libraries' });
193
194
        # Wednesdays are closed
195
        my $dbh = C4::Context->dbh;
196
        $dbh->do(q|
197
            INSERT INTO repeatable_holidays (branchcode,weekday,day,month,title,description)
198
            VALUES ( ?, ?, NULL, NULL, ?, '' )
199
        |, undef, $library->branchcode, 3, 'Closed on Wednesday');
200
201
        my $calendar = Koha::Calendar->new( branchcode => $library->branchcode );
202
203
        subtest 'Same hours' => sub {
204
            plan tests => 12;
205
206
            my ( $diff_hours, $diff_days );
207
208
            # Between 5th and 6th (This case should never happen in real code, one cannot return on a closed day)
209
            $diff_hours = $calendar->hours_between( $now, $nov_6 )->hours;
210
            is( $diff_hours, 0 * 24, 'hours: 1 day, end_dt = holiday' ); # FIXME Is this really should be 0?
211
            $diff_days = $calendar->days_between( $now, $nov_6)->delta_days;
212
            is( $diff_days, 0, 'days: 1 day, end_dt = holiday' ); # FIXME Is this really should be 0?
213
214
            # Between 6th and 7th (This case should never happen in real code, one cannot issue on a closed day)
215
            $diff_hours = $calendar->hours_between( $nov_6, $nov_7 )->hours;
216
            is( $diff_hours, 0 * 24, 'hours: 1 day, start_dt = holiday' ); # FIXME Is this really should be 0?
217
            $diff_days = $calendar->days_between( $nov_6, $nov_7 )->delta_days;
218
            is( $diff_days, 0, 'days: 1 day, start_dt = holiday' ); # FIXME Is this really should be 0?
219
220
            # Between 5th and 7th
221
            $diff_hours = $calendar->hours_between( $now, $nov_7 )->hours;
222
            is( $diff_hours, 2 * 24 - 1 * 24, 'hours: 2 days, 1 holiday' );
223
            $diff_days = $calendar->days_between( $now, $nov_7 )->delta_days;
224
            is( $diff_days, 2 - 1, 'days: 2 days, 1 holiday' );
225
226
            # Between 5th and 12th
227
            $diff_hours = $calendar->hours_between( $now, $nov_12 )->hours;
228
            is( $diff_hours, 7 * 24 - 1 * 24, 'hours: 7 days, 1 holiday' );
229
            $diff_days = $calendar->days_between( $now, $nov_12)->delta_days;
230
            is( $diff_days, 7 - 1, 'day: 7 days, 1 holiday' );
231
232
            # Between 5th and 13th
233
            $diff_hours = $calendar->hours_between( $now, $nov_13 )->hours;
234
            is( $diff_hours, 8 * 24 - 2 * 24, 'hours: 8 days, 2 holidays' );
235
            $diff_days = $calendar->days_between( $now, $nov_13)->delta_days;
236
            is( $diff_days, 8 - 2, 'days: 8 days, 2 holidays' );
237
238
            # Between 5th and 15th
239
            $diff_hours = $calendar->hours_between( $now, $nov_15 )->hours;
240
            is( $diff_hours, 10 * 24 - 2 * 24, 'hours: 10 days, 2 holidays' );
241
            $diff_days = $calendar->days_between( $now, $nov_15)->delta_days;
242
            is( $diff_days, 10 - 2, 'days: 10 days, 2 holidays' );
243
        };
244
245
        subtest 'Different hours' => sub {
246
            plan tests => 14;
247
248
            my ( $diff_hours, $diff_days );
249
250
            # Between 5th and 5th (Same day short hours loan)
251
            # No test - Tested above as 5th is an open day
252
253
            # Between 5th and 6th (This case should never happen in real code, one cannot return on a closed day)
254
            my $duration = $calendar->hours_between( $now, $nov_6->clone->subtract(hours => 3) );
255
            is( $duration->hours, abs(0 * 24 - 3), 'hours: 21 hours, end_dt = holiday' ); # FIXME $duration->hours always return a abs
256
            is( $duration->is_negative, 1, '? is negative ?' ); # FIXME Do really test for that case in our calls to hours_between?
257
            $duration = $calendar->days_between( $now, $nov_6->clone->subtract(hours => 3) );
258
            is( $duration->hours, abs(0), 'days: 21 hours, end_dt = holiday' ); # FIXME Is this correct?
259
260
            # Between 6th and 7th (This case should never happen in real code, one cannot issue on a closed day)
261
            $duration = $calendar->hours_between( $nov_6, $nov_7->clone->subtract(hours => 3) );
262
            is( $duration->hours, abs(0 * 24 - 3), 'hours: 21 hours, start_dt = holiday' ); # FIXME $duration->hours always return a abs
263
            is( $duration->is_negative, 1, '? is negative ?' ); # FIXME Do really test for that case in our calls to hours_between?
264
            $duration = $calendar->days_between( $nov_6, $nov_7->clone->subtract(hours => 3) );
265
            is( $duration->hours, abs(0), 'days: 21 hours, start_dt = holiday' ); # FIXME Is this correct?
266
267
            # Between 5th and 7th
268
            $diff_hours = $calendar->hours_between( $now, $nov_7->clone->subtract(hours => 3) )->hours;
269
            is( $diff_hours, 2 * 24 - 1 * 24 - 3, 'hours: 45 hours, 1 holiday' );
270
            $diff_days = $calendar->days_between( $now, $nov_7->clone->subtract(hours => 3) )->delta_days;
271
            is( $diff_days, 2 - 1, 'days: 45 hours, 1 holiday' );
272
273
            # Between 5th and 12th
274
            $diff_hours = $calendar->hours_between( $now, $nov_12->clone->subtract(hours => 3) )->hours;
275
            is( $diff_hours, 7 * 24 - 1 * 24 - 3, 'hours: 165 hours, 1 holiday' );
276
            $diff_days = $calendar->days_between( $now, $nov_12->clone->subtract(hours => 3) )->delta_days;
277
            is( $diff_days, 7 - 1, 'days: 165 hours, 1 holiday' );
278
279
            # Between 5th and 13th
280
            $diff_hours = $calendar->hours_between( $now, $nov_13->clone->subtract(hours => 3) )->hours;
281
            is( $diff_hours, 8 * 24 - 2 * 24 - 3, 'hours: 289 hours, 2 holidays ' );
282
            $diff_days = $calendar->days_between( $now, $nov_13->clone->subtract(hours => 3) )->delta_days;
283
            is( $diff_days, 8 - 1, 'days: 289 hours, 2 holidays' );
284
285
            # Between 5th and 15th
286
            $diff_hours = $calendar->hours_between( $now, $nov_15->clone->subtract(hours => 3) )->hours;
287
            is( $diff_hours, 10 * 24 - 2 * 24 - 3, 'hours: 237 hours, 2 holidays' );
288
            $diff_days = $calendar->days_between( $now, $nov_15->clone->subtract(hours => 3) )->delta_days;
289
            is( $diff_days, 10 - 2, 'days: 237 hours, 2 holidays' );
290
        };
291
292
    };
293
294
    Time::Fake->reset;
295
};
296
297
subtest 'is_holiday' => sub {
298
    plan tests => 1;
299
300
    subtest 'weekday holidays' => sub {
301
        plan tests => 7;
302
303
        my $library = $builder->build_object( { class => 'Koha::Libraries' } );
304
305
        my $day = dt_from_string();
306
        my $dow = scalar $day->day_of_week;
307
        $dow = 0 if $dow == 7;
308
309
        # Closed this day of the week
310
        my $dbh = C4::Context->dbh;
311
        $dbh->do(
312
            q|
313
            INSERT INTO repeatable_holidays (branchcode,weekday,day,month,title,description)
314
            VALUES ( ?, ?, NULL, NULL, ?, '' )
315
        |, undef, $library->branchcode, $dow, "TEST"
316
        );
317
318
        # Iterate 7 days
319
        my $sth = $dbh->prepare(
320
"UPDATE repeatable_holidays SET weekday = ? WHERE branchcode = ? AND title = 'TEST'"
321
        );
322
        for my $i ( 0 .. 6 ) {
323
            my $calendar =
324
              Koha::Calendar->new( branchcode => $library->branchcode );
325
326
            is( $calendar->is_holiday($day), 1, $day->day_name() ." works as a repeatable holiday");
327
328
            # Increment the date and holiday day
329
            $day->add( days => 1 );
330
            $dow++;
331
            $dow = 0 if $dow == 7;
332
            $sth->execute($dow, $library->branchcode);
333
        }
334
    };
335
};
336
337
subtest 'get_push_amt' => sub {
338
    plan tests => 1;
339
340
    t::lib::Mocks::mock_preference('useDaysMode', 'Dayweek');
341
342
    subtest 'weekday holidays' => sub {
343
        plan tests => 7;
344
345
        my $library = $builder->build_object( { class => 'Koha::Libraries' } );
346
347
        my $day = dt_from_string();
348
        my $dow = scalar $day->day_of_week;
349
        $dow = 0 if $dow == 7;
350
351
        # Closed this day of the week
352
        my $dbh = C4::Context->dbh;
353
        $dbh->do(
354
            q|
355
            INSERT INTO repeatable_holidays (branchcode,weekday,day,month,title,description)
356
            VALUES ( ?, ?, NULL, NULL, ?, '' )
357
        |, undef, $library->branchcode, $dow, "TEST"
358
        );
359
360
        # Iterate 7 days
361
        my $sth = $dbh->prepare(
362
"UPDATE repeatable_holidays SET weekday = ? WHERE branchcode = ? AND title = 'TEST'"
363
        );
364
        for my $i ( 0 .. 6 ) {
365
            my $calendar =
366
              Koha::Calendar->new( branchcode => $library->branchcode, days_mode => 'Dayweek' );
367
368
            my $npa;
369
            eval {
370
                local $SIG{ALRM} = sub { die "alarm\n" };    # NB: \n required
371
                alarm 2;
372
                $npa = $calendar->next_open_days( $day, 0 );
373
                alarm 0;
374
            };
375
            if ($@) {
376
                die unless $@ eq "alarm\n";    # propagate unexpected errors
377
                # timed out
378
                ok(0, "next_push_amt succeeded for ".$day->day_name()." weekday holiday");
379
            }
380
            else {
381
                ok($npa, "next_push_amt succeeded for ".$day->day_name()." weekday holiday");
382
            }
383
384
            # Increment the date and holiday day
385
            $day->add( days => 1 );
386
            $dow++;
387
            $dow = 0 if $dow == 7;
388
            $sth->execute( $dow, $library->branchcode );
389
        }
390
    };
391
};
392
393
$schema->storage->txn_rollback();
(-)a/t/db_dependent/Circulation.t (-40 / +36 lines)
Lines 32-38 use t::lib::Mocks; Link Here
32
use t::lib::TestBuilder;
32
use t::lib::TestBuilder;
33
33
34
use C4::Accounts;
34
use C4::Accounts;
35
use C4::Calendar qw( new insert_single_holiday insert_week_day_holiday delete_holiday );
36
use C4::Circulation qw( AddIssue AddReturn CanBookBeRenewed GetIssuingCharges AddRenewal GetSoonestRenewDate GetLatestAutoRenewDate LostItem GetUpcomingDueIssues CanBookBeIssued AddIssuingCharge MarkIssueReturned ProcessOfflinePayment transferbook updateWrongTransfer );
35
use C4::Circulation qw( AddIssue AddReturn CanBookBeRenewed GetIssuingCharges AddRenewal GetSoonestRenewDate GetLatestAutoRenewDate LostItem GetUpcomingDueIssues CanBookBeIssued AddIssuingCharge MarkIssueReturned ProcessOfflinePayment transferbook updateWrongTransfer );
37
use C4::Biblio;
36
use C4::Biblio;
38
use C4::Items qw( ModItemTransfer );
37
use C4::Items qw( ModItemTransfer );
Lines 42-47 use C4::Overdues qw( CalcFine UpdateFine get_chargeable_units ); Link Here
42
use C4::Members::Messaging qw( SetMessagingPreference );
41
use C4::Members::Messaging qw( SetMessagingPreference );
43
use Koha::DateUtils qw( dt_from_string output_pref );
42
use Koha::DateUtils qw( dt_from_string output_pref );
44
use Koha::Database;
43
use Koha::Database;
44
use Koha::DiscreteCalendar;
45
use Koha::Items;
45
use Koha::Items;
46
use Koha::Item::Transfers;
46
use Koha::Item::Transfers;
47
use Koha::Checkouts;
47
use Koha::Checkouts;
Lines 115-122 my $mocked_datetime = Test::MockModule->new('DateTime'); Link Here
115
$mocked_datetime->mock( 'now', sub { return $now_value->clone; } );
115
$mocked_datetime->mock( 'now', sub { return $now_value->clone; } );
116
116
117
my $cache = Koha::Caches->get_instance();
117
my $cache = Koha::Caches->get_instance();
118
$dbh->do(q|DELETE FROM special_holidays|);
119
$dbh->do(q|DELETE FROM repeatable_holidays|);
120
my $branches = Koha::Libraries->search();
118
my $branches = Koha::Libraries->search();
121
for my $branch ( $branches->next ) {
119
for my $branch ( $branches->next ) {
122
    my $key = $branch->branchcode . "_holidays";
120
    my $key = $branch->branchcode . "_holidays";
Lines 2633-2648 subtest 'AddReturn + suspension_chargeperiod' => sub { Link Here
2633
    );
2631
    );
2634
2632
2635
    my $now = dt_from_string;
2633
    my $now = dt_from_string;
2636
    my $five_days_ago = $now->clone->subtract( days => 5 );
2634
    my $in_five_days = $now->clone->add( days => 5 );
2637
    # We want to charge 2 days every day, without grace
2635
    # We want to charge 2 days every day, without grace
2638
    # With 5 days of overdue: 5 * Z
2636
    # With 5 days of overdue: 5 * Z
2639
    my $expected_expiration = $now->clone->add( days => ( 5 * 2 ) / 1 );
2637
    my $expected_expiration = $now->clone->add( days => 5 + ( 5 * 2 ) / 1 );
2640
    test_debarment_on_checkout(
2638
    test_debarment_on_checkout(
2641
        {
2639
        {
2642
            item            => $item_1,
2640
            item            => $item_1,
2643
            library         => $library,
2641
            library         => $library,
2644
            patron          => $patron,
2642
            patron          => $patron,
2645
            due_date        => $five_days_ago,
2643
            return_date     => $in_five_days,
2646
            expiration_date => $expected_expiration,
2644
            expiration_date => $expected_expiration,
2647
        }
2645
        }
2648
    );
2646
    );
Lines 2691-2703 subtest 'AddReturn + suspension_chargeperiod' => sub { Link Here
2691
        }
2689
        }
2692
    );
2690
    );
2693
2691
2694
    $expected_expiration = $now->clone->add( days => floor( 5 * 2 ) / 2 );
2692
    $expected_expiration = $now->clone->add( days => 5 + floor( 5 * 2 ) / 2 );
2695
    test_debarment_on_checkout(
2693
    test_debarment_on_checkout(
2696
        {
2694
        {
2697
            item            => $item_1,
2695
            item            => $item_1,
2698
            library         => $library,
2696
            library         => $library,
2699
            patron          => $patron,
2697
            patron          => $patron,
2700
            due_date        => $five_days_ago,
2698
            return_date     => $in_five_days,
2701
            expiration_date => $expected_expiration,
2699
            expiration_date => $expected_expiration,
2702
        }
2700
        }
2703
    );
2701
    );
Lines 2715-2727 subtest 'AddReturn + suspension_chargeperiod' => sub { Link Here
2715
            }
2713
            }
2716
        }
2714
        }
2717
    );
2715
    );
2718
    $expected_expiration = $now->clone->add( days => floor( ( ( 5 - 1 ) / 3 ) * 2 ) );
2716
    $expected_expiration = $now->clone->add( days => 5 + floor( ( ( 5 - 1 ) / 3 ) * 2 ) );
2719
    test_debarment_on_checkout(
2717
    test_debarment_on_checkout(
2720
        {
2718
        {
2721
            item            => $item_1,
2719
            item            => $item_1,
2722
            library         => $library,
2720
            library         => $library,
2723
            patron          => $patron,
2721
            patron          => $patron,
2724
            due_date        => $five_days_ago,
2722
            return_date     => $in_five_days,
2725
            expiration_date => $expected_expiration,
2723
            expiration_date => $expected_expiration,
2726
        }
2724
        }
2727
    );
2725
    );
Lines 2744-2808 subtest 'AddReturn + suspension_chargeperiod' => sub { Link Here
2744
    t::lib::Mocks::mock_preference('SuspensionsCalendar', 'noSuspensionsWhenClosed');
2742
    t::lib::Mocks::mock_preference('SuspensionsCalendar', 'noSuspensionsWhenClosed');
2745
2743
2746
    # Adding a holiday 2 days ago
2744
    # Adding a holiday 2 days ago
2747
    my $calendar = C4::Calendar->new(branchcode => $library->{branchcode});
2745
    my $calendar = Koha::DiscreteCalendar->new(branchcode => $library->{branchcode});
2748
    my $two_days_ago = $now->clone->subtract( days => 2 );
2746
    my $in_two_days = $now->clone->add( days => 2 );
2749
    $calendar->insert_single_holiday(
2747
    $calendar->edit_holiday(
2750
        day             => $two_days_ago->day,
2748
        title           => 'holidayTest+2d',
2751
        month           => $two_days_ago->month,
2749
        holiday_type    => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
2752
        year            => $two_days_ago->year,
2750
        start_date      => $in_two_days,
2753
        title           => 'holidayTest-2d',
2751
        end_date        => $in_two_days,
2754
        description     => 'holidayDesc 2 days ago'
2755
    );
2752
    );
2756
    # With 5 days of overdue, only 4 (x finedays=2) days must charged (one was an holiday)
2753
    # With 5 days of overdue, only 4 (x finedays=2) days must charged (one was an holiday)
2757
    $expected_expiration = $now->clone->add( days => floor( ( ( 5 - 0 - 1 ) / 1 ) * 2 ) );
2754
    $expected_expiration = $now->clone->add( days => 5 + floor( ( ( 5 - 0 - 1 ) / 1 ) * 2 ) );
2758
    test_debarment_on_checkout(
2755
    test_debarment_on_checkout(
2759
        {
2756
        {
2760
            item            => $item_1,
2757
            item            => $item_1,
2761
            library         => $library,
2758
            library         => $library,
2762
            patron          => $patron,
2759
            patron          => $patron,
2763
            due_date        => $five_days_ago,
2760
            return_date     => $in_five_days,
2764
            expiration_date => $expected_expiration,
2761
            expiration_date => $expected_expiration,
2765
        }
2762
        }
2766
    );
2763
    );
2767
2764
2768
    # Adding a holiday 2 days ahead, with finesCalendar=noFinesWhenClosed it should be skipped
2765
    # Adding a holiday 2 days ahead, with finesCalendar=noFinesWhenClosed it should be skipped
2769
    my $two_days_ahead = $now->clone->add( days => 2 );
2766
    my $in_seven_days = $now->clone->add( days => 7 );
2770
    $calendar->insert_single_holiday(
2767
    $calendar->edit_holiday(
2771
        day             => $two_days_ahead->day,
2768
        title           => 'holidayTest+7d',
2772
        month           => $two_days_ahead->month,
2769
        holiday_type    => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
2773
        year            => $two_days_ahead->year,
2770
        start_date      => $in_seven_days,
2774
        title           => 'holidayTest+2d',
2771
        end_date        => $in_seven_days,
2775
        description     => 'holidayDesc 2 days ahead'
2776
    );
2772
    );
2777
2773
2778
    # Same as above, but we should skip D+2
2774
    # Same as above, but we should skip D+2
2779
    $expected_expiration = $now->clone->add( days => floor( ( ( 5 - 0 - 1 ) / 1 ) * 2 ) + 1 );
2775
    $expected_expiration = $now->clone->add( days => 5 + floor( ( ( 5 - 0 - 1 ) / 1 ) * 2 ) + 1 );
2780
    test_debarment_on_checkout(
2776
    test_debarment_on_checkout(
2781
        {
2777
        {
2782
            item            => $item_1,
2778
            item            => $item_1,
2783
            library         => $library,
2779
            library         => $library,
2784
            patron          => $patron,
2780
            patron          => $patron,
2785
            due_date        => $five_days_ago,
2781
            return_date     => $in_five_days,
2786
            expiration_date => $expected_expiration,
2782
            expiration_date => $expected_expiration,
2787
        }
2783
        }
2788
    );
2784
    );
2789
2785
2790
    # Adding another holiday, day of expiration date
2786
    # Adding another holiday, day of expiration date
2791
    my $expected_expiration_dt = dt_from_string($expected_expiration);
2787
    my $expected_expiration_dt = dt_from_string($expected_expiration);
2792
    $calendar->insert_single_holiday(
2788
    $calendar->edit_holiday( {
2793
        day             => $expected_expiration_dt->day,
2789
        title           => 'holidayTest+expected_expiration',
2794
        month           => $expected_expiration_dt->month,
2790
        holiday_type    => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
2795
        year            => $expected_expiration_dt->year,
2791
        start_date      => $expected_expiration_dt,
2796
        title           => 'holidayTest_exp',
2792
        end_date        => $expected_expiration_dt,
2797
        description     => 'holidayDesc on expiration date'
2793
    } );
2798
    );
2794
2799
    # Expiration date will be the day after
2795
    # Expiration date will be the day after
2800
    test_debarment_on_checkout(
2796
    test_debarment_on_checkout(
2801
        {
2797
        {
2802
            item            => $item_1,
2798
            item            => $item_1,
2803
            library         => $library,
2799
            library         => $library,
2804
            patron          => $patron,
2800
            patron          => $patron,
2805
            due_date        => $five_days_ago,
2801
            return_date     => $in_five_days,
2806
            expiration_date => $expected_expiration_dt->clone->add( days => 1 ),
2802
            expiration_date => $expected_expiration_dt->clone->add( days => 1 ),
2807
        }
2803
        }
2808
    );
2804
    );
Lines 2813-2819 subtest 'AddReturn + suspension_chargeperiod' => sub { Link Here
2813
            library         => $library,
2809
            library         => $library,
2814
            patron          => $patron,
2810
            patron          => $patron,
2815
            return_date     => $now->clone->add(days => 5),
2811
            return_date     => $now->clone->add(days => 5),
2816
            expiration_date => $now->clone->add(days => 5 + (5 * 2 - 1) ),
2812
            expiration_date => $now->clone->add(days => 5 + (5 * 2 - 1) + 1 ), # We add an extra +1 because of the holiday
2817
        }
2813
        }
2818
    );
2814
    );
2819
2815
Lines 2824-2830 subtest 'AddReturn + suspension_chargeperiod' => sub { Link Here
2824
            patron          => $patron,
2820
            patron          => $patron,
2825
            due_date        => $now->clone->add(days => 1),
2821
            due_date        => $now->clone->add(days => 1),
2826
            return_date     => $now->clone->add(days => 5),
2822
            return_date     => $now->clone->add(days => 5),
2827
            expiration_date => $now->clone->add(days => 5 + (4 * 2 - 1) ),
2823
            expiration_date => $now->clone->add(days => 5 + (4 * 2 - 1) + 1 ),
2828
        }
2824
        }
2829
    );
2825
    );
2830
2826
Lines 4542-4548 subtest 'Incremented fee tests' => sub { Link Here
4542
    $accountline->delete();
4538
    $accountline->delete();
4543
    $issue->delete();
4539
    $issue->delete();
4544
4540
4545
    my $calendar = C4::Calendar->new( branchcode => $library->id );
4541
    my $calendar = Koha::DiscreteCalendar->new( branchcode => $library->id );
4546
    # DateTime 1..7 (Mon..Sun), C4::Calender 0..6 (Sun..Sat)
4542
    # DateTime 1..7 (Mon..Sun), C4::Calender 0..6 (Sun..Sat)
4547
    my $closed_day =
4543
    my $closed_day =
4548
        ( $dt_from->day_of_week == 6 ) ? 0
4544
        ( $dt_from->day_of_week == 6 ) ? 0
(-)a/t/db_dependent/Circulation/CalcDateDue.t (-24 / +23 lines)
Lines 8-14 use DBI; Link Here
8
use DateTime;
8
use DateTime;
9
use t::lib::Mocks;
9
use t::lib::Mocks;
10
use t::lib::TestBuilder;
10
use t::lib::TestBuilder;
11
use C4::Calendar qw( new insert_single_holiday delete_holiday insert_week_day_holiday );
11
use Koha::DateUtils;
12
use Koha::DiscreteCalendar;
12
13
13
use Koha::CirculationRules;
14
use Koha::CirculationRules;
14
15
Lines 47-58 my $cache = Koha::Caches->get_instance(); Link Here
47
my $key   = $branchcode . "_holidays";
48
my $key   = $branchcode . "_holidays";
48
$cache->clear_from_cache($key);
49
$cache->clear_from_cache($key);
49
50
50
my $dateexpiry = '2013-01-01';
51
my $dateexpiry = dt_from_string->truncate(to => 'day')->add(days => 30, hours => 23, minutes => 59)->iso8601;
51
52
my $borrower = {categorycode => 'B', dateexpiry => $dateexpiry};
52
my $borrower = {categorycode => 'B', dateexpiry => $dateexpiry};
53
my $start_date = DateTime->new({year => 2013, month => 2, day => 9});
53
my $start_date =dt_from_string->truncate(to => 'day')->add(days => 60);
54
my $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
54
my $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
55
is($date, $dateexpiry . 'T23:59:00', 'date expiry');
55
is($date, $dateexpiry, 'date expiry');
56
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
56
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
57
57
58
58
Lines 61-91 t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1); Link Here
61
t::lib::Mocks::mock_preference('useDaysMode', 'noDays');
61
t::lib::Mocks::mock_preference('useDaysMode', 'noDays');
62
62
63
$borrower = {categorycode => 'B', dateexpiry => $dateexpiry};
63
$borrower = {categorycode => 'B', dateexpiry => $dateexpiry};
64
$start_date = DateTime->new({year => 2013, month => 2, day => 9});
64
$start_date =dt_from_string->truncate(to => 'day')->add(days => 60);
65
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
65
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
66
is($date, $dateexpiry . 'T23:59:00', 'date expiry with useDaysMode to noDays');
66
is($date, $dateexpiry, 'date expiry with useDaysMode to noDays');
67
67
68
# Let's add a special holiday on 2013-01-01. With ReturnBeforeExpiry and
68
# Let's add a special holiday on 2013-01-01. With ReturnBeforeExpiry and
69
# useDaysMode different from 'Days', return should forward the dateexpiry.
69
# useDaysMode different from 'Days', return should forward the dateexpiry.
70
my $calendar = C4::Calendar->new(branchcode => $branchcode);
70
my $calendar = Koha::DiscreteCalendar->new({branchcode => $branchcode});
71
$calendar->insert_single_holiday(
71
$calendar->edit_holiday({
72
    day             => 1,
72
    title => 'holidayTest',
73
    month           => 1,
73
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
74
    year            => 2013,
74
    start_date => dt_from_string->add(days=>30),
75
    title           =>'holidayTest',
75
    end_date => dt_from_string->add(days=>30)
76
    description     => 'holidayDesc'
76
});
77
);
78
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
77
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
79
is($date, '2012-12-31T23:59:00', 'date expiry should be 2013-01-01 -1 day');
78
is($date, dt_from_string->truncate(to => 'day')->add(days=>29, hours=>23, minutes=>59), 'date expiry should be 2013-01-01 -1 day');
80
$calendar->insert_single_holiday(
79
81
    day             => 31,
80
$calendar->edit_holiday({
82
    month           => 12,
81
    title => 'holidayTest',
83
    year            => 2012,
82
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
84
    title           =>'holidayTest',
83
    start_date => dt_from_string->add(days => 29),
85
    description     => 'holidayDesc'
84
    end_date => dt_from_string->add(days => 29)
86
);
85
});
87
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
86
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
88
is($date, '2012-12-30T23:59:00', 'date expiry should be 2013-01-01 -2 day');
87
is($date, dt_from_string->truncate(to => 'day')->add(days=> 28, hours=>23, minutes=>59), 'date expiry should be 2013-01-01 -2 day');
89
88
90
89
91
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
90
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
(-)a/t/db_dependent/Circulation/CalcFine.t (-22 / +4 lines)
Lines 82-98 subtest 'Test basic functionality' => sub { Link Here
82
        },
82
        },
83
    );
83
    );
84
84
85
    my $start_dt = DateTime->new(
85
    my $start_dt = DateTime->today;
86
        year       => 2000,
86
    my $end_dt = DateTime->today->add(days => 29);
87
        month      => 1,
88
        day        => 1,
89
    );
90
91
    my $end_dt = DateTime->new(
92
        year       => 2000,
93
        month      => 1,
94
        day        => 30,
95
    );
96
87
97
    my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
88
    my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
98
89
Lines 162-178 subtest 'Test cap_fine_to_replacement_price' => sub { Link Here
162
        }
153
        }
163
    );
154
    );
164
155
165
    my $start_dt = DateTime->new(
156
    my $start_dt = DateTime->today;
166
        year       => 2000,
157
    my $end_dt = DateTime->today->add(days => 29);
167
        month      => 1,
168
        day        => 1,
169
    );
170
171
    my $end_dt = DateTime->new(
172
        year       => 2000,
173
        month      => 1,
174
        day        => 30,
175
    );
176
158
177
    my $item = $builder->build_sample_item(
159
    my $item = $builder->build_sample_item(
178
        {
160
        {
(-)a/t/db_dependent/DiscreteCalendar.t (+462 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2015 Koha Development team
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More tests => 50;
22
use Test::MockModule;
23
24
use C4::Context;
25
use C4::Output;
26
use Koha::DateUtils;
27
use Koha::DiscreteCalendar;
28
29
30
my $module_context = Test::MockModule->new('C4::Context');
31
my $today = DateTime->today;
32
my $schema = Koha::Database->new->schema;
33
$schema->storage->txn_begin;
34
35
my $branch1 = "Library1";
36
my $branch2 = "Library2";
37
38
$schema->resultset('DiscreteCalendar')->search({
39
    branchcode  =>''
40
})->update_all({
41
    is_opened    => 1,
42
    holiday_type => '',
43
    note        => '',
44
    open_hour    => '08:00:00',
45
    close_hour   => '16:00:00'
46
});
47
48
#Added entries for the branches.
49
Koha::DiscreteCalendar->add_new_branch('', $branch1);
50
Koha::DiscreteCalendar->add_new_branch('', $branch2);
51
52
isnt($branch1,'', "First branch to do tests. BranchCode => $branch1");
53
isnt($branch2,'', "Second branch to do tests. BranchCode => $branch2");
54
55
#2 Calendars to make sure branches are treated separately.
56
my $calendar = Koha::DiscreteCalendar->new({branchcode => $branch1});
57
my $calendar2 = Koha::DiscreteCalendar->new({branchcode => $branch2});
58
59
my $unique_holiday = DateTime->today;
60
$calendar->edit_holiday({
61
    title => "Single holiday Today",
62
    holiday_type=> $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
63
    start_date=>$unique_holiday,
64
    end_date=>$unique_holiday
65
});
66
is($calendar->is_opened($unique_holiday), 0, "Branch closed today : $unique_holiday");
67
68
my @unique_holidays = $calendar->get_unique_holidays();
69
is(scalar @unique_holidays, 1, "Set of exception holidays at 1");
70
71
my $yesterday = DateTime->today->subtract(days => 1);
72
$calendar->edit_holiday({
73
    title => "Single holiday Today",
74
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
75
    start_date => $yesterday,
76
    end_date => $yesterday
77
});
78
is($calendar->is_opened($yesterday), 1, "Cannot edit dates in the past without override : $yesterday is not a holiday");
79
80
$calendar->edit_holiday({
81
    title => "Single holiday Today",
82
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
83
    start_date => $yesterday,
84
    end_date => $yesterday,
85
    override => 1
86
});
87
is($calendar->is_opened($yesterday), 0, "Can edit dates in the past without override : $yesterday is a holiday");
88
89
90
my $days_between_start = DateTime->today;
91
my $days_between_end = DateTime->today->add(days => 6);
92
my $days_between = $calendar->days_between($days_between_start, $days_between_end)->in_units('days');
93
is($days_between, 5, "Days between skips holiday");
94
95
my $repeatable_holiday = DateTime->today->add(days => 1);
96
$calendar->edit_holiday({
97
    title => "repeatable",
98
    holiday_type=> $Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE},
99
    start_date=>$repeatable_holiday,
100
    end_date=>$repeatable_holiday
101
});
102
is($calendar->is_opened($repeatable_holiday), 0, "Branch not opened on $repeatable_holiday");
103
104
my @repeatable_holidays = $calendar->get_repeatable_holidays();
105
is(scalar @repeatable_holidays, 1, "Set of repeatable holidays at 1");
106
107
# 1 being mysql DAYOFWEEK() for Sunday
108
$calendar->edit_holiday({
109
    title => "Weekly",
110
    weekday=>1,
111
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY},
112
    start_date=>$today,
113
    end_date=>$today
114
});
115
my @weekly_holidays = $calendar->get_week_days_holidays();
116
is(scalar @weekly_holidays, 1, "Set of weekly holidays at 1");
117
118
my $sunday = DateTime->today->add(days =>( 7 - $today->day_of_week));
119
is($calendar->is_opened($sunday), 0, "Branch not opened on " . $sunday->day_name ."s");
120
121
my $unique_holiday_range_start = DateTime->today->add(days => 2);
122
my $unique_holiday_range_end = DateTime->today->add(days => 7);
123
$calendar->edit_holiday({
124
    title => "Single holiday range",
125
    holiday_type=>"E",
126
    start_date=>$unique_holiday_range_start,
127
    end_date=>$unique_holiday_range_end
128
});
129
@unique_holidays = $calendar->get_unique_holidays();
130
is(scalar @unique_holidays, 8, "Set of exception holidays at 7");
131
132
my $repeatable_holiday_range_start = DateTime->today->add(days => 8);
133
my $repeatable_holiday_range_end = DateTime->today->add(days => 13);
134
$calendar->edit_holiday({
135
    title => "Repeatable holiday range",
136
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE},
137
    start_date=>$repeatable_holiday_range_start,
138
    end_date=>$repeatable_holiday_range_end
139
});
140
@repeatable_holidays = $calendar->get_repeatable_holidays();
141
is(scalar @repeatable_holidays, 7, "Set of repeatable holidays at 7");
142
143
#Hourly loan
144
# ex :
145
# item due      : 2017-01-24 11:00:00
146
# item returned : 2017-01-26 10:00:00
147
# Branch closed : 2017-01-25
148
# Open/close hours : 08:00 to 16:00 (8h day)
149
# Hours due : 5 hours on 2017-01-24 + 2 hours on 2017-01-26 = 7hours
150
151
my $open_hours_since_start = dt_from_string->truncate(to => 'day')->add(days => 40, hours => 11);
152
my $open_hours_since_end = dt_from_string->truncate(to => 'day')->add(days => 42, hours => 10);
153
my $holiday_between =  dt_from_string->truncate(to => 'day')->add(days => 41);
154
$calendar->edit_holiday({
155
    title => '',
156
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
157
    start_date=>$open_hours_since_start,
158
    end_date=>$open_hours_since_end
159
});
160
161
$calendar->edit_holiday({
162
    title => "Single holiday",
163
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
164
    start_date=> $holiday_between,
165
    end_date=>$holiday_between
166
});
167
my $open_hours_between = $calendar->open_hours_between($open_hours_since_start, $open_hours_since_end);
168
is($open_hours_between, 7, "7 Hours open between $open_hours_since_start and $open_hours_since_end");
169
170
my $christmas = DateTime->new(
171
    year  => $today->year(),
172
    month => 12,
173
    day   => 25,
174
);
175
$calendar->edit_holiday({
176
    title => "Christmas",
177
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE},
178
    start_date=>$christmas,
179
    end_date=>$christmas,
180
    override => 1, # necessary if unit tests are run between Christmas and the first of the year
181
});
182
is($calendar->is_opened($christmas), 0, "Branch closed on Christmas : $christmas");
183
184
my $newyear = DateTime->new(
185
    year  => $today->year() +1,
186
    month => 1,
187
    day   => 1,
188
);
189
190
$calendar->edit_holiday({
191
    title => "New Year",
192
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{REPEATABLE},
193
    start_date=>$newyear,
194
    end_date=>$newyear
195
});
196
is($calendar->is_opened($newyear), 0, "Branch closed on New Year : $newyear");
197
198
#Hours between :
199
my $date_due = DateTime->today->add(days =>1);
200
my $date_returned = DateTime->today->add(hours => 8);
201
my $hours_between = $calendar->hours_between($date_due, $date_returned);
202
203
is($hours_between->in_units('hours'), 16, "Date due $date_due, returned $date_returned, 16 hours in advance");
204
205
$date_due = DateTime->today->add(days =>1);
206
$date_returned = DateTime->today->add(days => 2, hours=> 8);
207
$hours_between = $calendar->hours_between($date_due, $date_returned);
208
209
is($hours_between->in_units('hours'), -16, "Date due $date_due, returned $date_returned, 16 hours late");
210
211
212
#delete holidays
213
is($calendar->is_opened($today), 0, "Today is closed");
214
$calendar->edit_holiday({
215
    title => '',
216
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
217
    start_date=>$unique_holiday,
218
    end_date=>$unique_holiday
219
});
220
is($calendar->is_opened($today), 1, "Today's holiday was removed");
221
222
$calendar->edit_holiday({
223
    title => '',
224
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE},
225
    start_date => $yesterday,
226
    end_date => $yesterday,
227
    override => 1
228
});
229
is($calendar->is_opened($yesterday), 1, "Yesterdays's holiday was removed with override");
230
231
my $new_open_hours = '08:00';
232
$calendar->edit_holiday({
233
    title => '',
234
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
235
    open_hour=>$new_open_hours,
236
    close_hour=>'',
237
    start_date=>$today,
238
    end_date=>$today
239
});
240
is($calendar->get_date_info($today, $branch1)->{open_hour}, '08:00:00', "Open hour changed to 08:00:00");
241
242
isnt($calendar->get_date_info($today, $branch1)->{close_hour}, '', "Close hour not removed");
243
244
my $delete_range_end = DateTime->today->add(days => 30);
245
$calendar->edit_holiday({
246
    title => '',
247
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
248
    start_date=>$today,
249
    end_date=>$delete_range_end
250
});
251
252
253
is($calendar->is_opened($today), 1, "Today's holiday was already removed");
254
is($calendar->is_opened(DateTime->today->add(days => 1)), 1, "Tomorrow's holiday was removed");
255
is($calendar->is_opened($delete_range_end), 1, "End of range holiday was removed");
256
257
#Check if other branch was affected
258
my @unique_holidays_branch2 = $calendar2->get_unique_holidays();
259
is(scalar @unique_holidays_branch2, 0, "Set of exception holidays at 0 for branch => $branch2");
260
my @repeatable_holidays_branch2 = $calendar2->get_repeatable_holidays();
261
is(scalar @repeatable_holidays_branch2, 0, "Set of repeatable holidays at 0 for branch => $branch2");
262
my @weekly_holidays_branch2 = $calendar2->get_week_days_holidays();
263
is(scalar @weekly_holidays_branch2, 0, "Set of weekly holidays at 0 for branch => $branch2");
264
265
266
#Tests for addDate()
267
268
my $one_day_dur = DateTime::Duration->new( days => 1 );
269
my $negative_one_day_dur = DateTime::Duration->new( days => - 1 );
270
my $two_day_dur = DateTime::Duration->new( days => 2 );
271
my $seven_day_dur = DateTime::Duration->new( days => 7 );
272
273
#Preference useDaysMode Calendar
274
$calendar->{days_mode} = 'Calendar';
275
$unique_holiday->add(days => 1);
276
my $tomorrow = DateTime->today->add(days => 1);
277
$calendar->edit_holiday({
278
    title => "Single holiday Today",
279
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
280
    start_date=>$tomorrow,
281
    end_date=>$tomorrow
282
});
283
284
is($calendar->addDate( $today, $one_day_dur, 'days' )->ymd(),
285
    $today->add(days => 2)->ymd(),
286
    'Single day add (Calendar)' );
287
288
is($calendar->addDate( $today, $two_day_dur, 'days' )->ymd(),
289
    $today->add(days => 2)->ymd(),
290
    'Two days add, skips holiday (Calendar)' );
291
292
cmp_ok($calendar->addDate( $today, $seven_day_dur, 'days' )->ymd(), 'eq',
293
    $today->add(days => 7)->ymd(),
294
    'Add 7 days (Calendar)' );
295
#Closed Sunday
296
$calendar->edit_holiday({
297
    title => "Weekly",
298
    weekday=>1,
299
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY},
300
    start_date=>$today,
301
    end_date=>$today
302
});
303
is( $calendar->addDate( $sunday, $one_day_dur, 'days' )->day_of_week, 1,
304
    'addDate skips closed Sunday (Calendar)' );
305
#to remove the closed sundays
306
$today = DateTime->today;
307
$calendar->edit_holiday({
308
    title => '',
309
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
310
    start_date=>$today,
311
    end_date=>$delete_range_end
312
});
313
314
is( $calendar->addDate($today, $negative_one_day_dur , 'days')->ymd(),
315
    $today->add(days => - 1)->ymd(),
316
    'Negative call to addDate (Calendar)' );
317
318
#Preference useDaysMode DateDue
319
$calendar->{days_mode} = 'Datedue';
320
#clean everything
321
$today = DateTime->today;
322
$calendar->edit_holiday({
323
    title => '',
324
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
325
    start_date=>$today,
326
    end_date=>$delete_range_end
327
});
328
$calendar->edit_holiday({
329
    title => "Single holiday Today",
330
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
331
    start_date=>$tomorrow,
332
    end_date=>$tomorrow
333
});
334
335
is($calendar->addDate( $today, $one_day_dur, 'days' )->ymd(),
336
    $today->add(days => 2)->ymd(),
337
    'Single day add' );
338
339
is($calendar->addDate( $today, $two_day_dur, 'days' )->ymd(),
340
    $today->add(days => 2)->ymd(),
341
    'Two days add, skips holiday (Datedue)' );
342
343
cmp_ok($calendar->addDate( $today, $seven_day_dur, 'days' )->ymd(), 'eq',
344
    $today->add(days => 7)->ymd(),
345
    'Add 7 days (Datedue)' );
346
#Closed Sunday
347
$calendar->edit_holiday({
348
    title => "Weekly",
349
    weekday=>1,
350
    holiday_type=> $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY},
351
    start_date=>$today,
352
    end_date=>$today
353
});
354
is( $calendar->addDate( $sunday, $one_day_dur, 'days' )->day_of_week, 1,
355
    'addDate skips closed Sunday (Datedue)' );
356
#to remove the closed sundays
357
$today = DateTime->today;
358
$calendar->edit_holiday({
359
    title => '',
360
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
361
    start_date=>$today,
362
    end_date=>$delete_range_end
363
});
364
365
is( $calendar->addDate($today, $negative_one_day_dur , 'days')->ymd(),
366
    $today->add(days => - 1)->ymd(),
367
    'Negative call to addDate (Datedue)' );
368
369
#Preference useDaysMode Days
370
$calendar->{days_mode} = 'Days';
371
#clean everything
372
$today = DateTime->today;
373
$calendar->edit_holiday({
374
    title => '',
375
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE},
376
    start_date=>$today,
377
    end_date=>$delete_range_end
378
});
379
$calendar->edit_holiday({
380
    title => "Single holiday Today",
381
    holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
382
    start_date=>$tomorrow,
383
    end_date=>$tomorrow
384
});
385
is($calendar->addDate( $today, $one_day_dur, 'days' )->ymd(),
386
    $today->add(days => 1)->ymd(),
387
    'Single day add' );
388
389
is($calendar->addDate( $today, $two_day_dur, 'days' )->ymd(),
390
    $today->add(days => 2)->ymd(),
391
    'Two days add, skips holiday (Days)' );
392
393
cmp_ok($calendar->addDate( $today, $seven_day_dur, 'days' )->ymd(), 'eq',
394
    $today->add(days => 7)->ymd(),
395
    'Add 7 days (Days)' );
396
#Closed Sunday
397
$calendar->edit_holiday({
398
    title => "Weekly",
399
    weekday => 1,
400
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{WEEKLY},
401
    start_date => $today,
402
    end_date => $today
403
});
404
is( $calendar->addDate( $sunday, $one_day_dur, 'days' )->day_of_week, 1,
405
    'addDate skips closed Sunday (Days)' );
406
407
is( $calendar->addDate($today, $negative_one_day_dur , 'days')->ymd(),
408
    $today->add(days => - 1)->ymd(),
409
    'Negative call to addDate (Days)' );
410
411
#Days_forward
412
413
#clean the range
414
$today = DateTime->today;
415
$calendar->edit_holiday({
416
    title => '',
417
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE},
418
    start_date => $today,
419
    end_date => DateTime->today->add(days => 20)
420
});
421
my $forwarded_dt = $calendar->days_forward($today, 10);
422
423
my $expected = $today->clone;
424
$expected->add(days => 10);
425
is($forwarded_dt->ymd, $expected->ymd, 'With no holiday on the perioddays_forward should add 10 days');
426
427
#Added a holiday
428
$unique_holiday = DateTime->today->add(days => 15);
429
$calendar->edit_holiday({
430
    title => "Single holiday Today",
431
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
432
    start_date => $unique_holiday,
433
    end_date => $unique_holiday
434
});
435
$forwarded_dt = $calendar->days_forward($today, 20);
436
437
$expected->add(days => 11);
438
is($forwarded_dt->ymd, $expected->ymd, 'With holiday on the perioddays_forward should add 20 days + 1 day for holiday');
439
440
$forwarded_dt = $calendar->days_forward($today, 0);
441
is($forwarded_dt->ymd, $today->ymd, '0 day should return start dt');
442
443
$forwarded_dt = $calendar->days_forward($today, -2);
444
is($forwarded_dt->ymd, $today->ymd, 'negative day should return start dt');
445
446
#copying a branch to an other
447
is($calendar2->is_opened($tomorrow), 1, "$branch2 opened tomorrow");
448
#Added a goliday tomorrow for branch1
449
$calendar->edit_holiday({
450
    title => "Single holiday Today",
451
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
452
    start_date => $tomorrow,
453
    end_date => $tomorrow
454
});
455
#Copy dates from branch1 to branch2
456
$calendar->copy_to_branch($branch2);
457
#Check if branch2 is also closed tomorrow after copying from branch1
458
is($calendar2->is_opened($tomorrow), 0, "$branch2 close tomorrow after copying from $branch1");
459
460
$schema->storage->txn_rollback;
461
462
1;
(-)a/t/db_dependent/Fines.t (-5 / +6 lines)
Lines 1-6 Link Here
1
#!/usr/bin/perl
1
#!/usr/bin/perl
2
2
3
use Modern::Perl;
3
use Modern::Perl;
4
use DateTime;
4
5
5
use C4::Context;
6
use C4::Context;
6
use C4::Overdues qw( CalcFine );
7
use C4::Overdues qw( CalcFine );
Lines 33-45 my $issuingrule = Koha::CirculationRules->set_rules( Link Here
33
34
34
ok( $issuingrule, 'Issuing rule created' );
35
ok( $issuingrule, 'Issuing rule created' );
35
36
36
my $period_start = dt_from_string('2000-01-01');
37
my $period_start = dt_from_string;
37
my $period_end = dt_from_string('2000-01-05');
38
my $period_end = dt_from_string->add(days => 4);
38
39
39
my ( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
40
my ( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
40
is( $fine, 0, '4 days overdue, charge period 7 days, charge at end of interval gives fine of $0' );
41
is( $fine, 0, '4 days overdue, charge period 7 days, charge at end of interval gives fine of $0' );
41
42
42
$period_end = dt_from_string('2000-01-10');
43
$period_end = dt_from_string->add(days => 9);
43
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
44
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
44
is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
45
is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
45
46
Lines 55-64 $issuingrule = Koha::CirculationRules->set_rules( Link Here
55
    }
56
    }
56
);
57
);
57
58
58
$period_end = dt_from_string('2000-01-05');
59
$period_end = dt_from_string->add(days => 4);
59
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
60
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
60
is( $fine, 1, '4 days overdue, charge period 7 days, charge at start of interval gives fine of $1' );
61
is( $fine, 1, '4 days overdue, charge period 7 days, charge at start of interval gives fine of $1' );
61
62
62
$period_end = dt_from_string('2000-01-10');
63
$period_end = dt_from_string->add(days => 9);
63
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
64
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
64
is( $fine, 2, '9 days overdue, charge period 7 days, charge at start of interval gives fine of $2' );
65
is( $fine, 2, '9 days overdue, charge period 7 days, charge at start of interval gives fine of $2' );
(-)a/t/db_dependent/Hold.t (-6 / +14 lines)
Lines 22-28 use C4::Context; Link Here
22
use C4::Biblio qw( AddBiblio );
22
use C4::Biblio qw( AddBiblio );
23
use Koha::Database;
23
use Koha::Database;
24
use Koha::Libraries;
24
use Koha::Libraries;
25
use C4::Calendar qw( new insert_single_holiday );
25
use Koha::DiscreteCalendar;
26
use Koha::Patrons;
26
use Koha::Patrons;
27
use Koha::Holds;
27
use Koha::Holds;
28
use Koha::Item;
28
use Koha::Item;
Lines 68-74 my $hold = Koha::Hold->new( Link Here
68
    {
68
    {
69
        biblionumber   => $biblionumber,
69
        biblionumber   => $biblionumber,
70
        itemnumber     => $item->id(),
70
        itemnumber     => $item->id(),
71
        reservedate    => '2017-01-01',
71
        reservedate    => dt_from_string->subtract(days => 2),
72
        waitingdate    => '2000-01-01',
72
        waitingdate    => '2000-01-01',
73
        borrowernumber => $borrower->{borrowernumber},
73
        borrowernumber => $borrower->{borrowernumber},
74
        branchcode     => $branches[1]->{branchcode},
74
        branchcode     => $branches[1]->{branchcode},
Lines 77-87 my $hold = Koha::Hold->new( Link Here
77
);
77
);
78
$hold->store();
78
$hold->store();
79
79
80
my $b1_cal = C4::Calendar->new( branchcode => $branches[1]->{branchcode} );
80
my $b1_cal = Koha::DiscreteCalendar->new({ branchcode => $branches[1]->{branchcode} });
81
$b1_cal->insert_single_holiday( day => 2, month => 1, year => 2017, title => "Morty Day", description => "Rick" ); #Add a holiday
81
my $holiday = dt_from_string->subtract(days => 1);
82
$b1_cal->edit_holiday({
83
    title => "Morty Day",
84
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
85
    start_date => $holiday,
86
    end_date => $holiday,
87
    override => 1
88
}); #Add a holiday
89
82
my $today = dt_from_string;
90
my $today = dt_from_string;
83
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");
91
is( $hold->age(), $today->delta_days( dt_from_string->subtract(days => 2) )->in_units( 'days' ), "Age of hold is days from reservedate to now if calendar ignored");
84
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");
92
is( $hold->age(1), $today->delta_days( dt_from_string->subtract(days => 2) )->in_units( 'days' ) - 1, "Age of hold is days from reservedate to now minus 1 if calendar used");
85
93
86
is( $hold->suspend, 0, "Hold is not suspended" );
94
is( $hold->suspend, 0, "Hold is not suspended" );
87
$hold->suspend_hold();
95
$hold->suspend_hold();
(-)a/t/db_dependent/Holds.t (-1 lines)
Lines 13-19 use Test::Exception; Link Here
13
use MARC::Record;
13
use MARC::Record;
14
14
15
use C4::Biblio;
15
use C4::Biblio;
16
use C4::Calendar;
17
use C4::Items;
16
use C4::Items;
18
use C4::Reserves qw( AddReserve CalculatePriority ModReserve ToggleSuspend AutoUnsuspendReserves SuspendAll ModReserveMinusPriority AlterPriority CanItemBeReserved CheckReserves );
17
use C4::Reserves qw( AddReserve CalculatePriority ModReserve ToggleSuspend AutoUnsuspendReserves SuspendAll ModReserveMinusPriority AlterPriority CanItemBeReserved CheckReserves );
19
use C4::Circulation qw( CanBookBeRenewed );
18
use C4::Circulation qw( CanBookBeRenewed );
(-)a/t/db_dependent/HoldsQueue.t (-9 / +25 lines)
Lines 11-17 use Modern::Perl; Link Here
11
use Test::More tests => 58;
11
use Test::More tests => 58;
12
use Data::Dumper;
12
use Data::Dumper;
13
13
14
use C4::Calendar qw( new insert_single_holiday );
14
use Koha::DiscreteCalendar;
15
use C4::Context;
15
use C4::Context;
16
use C4::Members;
16
use C4::Members;
17
use C4::Circulation qw( AddIssue AddReturn );
17
use C4::Circulation qw( AddIssue AddReturn );
Lines 200-205 $library2 = $builder->build({ Link Here
200
$library3 = $builder->build({
200
$library3 = $builder->build({
201
    source => 'Branch',
201
    source => 'Branch',
202
});
202
});
203
204
$schema->resultset('DiscreteCalendar')->search({
205
    branchcode  =>''
206
})->update_all({
207
    is_opened    => 1,
208
    holiday_type => '',
209
    note        => '',
210
    open_hour    => '08:00:00',
211
    close_hour   => '16:00:00'
212
});
213
214
Koha::DiscreteCalendar->new({ branchcode => '' })->add_new_branch('', $library1->{branchcode});
215
Koha::DiscreteCalendar->new({ branchcode => '' })->add_new_branch('', $library2->{branchcode});
216
Koha::DiscreteCalendar->new({ branchcode => '' })->add_new_branch('', $library3->{branchcode});
217
203
@branchcodes = ( $library1->{branchcode}, $library2->{branchcode}, $library3->{branchcode} );
218
@branchcodes = ( $library1->{branchcode}, $library2->{branchcode}, $library3->{branchcode} );
204
219
205
my $category = $builder->build({ source => 'Category', value => {exclude_from_local_holds_priority => 0} } );
220
my $category = $builder->build({ source => 'Category', value => {exclude_from_local_holds_priority => 0} } );
Lines 327-342 is( $holds_queue->[1]->{cardnumber}, $borrower2->{cardnumber}, "Holds queue fill Link Here
327
# have 1 row in the holds queue
342
# have 1 row in the holds queue
328
t::lib::Mocks::mock_preference('HoldsQueueSkipClosed', 1);
343
t::lib::Mocks::mock_preference('HoldsQueueSkipClosed', 1);
329
my $today = dt_from_string();
344
my $today = dt_from_string();
330
C4::Calendar->new( branchcode => $branchcodes[0] )->insert_single_holiday(
345
331
    day         => $today->day(),
332
    month       => $today->month(),
333
    year        => $today->year(),
334
    title       => "$today",
335
    description => "$today",
336
);
337
# If the test below is removed, aother tests using the holiday will fail. For some reason if we call is_holiday now
346
# If the test below is removed, aother tests using the holiday will fail. For some reason if we call is_holiday now
338
# the holiday will get set in cache correctly, but not if we let C4::HoldsQueue call is_holiday instead.
347
# the holiday will get set in cache correctly, but not if we let C4::HoldsQueue call is_holiday instead.
339
is( Koha::Calendar->new( branchcode => $branchcodes[0] )->is_holiday( $today ), 1, 'Is today a holiday for pickup branch' );
348
Koha::DiscreteCalendar->new({ branchcode => $branchcodes[0] })->edit_holiday({
349
    title        => "Today",
350
    holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION},
351
    start_date   => $today,
352
    end_date     => $today
353
});
354
355
is( Koha::DiscreteCalendar->new({ branchcode => $branchcodes[0] })->is_holiday( $today ), 1, 'Is today a holiday for pickup branch' );
340
C4::HoldsQueue::CreateQueue();
356
C4::HoldsQueue::CreateQueue();
341
$holds_queue = $dbh->selectall_arrayref("SELECT * FROM tmp_holdsqueue", { Slice => {} });
357
$holds_queue = $dbh->selectall_arrayref("SELECT * FROM tmp_holdsqueue", { Slice => {} });
342
is( scalar( @$holds_queue ), 1, "Holds not filled with items from closed libraries" );
358
is( scalar( @$holds_queue ), 1, "Holds not filled with items from closed libraries" );
(-)a/t/db_dependent/Holidays.t (-281 lines)
Lines 1-281 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 12;
21
22
use DateTime;
23
use DateTime::TimeZone;
24
25
use t::lib::TestBuilder;
26
use C4::Context;
27
use Koha::Database;
28
use Koha::DateUtils qw( dt_from_string );
29
30
BEGIN {
31
    use_ok('Koha::Calendar');
32
    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 ));
33
}
34
35
my $schema = Koha::Database->new->schema;
36
my $dbh = C4::Context->dbh;
37
my $builder = t::lib::TestBuilder->new;
38
39
subtest 'is_holiday timezone tests' => sub {
40
41
    plan tests => 1;
42
43
    $schema->storage->txn_begin;
44
45
    $dbh->do("DELETE FROM special_holidays");
46
    # Clear cache
47
    Koha::Caches->get_instance->flush_all;
48
49
    # Artificially set timezone
50
    my $timezone = 'America/Santiago';
51
    $ENV{TZ} = $timezone;
52
    use POSIX qw(tzset);
53
    tzset;
54
55
    my $branch = $builder->build( { source => 'Branch' } )->{branchcode};
56
    my $calendar = Koha::Calendar->new( branchcode => $branch );
57
58
    C4::Calendar->new( branchcode => $branch )->insert_exception_holiday(
59
        day         => 6,
60
        month       => 9,
61
        year        => 2015,
62
        title       => 'Invalid date',
63
        description => 'Invalid date description',
64
    );
65
66
    my $exception_holiday = DateTime->new( day => 6, month => 9, year => 2015 );
67
    my $now_dt            = DateTime->now;
68
69
    my $diff;
70
    eval { $diff = $calendar->days_between( $now_dt, $exception_holiday ) };
71
    unlike(
72
        $@,
73
        qr/Invalid local time for date in time zone: America\/Santiago/,
74
        'Avoid invalid datetime due to DST'
75
    );
76
77
    $schema->storage->txn_rollback;
78
};
79
80
$schema->storage->txn_begin;
81
82
# Create two fresh branches for the tests
83
my $branch_1 = $builder->build({ source => 'Branch' })->{ branchcode };
84
my $branch_2 = $builder->build({ source => 'Branch' })->{ branchcode };
85
86
C4::Calendar->new( branchcode => $branch_1 )->insert_week_day_holiday(
87
    weekday     => 0,
88
    title       => '',
89
    description => 'Sundays',
90
);
91
92
my $holiday2add = dt_from_string("2015-01-01");
93
C4::Calendar->new( branchcode => $branch_1 )->insert_day_month_holiday(
94
    day         => $holiday2add->day(),
95
    month       => $holiday2add->month(),
96
    year        => $holiday2add->year(),
97
    title       => '',
98
    description => "New Year's Day",
99
);
100
$holiday2add = dt_from_string("2014-12-25");
101
C4::Calendar->new( branchcode => $branch_1 )->insert_day_month_holiday(
102
    day         => $holiday2add->day(),
103
    month       => $holiday2add->month(),
104
    year        => $holiday2add->year(),
105
    title       => '',
106
    description => 'Christmas',
107
);
108
109
my $koha_calendar = Koha::Calendar->new( branchcode => $branch_1 );
110
my $c4_calendar = C4::Calendar->new( branchcode => $branch_1 );
111
112
isa_ok( $koha_calendar, 'Koha::Calendar', 'Koha::Calendar class returned' );
113
isa_ok( $c4_calendar,   'C4::Calendar',   'C4::Calendar class returned' );
114
115
my $sunday = DateTime->new(
116
    year  => 2011,
117
    month => 6,
118
    day   => 26,
119
);
120
my $monday = DateTime->new(
121
    year  => 2011,
122
    month => 6,
123
    day   => 27,
124
);
125
my $christmas = DateTime->new(
126
    year  => 2032,
127
    month => 12,
128
    day   => 25,
129
);
130
my $newyear = DateTime->new(
131
    year  => 2035,
132
    month => 1,
133
    day   => 1,
134
);
135
136
is( $koha_calendar->is_holiday($sunday),    1, 'Sunday is a closed day' );
137
is( $koha_calendar->is_holiday($monday),    0, 'Monday is not a closed day' );
138
is( $koha_calendar->is_holiday($christmas), 1, 'Christmas is a closed day' );
139
is( $koha_calendar->is_holiday($newyear),   1, 'New Years day is a closed day' );
140
141
$dbh->do("DELETE FROM repeatable_holidays");
142
$dbh->do("DELETE FROM special_holidays");
143
144
my $custom_holiday = DateTime->new(
145
    year  => 2013,
146
    month => 11,
147
    day   => 12,
148
);
149
150
my $today = dt_from_string();
151
C4::Calendar->new( branchcode => $branch_2 )->insert_single_holiday(
152
    day         => $today->day(),
153
    month       => $today->month(),
154
    year        => $today->year(),
155
    title       => "$today",
156
    description => "$today",
157
);
158
159
is( Koha::Calendar->new( branchcode => $branch_2 )->is_holiday( $today ), 1, "Today is a holiday for $branch_2" );
160
is( Koha::Calendar->new( branchcode => $branch_1 )->is_holiday( $today ), 0, "Today is not a holiday for $branch_1");
161
162
$schema->storage->txn_rollback;
163
164
subtest 'copy_to_branch' => sub {
165
166
    plan tests => 8;
167
168
    $schema->storage->txn_begin;
169
170
    my $branch1 = $builder->build( { source => 'Branch' } )->{ branchcode };
171
    my $calendar1 = C4::Calendar->new( branchcode => $branch1 );
172
    my $sunday = dt_from_string("2020-03-15");
173
    $calendar1->insert_week_day_holiday(
174
        weekday     => 0,
175
        title       => '',
176
        description => 'Sundays',
177
    );
178
179
    my $day_month = dt_from_string("2020-03-17");
180
    $calendar1->insert_day_month_holiday(
181
        day         => $day_month->day(),
182
        month       => $day_month->month(),
183
        year        => $day_month->year(),
184
        title       => '',
185
        description => "",
186
    );
187
188
    my $future_date = dt_from_string("9999-12-31");
189
    $calendar1->insert_single_holiday(
190
        day         => $future_date->day(),
191
        month       => $future_date->month(),
192
        year        => $future_date->year(),
193
        title       => "",
194
        description => "",
195
    );
196
197
    my $future_exception = dt_from_string("9999-12-30");
198
    $calendar1->insert_exception_holiday(
199
        day         => $future_exception->day(),
200
        month       => $future_exception->month(),
201
        year        => $future_exception->year(),
202
        title       => "",
203
        description => "",
204
    );
205
206
    my $past_date = dt_from_string("2019-11-20");
207
    $calendar1->insert_single_holiday(
208
        day         => $past_date->day(),
209
        month       => $past_date->month(),
210
        year        => $past_date->year(),
211
        title       => "",
212
        description => "",
213
    );
214
215
    my $past_exception = dt_from_string("2020-03-09");
216
    $calendar1->insert_exception_holiday(
217
        day         => $past_exception->day(),
218
        month       => $past_exception->month(),
219
        year        => $past_exception->year(),
220
        title       => "",
221
        description => "",
222
    );
223
224
    my $branch2 = $builder->build( { source => 'Branch' } )->{branchcode};
225
226
    C4::Calendar->new( branchcode => $branch1 )->copy_to_branch( $branch2 );
227
228
    my $calendar2 = C4::Calendar->new( branchcode => $branch2 );
229
    my $exceptions = $calendar2->get_exception_holidays;
230
231
    is( $calendar2->isHoliday( $sunday->day, $sunday->month, $sunday->year ), 1, "Weekday holiday copied to branch 2" );
232
    is( $calendar2->isHoliday( $day_month->day, $day_month->month, $day_month->year ), 1, "Day/month holiday copied to branch 2" );
233
    is( $calendar2->isHoliday( $future_date->day, $future_date->month, $future_date->year ), 1, "Single holiday copied to branch 2" );
234
    is( ( grep { $_->{date} eq "9999-12-30"} values %$exceptions ), 1, "Exception holiday copied to branch 2" );
235
    is( $calendar2->isHoliday( $past_date->day, $past_date->month, $past_date->year ), 0, "Don't copy past single holidays" );
236
    is( ( grep { $_->{date} eq "2020-03-09"} values %$exceptions ), 0, "Don't copy past exception holidays " );
237
238
    C4::Calendar->new( branchcode => $branch1 )->copy_to_branch( $branch2 );
239
240
    #Select all rows with same values from database
241
    my $dbh = C4::Context->dbh;
242
    my $get_repeatable_holidays = "SELECT a.* FROM repeatable_holidays a
243
        JOIN (SELECT branchcode, weekday, day, month, COUNT(*)
244
        FROM repeatable_holidays
245
        GROUP BY branchcode, weekday, day, month HAVING count(*) > 1) b
246
        ON a.branchcode = b.branchcode
247
        AND ( a.weekday = b.weekday OR (a.day = b.day AND a.month = b.month))
248
        ORDER BY a.branchcode;";
249
    my $sth  = $dbh->prepare($get_repeatable_holidays);
250
    $sth->execute;
251
252
    my @repeatable_holidays;
253
    while(my $row = $sth->fetchrow_hashref){
254
        push @repeatable_holidays, $row
255
    }
256
257
    is( scalar(@repeatable_holidays), 0, "None of the repeatable holidays were doubled");
258
259
    my $get_special_holidays = "SELECT a.* FROM special_holidays a
260
    JOIN (SELECT branchcode, day, month, year, isexception, COUNT(*)
261
    FROM special_holidays
262
    GROUP BY branchcode, day, month, year, isexception HAVING count(*) > 1) b
263
    ON a.branchcode = b.branchcode
264
    AND a.day = b.day AND a.month = b.month AND a.year = b.year AND a.isexception = b.isexception
265
    ORDER BY a.branchcode;";
266
    $sth  = $dbh->prepare($get_special_holidays);
267
    $sth->execute;
268
269
    my @special_holidays;
270
    while(my $row = $sth->fetchrow_hashref){
271
        push @special_holidays, $row
272
    }
273
274
    is( scalar(@special_holidays), 0, "None of the special holidays were doubled");
275
276
    $schema->storage->txn_rollback;
277
278
};
279
280
# Clear cache
281
Koha::Caches->get_instance->flush_all;
(-)a/t/db_dependent/Koha/Charges/Fees.t (-2 / +2 lines)
Lines 28-34 use t::lib::TestBuilder; Link Here
28
use t::lib::Dates;
28
use t::lib::Dates;
29
29
30
use Time::Fake;
30
use Time::Fake;
31
use C4::Calendar qw( new insert_week_day_holiday delete_holiday );
31
use Koha::DiscreteCalendar;
32
use Koha::DateUtils qw(dt_from_string);
32
use Koha::DateUtils qw(dt_from_string);
33
33
34
BEGIN {
34
BEGIN {
Lines 357-363 subtest 'accumulate_rentalcharge tests' => sub { Link Here
357
    );
357
    );
358
    $itemtype->rentalcharge_daily_calendar(1)->store();
358
    $itemtype->rentalcharge_daily_calendar(1)->store();
359
359
360
    my $calendar = C4::Calendar->new( branchcode => $library->id );
360
    my $calendar = Koha::DiscreteCalendar->new( branchcode => $library->id );
361
    # DateTime 1..7 (Mon..Sun), C4::Calender 0..6 (Sun..Sat)
361
    # DateTime 1..7 (Mon..Sun), C4::Calender 0..6 (Sun..Sat)
362
    my $closed_day =
362
    my $closed_day =
363
        ( $dt_from->day_of_week == 6 ) ? 0
363
        ( $dt_from->day_of_week == 6 ) ? 0
(-)a/t/db_dependent/Koha/ItemTypes.t (-1 lines)
Lines 25-31 use Test::More tests => 14; Link Here
25
use t::lib::Mocks;
25
use t::lib::Mocks;
26
use t::lib::TestBuilder;
26
use t::lib::TestBuilder;
27
27
28
use C4::Calendar qw( new );
29
use Koha::Biblioitems;
28
use Koha::Biblioitems;
30
use Koha::Libraries;
29
use Koha::Libraries;
31
use Koha::Database;
30
use Koha::Database;
(-)a/t/lib/TestBuilder.pm (-1 / +6 lines)
Lines 450-455 sub _gen_type { Link Here
450
        decimal          => \&_gen_real,
450
        decimal          => \&_gen_real,
451
        double_precision => \&_gen_real,
451
        double_precision => \&_gen_real,
452
452
453
        time      => \&_gen_time,
453
        timestamp => \&_gen_datetime,
454
        timestamp => \&_gen_datetime,
454
        datetime  => \&_gen_datetime,
455
        datetime  => \&_gen_datetime,
455
        date      => \&_gen_date,
456
        date      => \&_gen_date,
Lines 514-519 sub _gen_datetime { Link Here
514
    return $self->schema->storage->datetime_parser->format_datetime(dt_from_string);
515
    return $self->schema->storage->datetime_parser->format_datetime(dt_from_string);
515
}
516
}
516
517
518
sub _gen_time {
519
    my ($self, $params) = @_;
520
    return $self->schema->storage->datetime_parser->format_time(dt_from_string);
521
}
522
517
sub _gen_text {
523
sub _gen_text {
518
    my ($self, $params) = @_;
524
    my ($self, $params) = @_;
519
    # From perldoc String::Random
525
    # From perldoc String::Random
520
- 

Return to bug 17015