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

(-)a/Koha/Calendar.pm (-12 / +18 lines)
Lines 33-60 sub _init { Link Here
33
    my $self       = shift;
33
    my $self       = shift;
34
    my $branch     = $self->{branchcode};
34
    my $branch     = $self->{branchcode};
35
    my $dbh        = C4::Context->dbh();
35
    my $dbh        = C4::Context->dbh();
36
    my $repeat_sth = $dbh->prepare(
36
    my $weekly_closed_days_sth = $dbh->prepare(
37
'SELECT * from repeatable_holidays WHERE branchcode = ? AND ISNULL(weekday) = ?'
37
'SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL'
38
    );
38
    );
39
    $repeat_sth->execute( $branch, 0 );
39
    $weekly_closed_days_sth->execute( $branch );
40
    $self->{weekly_closed_days} = [ 0, 0, 0, 0, 0, 0, 0 ];
40
    $self->{weekly_closed_days} = [ 0, 0, 0, 0, 0, 0, 0 ];
41
    Readonly::Scalar my $sunday => 7;
41
    Readonly::Scalar my $sunday => 7;
42
    while ( my $tuple = $repeat_sth->fetchrow_hashref ) {
42
    while ( my $tuple = $weekly_closed_days_sth->fetchrow_hashref ) {
43
        $self->{weekly_closed_days}->[ $tuple->{weekday} ] = 1;
43
        $self->{weekly_closed_days}->[ $tuple->{weekday} ] = 1;
44
    }
44
    }
45
    $repeat_sth->execute( $branch, 1 );
45
    my $day_month_closed_days_sth = $dbh->prepare(
46
'SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL'
47
    );
48
    $day_month_closed_days_sth->execute( $branch );
46
    $self->{day_month_closed_days} = {};
49
    $self->{day_month_closed_days} = {};
47
    while ( my $tuple = $repeat_sth->fetchrow_hashref ) {
50
    while ( my $tuple = $day_month_closed_days_sth->fetchrow_hashref ) {
48
        $self->{day_month_closed_days}->{ $tuple->{month} }->{ $tuple->{day} } =
51
        $self->{day_month_closed_days}->{ $tuple->{month} }->{ $tuple->{day} } =
49
          1;
52
          1;
50
    }
53
    }
51
54
52
    my $special = $dbh->prepare(
55
    my $exception_holidays_sth = $dbh->prepare(
53
'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = ?'
56
'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1'
54
    );
57
    );
55
    $special->execute( $branch, 1 );
58
    $exception_holidays_sth->execute( $branch );
56
    my $dates = [];
59
    my $dates = [];
57
    while ( my ( $day, $month, $year ) = $special->fetchrow ) {
60
    while ( my ( $day, $month, $year ) = $exception_holidays_sth->fetchrow ) {
58
        push @{$dates},
61
        push @{$dates},
59
          DateTime->new(
62
          DateTime->new(
60
            day       => $day,
63
            day       => $day,
Lines 66-74 sub _init { Link Here
66
    $self->{exception_holidays} =
69
    $self->{exception_holidays} =
67
      DateTime::Set->from_datetimes( dates => $dates );
70
      DateTime::Set->from_datetimes( dates => $dates );
68
71
69
    $special->execute( $branch, 0 );
72
    my $single_holidays_sth = $dbh->prepare(
73
'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0'
74
    );
75
    $single_holidays_sth->execute( $branch );
70
    $dates = [];
76
    $dates = [];
71
    while ( my ( $day, $month, $year ) = $special->fetchrow ) {
77
    while ( my ( $day, $month, $year ) = $single_holidays_sth->fetchrow ) {
72
        push @{$dates},
78
        push @{$dates},
73
          DateTime->new(
79
          DateTime->new(
74
            day       => $day,
80
            day       => $day,
(-)a/t/Calendar.t (-106 / +246 lines)
Lines 4-10 use strict; Link Here
4
use warnings;
4
use warnings;
5
use DateTime;
5
use DateTime;
6
use DateTime::Duration;
6
use DateTime::Duration;
7
use Test::More tests => 26;
7
use Test::More tests => 35;
8
use Test::MockModule;
9
use DBD::Mock;
8
use Koha::DateUtils;
10
use Koha::DateUtils;
9
11
10
BEGIN {
12
BEGIN {
Lines 15-138 BEGIN { Link Here
15
    use_ok('C4::Calendar');
17
    use_ok('C4::Calendar');
16
}
18
}
17
19
18
my $cal = Koha::Calendar->new( TEST_MODE => 1 );
20
my $module_context = new Test::MockModule('C4::Context');
21
$module_context->mock(
22
    '_new_dbh',
23
    sub {
24
        my $dbh = DBI->connect( 'DBI:Mock:', '', '' )
25
          || die "Cannot create handle: $DBI::errstr\n";
26
        return $dbh;
27
    }
28
);
29
30
# We need to mock the C4::Context->preference method for
31
# simplicity and re-usability of the session definition. Any
32
# syspref fits for syspref-agnostic tests.
33
$module_context->mock(
34
    'preference',
35
    sub {
36
        return 'Calendar';
37
    }
38
);
39
40
41
my $holidays_session = DBD::Mock::Session->new('holidays_session' => (
42
    { # weekly holidays
43
        statement => "SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL",
44
        results   => [
45
                        ['weekday'],
46
                        [0],    # sundays
47
                        [6]     # saturdays
48
                     ]
49
    },
50
    { # day and month repeatable holidays
51
        statement => "SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL",
52
        results   => [
53
                        [ 'month', 'day' ],
54
                        [ 1, 1 ],   # new year's day
55
                        [12,25]     # christmas
56
                     ]
57
    },
58
    { # exception holidays
59
        statement => "SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1",
60
        results   => [
61
                        [ 'day', 'month', 'year' ],
62
                        [ 11, 11, 2012 ] # sunday exception
63
                     ]
64
    },
65
    { # single holidays
66
        statement => "SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0",
67
        results   => [
68
                        [ 'day', 'month', 'year' ],
69
                        [ 1, 6, 2011 ],  # single holiday
70
                        [ 4, 7, 2012 ]
71
                     ]
72
    }
73
));
74
75
# Initialize the global $dbh variable
76
my $dbh = C4::Context->dbh();
77
# Apply the mock session
78
$dbh->{ mock_session } = $holidays_session;
79
# 'MPL' branch is arbitrary, is not used at all but is needed for initialization
80
my $cal = Koha::Calendar->new( branchcode => 'MPL' );
19
81
20
isa_ok( $cal, 'Koha::Calendar', 'Calendar class returned' );
82
isa_ok( $cal, 'Koha::Calendar', 'Calendar class returned' );
21
83
84
22
my $saturday = DateTime->new(
85
my $saturday = DateTime->new(
23
    year      => 2011,
86
    year      => 2012,
24
    month     => 6,
87
    month     => 11,
25
    day       => 25,
88
    day       => 24,
26
    time_zone => 'Europe/London',
27
);
89
);
90
28
my $sunday = DateTime->new(
91
my $sunday = DateTime->new(
29
    year      => 2011,
92
    year      => 2012,
30
    month     => 6,
93
    month     => 11,
31
    day       => 26,
94
    day       => 25,
32
    time_zone => 'Europe/London',
33
);
95
);
96
34
my $monday = DateTime->new(
97
my $monday = DateTime->new(
35
    year      => 2011,
98
    year      => 2012,
36
    month     => 6,
99
    month     => 11,
37
    day       => 27,
100
    day       => 26,
38
    time_zone => 'Europe/London',
39
);
101
);
40
my $bloomsday = DateTime->new(
102
41
    year      => 2011,
103
my $new_year = DateTime->new(
42
    month     => 6,
104
    year        => 2013,
43
    day       => 16,
105
    month       => 1,
44
    time_zone => 'Europe/London',
106
    day         => 1,
45
);    # should be a holiday
107
);
46
my $special = DateTime->new(
108
109
my $single_holiday = DateTime->new(
47
    year      => 2011,
110
    year      => 2011,
48
    month     => 6,
111
    month     => 6,
49
    day       => 1,
112
    day       => 1,
50
    time_zone => 'Europe/London',
51
);    # should be a holiday
113
);    # should be a holiday
114
52
my $notspecial = DateTime->new(
115
my $notspecial = DateTime->new(
53
    year      => 2011,
116
    year      => 2011,
54
    month     => 6,
117
    month     => 6,
55
    day       => 2,
118
    day       => 2
56
    time_zone => 'Europe/London',
57
);    # should NOT be a holiday
119
);    # should NOT be a holiday
58
120
59
is( $cal->is_holiday($sunday), 1, 'Sunday is a closed day' );   # wee free test;
121
my $sunday_exception = DateTime->new(
60
is( $cal->is_holiday($monday),     0, 'Monday is not a closed day' );    # alas
122
    year      => 2012,
61
is( $cal->is_holiday($bloomsday),  1, 'month/day closed day test' );
123
    month     => 11,
62
is( $cal->is_holiday($special),    1, 'special closed day test' );
124
    day       => 11
63
is( $cal->is_holiday($notspecial), 0, 'open day test' );
125
);
64
126
65
my $dt = $cal->addDate( $saturday, 1, 'days' );
127
my $day_after_christmas = DateTime->new(
66
is( $dt->day_of_week, 1, 'addDate skips closed Sunday' );
128
    year    => 2012,
129
    month   => 12,
130
    day     => 26
131
);  # for testing negative addDate
132
133
134
{   # Syspref-agnostic tests
135
    is ( $saturday->day_of_week, 6, '\'$saturday\' is actually a saturday (6th day of week)');
136
    is ( $sunday->day_of_week, 7, '\'$sunday\' is actually a sunday (7th day of week)');
137
    is ( $monday->day_of_week, 1, '\'$monday\' is actually a monday (1st day of week)');
138
    is ( $cal->is_holiday($saturday), 1, 'Saturday is a closed day' );
139
    is ( $cal->is_holiday($sunday), 1, 'Sunday is a closed day' );
140
    is ( $cal->is_holiday($monday), 0, 'Monday is not a closed day' );
141
    is ( $cal->is_holiday($new_year), 1, 'Month/Day closed day test (New year\'s day)' );
142
    is ( $cal->is_holiday($single_holiday), 1, 'Single holiday closed day test' );
143
    is ( $cal->is_holiday($notspecial), 0, 'Fixed single date that is not a holiday test' );
144
    is ( $cal->is_holiday($sunday_exception), 0, 'Exception holiday is not a closed day test' );
145
}
67
146
68
$dt = $cal->addDate( $bloomsday, -1 );
69
is( $dt->ymd(), '2011-06-15', 'Negative call to addDate' );
70
147
71
my $test_dt = DateTime->new(    # Monday
148
{   # Bugzilla #8966 - is_holiday truncates referenced date
72
    year      => 2012,
149
    my $later_dt = DateTime->new(    # Monday
73
    month     => 7,
150
        year      => 2012,
74
    day       => 23,
151
        month     => 9,
75
    hour      => 11,
152
        day       => 17,
76
    minute    => 53,
153
        hour      => 17,
77
    time_zone => 'Europe/London',
154
        minute    => 30,
78
);
155
        time_zone => 'Europe/London',
156
    );
79
157
80
my $later_dt = DateTime->new(    # Monday
81
    year      => 2012,
82
    month     => 9,
83
    day       => 17,
84
    hour      => 17,
85
    minute    => 30,
86
    time_zone => 'Europe/London',
87
);
88
158
89
my $daycount = $cal->days_between( $test_dt, $later_dt );
159
    is( $cal->is_holiday($later_dt), 0, 'bz-8966 (1/2) Apply is_holiday for the next test' );
90
cmp_ok( $daycount->in_units('days'),
160
    cmp_ok( $later_dt, 'eq', '2012-09-17T17:30:00', 'bz-8966 (2/2) Date should be the same after is_holiday' );
91
    '==', 48, 'days_between calculates correctly' );
161
}
92
162
93
my $ret;
163
94
164
{   # Bugzilla #8800 - is_holiday should use truncated date for 'contains' call
95
$cal->set_daysmode('Calendar');
165
    my $single_holiday_time = DateTime->new(
96
166
        year  => 2011,
97
# see bugzilla #8966
167
        month => 6,
98
is( $cal->is_holiday($later_dt), 0, 'is holiday for the next test' );
168
        day   => 1,
99
cmp_ok( $later_dt, 'eq', '2012-09-17T17:30:00', 'Date should be the same after is_holiday' );
169
        hour  => 11,
100
170
        minute  => 2
101
# example tests for bug report
171
    );
102
$cal->clear_weekly_closed_days();
172
103
173
    is( $cal->is_holiday($single_holiday_time),
104
$daycount = $cal->days_between( dt_from_string('2012-01-10','iso'),
174
        $cal->is_holiday($single_holiday) ,
105
    dt_from_string("2012-05-05",'iso') )->in_units('days');
175
        'bz-8800 is_holiday should truncate the date for holiday validation' );
106
cmp_ok( $daycount, '==', 116, 'test larger intervals' );
176
}
107
$daycount = $cal->days_between( dt_from_string("2012-01-01",'iso'),
177
108
    dt_from_string("2012-05-05",'iso') )->in_units('days');
178
109
cmp_ok( $daycount, '==', 125, 'test positive intervals' );
179
    my $one_day_dur = DateTime::Duration->new( days => 1 );
110
my $daycount2 = $cal->days_between( dt_from_string("2012-05-05",'iso'),
180
    my $two_day_dur = DateTime::Duration->new( days => 2 );
111
    dt_from_string("2012-01-01",'iso') )->in_units('days');
181
    my $seven_day_dur = DateTime::Duration->new( days => 7 );
112
cmp_ok( $daycount2, '==', $daycount, 'test parameter order not relevant' );
182
113
$daycount = $cal->days_between( dt_from_string("2012-07-01",'iso'),
183
    my $dt = dt_from_string( '2012-07-03','iso' );
114
    dt_from_string("2012-07-15",'iso') )->in_units('days');
184
    my $test_dt = DateTime->new(    # Monday
115
cmp_ok( $daycount, '==', 14, 'days_between calculates correctly' );
185
        year      => 2012,
116
$cal->add_holiday( dt_from_string('2012-07-06','iso') );
186
        month     => 7,
117
$daycount = $cal->days_between( dt_from_string("2012-07-01",'iso'),
187
        day       => 23,
118
    dt_from_string("2012-07-15",'iso') )->in_units('days');
188
        hour      => 11,
119
cmp_ok( $daycount, '==', 13, 'holiday correctly recognized' );
189
        minute    => 53,
120
190
    );
121
$cal->add_holiday( dt_from_string('2012-07-07','iso') );
191
122
$daycount = $cal->days_between( dt_from_string("2012-07-01",'iso'),
192
    my $later_dt = DateTime->new(    # Monday
123
    dt_from_string("2012-07-15",'iso') )->in_units('days');
193
        year      => 2012,
124
cmp_ok( $daycount, '==', 12, 'multiple holidays correctly recognized' );
194
        month     => 9,
125
195
        day       => 17,
126
my $one_day_dur = DateTime::Duration->new( days => 1 );
196
        hour      => 17,
127
my $two_day_dur = DateTime::Duration->new( days => 2 );
197
        minute    => 30,
128
my $seven_day_dur = DateTime::Duration->new( days => 7 );
198
        time_zone => 'Europe/London',
129
199
    );
130
    ## 'Datedue' tests
200
131
    $cal = Koha::Calendar->new( TEST_MODE => 1 ,
201
132
                                days_mode => 'Datedue');
202
{    ## 'Datedue' tests
133
203
134
    $cal->add_holiday( dt_from_string('2012-07-04','iso') );
204
    $module_context->unmock('preference');
135
    $dt = dt_from_string( '2012-07-03','iso' );
205
    $module_context->mock(
206
        'preference',
207
        sub {
208
            return 'Datedue';
209
        }
210
    );
211
    # rewind dbh session
212
    $holidays_session->reset;
213
214
215
    $cal = Koha::Calendar->new( branchcode => 'MPL' );
136
216
137
    is($cal->addDate( $dt, $one_day_dur, 'days' ),
217
    is($cal->addDate( $dt, $one_day_dur, 'days' ),
138
        dt_from_string('2012-07-05','iso'),
218
        dt_from_string('2012-07-05','iso'),
Lines 146-158 my $seven_day_dur = DateTime::Duration->new( days => 7 ); Link Here
146
        '2012-07-30T11:53:00',
226
        '2012-07-30T11:53:00',
147
        'Add 7 days (Datedue)' );
227
        'Add 7 days (Datedue)' );
148
228
229
    is( $cal->addDate( $saturday, $one_day_dur, 'days' )->day_of_week, 1,
230
        'addDate skips closed Sunday (Datedue)' );
231
232
    is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-24',
233
        'Negative call to addDate (Datedue)' );
234
235
    ## Note that the days_between API says closed days are not considered.
236
    ## This tests are here as an API test.
237
    cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
238
                '==', 40, 'days_between calculates correctly (Days)' );
149
239
240
    cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
241
                '==', 40, 'Test parameter order not relevant (Days)' );
150
242
151
    ## 'Calendar' tests'
152
    $cal = Koha::Calendar->new( TEST_MODE => 1,
153
                                days_mode => 'Calendar' );
154
243
155
    $cal->add_holiday( dt_from_string('2012-07-04','iso') );
244
}
245
246
247
{   ## 'Calendar' tests'
248
249
    $module_context->unmock('preference');
250
    $module_context->mock(
251
        'preference',
252
        sub {
253
            return 'Calendar';
254
        }
255
    );
256
    # rewind dbh session
257
    $holidays_session->reset;
258
259
    $cal = Koha::Calendar->new( branchcode => 'MPL' );
260
156
    $dt = dt_from_string('2012-07-03','iso');
261
    $dt = dt_from_string('2012-07-03','iso');
157
262
158
    is($cal->addDate( $dt, $one_day_dur, 'days' ),
263
    is($cal->addDate( $dt, $one_day_dur, 'days' ),
Lines 160-175 my $seven_day_dur = DateTime::Duration->new( days => 7 ); Link Here
160
        'Single day add (Calendar)' );
265
        'Single day add (Calendar)' );
161
266
162
    cmp_ok($cal->addDate( $test_dt, $seven_day_dur, 'days' ), 'eq',
267
    cmp_ok($cal->addDate( $test_dt, $seven_day_dur, 'days' ), 'eq',
163
       '2012-07-31T11:53:00',
268
       '2012-08-01T11:53:00',
164
       'Add 7 days (Calendar)' );
269
       'Add 7 days (Calendar)' );
165
270
271
    is( $cal->addDate( $saturday, $one_day_dur, 'days' )->day_of_week, 1,
272
            'addDate skips closed Sunday (Calendar)' );
273
274
    is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-24',
275
            'Negative call to addDate (Calendar)' );
166
276
277
    cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
278
                '==', 40, 'days_between calculates correctly (Calendar)' );
279
280
    cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
281
                '==', 40, 'Test parameter order not relevant (Calendar)' );
282
}
167
283
168
    ## 'Days' tests
169
    $cal = Koha::Calendar->new( TEST_MODE => 1,
170
                                days_mode => 'Days' );
171
284
172
    $cal->add_holiday( dt_from_string('2012-07-04','iso') );
285
{   ## 'Days' tests
286
    $module_context->unmock('preference');
287
    $module_context->mock(
288
        'preference',
289
        sub {
290
            return 'Days';
291
        }
292
    );
293
    # rewind dbh session
294
    $holidays_session->reset;
295
296
    $cal = Koha::Calendar->new( branchcode => 'MPL' );
297
173
    $dt = dt_from_string('2012-07-03','iso');
298
    $dt = dt_from_string('2012-07-03','iso');
174
299
175
    is($cal->addDate( $dt, $one_day_dur, 'days' ),
300
    is($cal->addDate( $dt, $one_day_dur, 'days' ),
Lines 179-181 my $seven_day_dur = DateTime::Duration->new( days => 7 ); Link Here
179
    cmp_ok($cal->addDate( $test_dt, $seven_day_dur, 'days' ),'eq',
304
    cmp_ok($cal->addDate( $test_dt, $seven_day_dur, 'days' ),'eq',
180
        '2012-07-30T11:53:00',
305
        '2012-07-30T11:53:00',
181
        'Add 7 days (Days)' );
306
        'Add 7 days (Days)' );
182
- 
307
308
    is( $cal->addDate( $saturday, $one_day_dur, 'days' )->day_of_week, 7,
309
        'addDate doesn\'t skip closed Sunday (Days)' );
310
311
    is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-25',
312
        'Negative call to addDate (Days)' );
313
314
    ## Note that the days_between API says closed days are not considered.
315
    ## This tests are here as an API test.
316
    cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
317
                '==', 40, 'days_between calculates correctly (Days)' );
318
319
    cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
320
                '==', 40, 'Test parameter order not relevant (Days)' );
321
322
}

Return to bug 9209