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

(-)a/C4/Calendar.pm (-616 / +153 lines)
Lines 15-726 package C4::Calendar; Link Here
15
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
15
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
16
# Suite 330, Boston, MA  02111-1307 USA
16
# Suite 330, Boston, MA  02111-1307 USA
17
17
18
use strict;
18
use Modern::Perl;
19
use warnings;
20
use vars qw($VERSION @EXPORT);
19
use vars qw($VERSION @EXPORT);
21
20
22
use Carp;
21
use Carp;
23
use Date::Calc qw( Date_to_Days Today);
24
22
25
use C4::Context;
23
use C4::Context;
26
24
25
our ( @ISA, @EXPORT );
26
27
BEGIN {
28
    @ISA = qw( Exporter );
29
    @EXPORT = qw(
30
        GetSingleEvents
31
        GetWeeklyEvents
32
        GetYearlyEvents
33
        ModSingleEvent
34
        ModRepeatingEvent
35
        DelSingleEvent
36
        DelRepeatingEvent
37
        CopyAllEvents
38
    );
39
}
40
27
use constant ISO_DATE_FORMAT => "%04d-%02d-%02d";
41
use constant ISO_DATE_FORMAT => "%04d-%02d-%02d";
28
=head1 NAME
42
=head1 NAME
29
43
30
C4::Calendar::Calendar - Koha module dealing with holidays.
44
C4::Calendar - Koha module dealing with holidays.
31
45
32
=head1 SYNOPSIS
46
=head1 SYNOPSIS
33
47
34
    use C4::Calendar::Calendar;
48
    use C4::Calendar;
35
49
36
=head1 DESCRIPTION
50
=head1 DESCRIPTION
37
51
38
This package is used to deal with holidays. Through this package, you can set 
52
This package is used to deal with hours and holidays;
39
all kind of holidays for the library.
40
53
41
=head1 FUNCTIONS
54
=head1 FUNCTIONS
42
55
43
=head2 new
56
=head2 GetSingleEvents
44
57
45
  $calendar = C4::Calendar->new(branchcode => $branchcode);
58
  \@events = GetSingleEvents( $branchcode )
46
59
47
Each library branch has its own Calendar.  
60
Get the non-repeating events for the given library.
48
C<$branchcode> specifies which Calendar you want.
49
61
50
=cut
62
=cut
51
63
52
sub new {
64
sub GetSingleEvents {
53
    my $classname = shift @_;
65
    my ( $branchcode ) = @_;
54
    my %options = @_;
66
55
    my $self = bless({}, $classname);
67
    return C4::Context->dbh->selectall_arrayref( q{
56
    foreach my $optionName (keys %options) {
68
        SELECT
57
        $self->{lc($optionName)} = $options{$optionName};
69
            CONCAT(LPAD(year, 4, '0'), '-', LPAD(month, 2, '0'), '-', LPAD(day, 2, '0')) as event_date,
58
    }
70
            0 as open_hour, 0 as open_minute, IF(isexception, 24, 0) as close_hour,
59
    defined($self->{branchcode}) or croak "No branchcode argument to new.  Should be C4::Calendar->new(branchcode => \$branchcode)";
71
            0 as close_minute, title, description, IF(isexception, 0, 1) as closed
60
    $self->_init($self->{branchcode});
72
        FROM special_holidays
61
    return $self;
73
        WHERE branchcode = ?
62
}
74
    }, { Slice => {} }, $branchcode );
63
64
sub _init {
65
    my $self = shift @_;
66
    my $branch = shift;
67
    defined($branch) or die "No branchcode sent to _init";  # must test for defined here and above to allow ""
68
    my $dbh = C4::Context->dbh();
69
    my $repeatable = $dbh->prepare( 'SELECT *
70
                                       FROM repeatable_holidays
71
                                      WHERE ( branchcode = ? )
72
                                        AND (ISNULL(weekday) = ?)' );
73
    $repeatable->execute($branch,0);
74
    my %week_days_holidays;
75
    while (my $row = $repeatable->fetchrow_hashref) {
76
        my $key = $row->{weekday};
77
        $week_days_holidays{$key}{title}       = $row->{title};
78
        $week_days_holidays{$key}{description} = $row->{description};
79
    }
80
    $self->{'week_days_holidays'} = \%week_days_holidays;
81
82
    $repeatable->execute($branch,1);
83
    my %day_month_holidays;
84
    while (my $row = $repeatable->fetchrow_hashref) {
85
        my $key = $row->{month} . "/" . $row->{day};
86
        $day_month_holidays{$key}{title}       = $row->{title};
87
        $day_month_holidays{$key}{description} = $row->{description};
88
        $day_month_holidays{$key}{day} = sprintf("%02d", $row->{day});
89
        $day_month_holidays{$key}{month} = sprintf("%02d", $row->{month});
90
    }
91
    $self->{'day_month_holidays'} = \%day_month_holidays;
92
93
    my $special = $dbh->prepare( 'SELECT day, month, year, title, description
94
                                    FROM special_holidays
95
                                   WHERE ( branchcode = ? )
96
                                     AND (isexception = ?)' );
97
    $special->execute($branch,1);
98
    my %exception_holidays;
99
    while (my ($day, $month, $year, $title, $description) = $special->fetchrow) {
100
        $exception_holidays{"$year/$month/$day"}{title} = $title;
101
        $exception_holidays{"$year/$month/$day"}{description} = $description;
102
        $exception_holidays{"$year/$month/$day"}{date} = 
103
		sprintf(ISO_DATE_FORMAT, $year, $month, $day);
104
    }
105
    $self->{'exception_holidays'} = \%exception_holidays;
106
107
    $special->execute($branch,0);
108
    my %single_holidays;
109
    while (my ($day, $month, $year, $title, $description) = $special->fetchrow) {
110
        $single_holidays{"$year/$month/$day"}{title} = $title;
111
        $single_holidays{"$year/$month/$day"}{description} = $description;
112
        $single_holidays{"$year/$month/$day"}{date} = 
113
		sprintf(ISO_DATE_FORMAT, $year, $month, $day);
114
    }
115
    $self->{'single_holidays'} = \%single_holidays;
116
    return $self;
117
}
75
}
118
76
119
=head2 get_week_days_holidays
77
=head2 GetWeeklyEvents
120
78
121
   $week_days_holidays = $calendar->get_week_days_holidays();
79
  \@events = GetWeeklyEvents( $branchcode )
122
80
123
Returns a hash reference to week days holidays.
81
Get the weekly-repeating events for the given library.
124
82
125
=cut
83
=cut
126
84
127
sub get_week_days_holidays {
85
sub GetWeeklyEvents {
128
    my $self = shift @_;
86
    my ( $branchcode ) = @_;
129
    my $week_days_holidays = $self->{'week_days_holidays'};
130
    return $week_days_holidays;
131
}
132
133
=head2 get_day_month_holidays
134
135
   $day_month_holidays = $calendar->get_day_month_holidays();
136
137
Returns a hash reference to day month holidays.
138
139
=cut
140
87
141
sub get_day_month_holidays {
88
    return C4::Context->dbh->selectall_arrayref( q{
142
    my $self = shift @_;
89
        SELECT
143
    my $day_month_holidays = $self->{'day_month_holidays'};
90
            weekday, 0 as open_hour, 0 as open_minute, 0 as close_hour,
144
    return $day_month_holidays;
91
            0 as close_minute, title, description, 1 as closed
92
        FROM repeatable_holidays
93
        WHERE branchcode = ? AND weekday IS NOT NULL
94
    }, { Slice => {} }, $branchcode );
145
}
95
}
146
96
147
=head2 get_exception_holidays
97
=head2 GetYearlyEvents
148
98
149
    $exception_holidays = $calendar->exception_holidays();
99
  \@events = GetYearlyEvents( $branchcode )
150
100
151
Returns a hash reference to exception holidays. This kind of days are those
101
Get the yearly-repeating events for the given library.
152
which stands for a holiday, but you wanted to make an exception for this particular
153
date.
154
102
155
=cut
103
=cut
156
104
157
sub get_exception_holidays {
105
sub GetYearlyEvents {
158
    my $self = shift @_;
106
    my ( $branchcode ) = @_;
159
    my $exception_holidays = $self->{'exception_holidays'};
160
    return $exception_holidays;
161
}
162
163
=head2 get_single_holidays
164
165
    $single_holidays = $calendar->get_single_holidays();
166
107
167
Returns a hash reference to single holidays. This kind of holidays are those which
108
    return C4::Context->dbh->selectall_arrayref( q{
168
happend just one time.
109
        SELECT
169
110
            month, day, 0 as open_hour, 0 as open_minute, 0 as close_hour,
170
=cut
111
            0 as close_minute, title, description, 1 as closed
171
112
        FROM repeatable_holidays
172
sub get_single_holidays {
113
        WHERE branchcode = ? AND weekday IS NULL
173
    my $self = shift @_;
114
    }, { Slice => {} }, $branchcode );
174
    my $single_holidays = $self->{'single_holidays'};
175
    return $single_holidays;
176
}
115
}
177
116
178
=head2 insert_week_day_holiday
117
=head2 ModSingleEvent
179
180
    insert_week_day_holiday(weekday => $weekday,
181
                            title => $title,
182
                            description => $description);
183
184
Inserts a new week day for $self->{branchcode}.
185
118
186
C<$day> Is the week day to make holiday.
119
  ModSingleEvent( $branchcode, $date, \%info )
187
120
188
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
121
Creates or updates an event for a single date. $date should be an ISO-formatted
189
122
date string, and \%info should contain the following keys: open_hour,
190
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
123
open_minute, close_hour, close_minute, title and description.
191
124
192
=cut
125
=cut
193
126
194
sub insert_week_day_holiday {
127
sub ModSingleEvent {
195
    my $self = shift @_;
128
    my ( $branchcode, $date, $info ) = @_;
196
    my %options = @_;
197
198
    my $weekday = $options{weekday};
199
    croak "Invalid weekday $weekday" unless $weekday =~ m/^[0-6]$/;
200
201
    my $dbh = C4::Context->dbh();
202
    my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ( '',?,?,NULL,NULL,?,? )"); 
203
	$insertHoliday->execute( $self->{branchcode}, $weekday, $options{title}, $options{description});
204
    $self->{'week_days_holidays'}->{$weekday}{title} = $options{title};
205
    $self->{'week_days_holidays'}->{$weekday}{description} = $options{description};
206
    return $self;
207
}
208
209
=head2 insert_day_month_holiday
210
211
    insert_day_month_holiday(day => $day,
212
                             month => $month,
213
                             title => $title,
214
                             description => $description);
215
216
Inserts a new day month holiday for $self->{branchcode}.
217
129
218
C<$day> Is the day month to make the date to insert.
130
    my ( $year, $month, $day ) = ( $date =~ /(\d+)-(\d+)-(\d+)/ );
131
    return unless ( $year && $month && $day );
219
132
220
C<$month> Is month to make the date to insert.
133
    my $dbh = C4::Context->dbh;
134
    my @args = ( ( map { $info->{$_} } qw(title description) ), $info->{close_hour} != 0, $branchcode, $year, $month, $day );
221
135
222
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
136
    # The code below relies on $dbh->do returning 0 when the update affects no rows
137
    my $affected = $dbh->do( q{
138
        UPDATE special_holidays
139
        SET
140
            title = ?, description = ?, isexception = ?
141
        WHERE branchcode = ? AND year = ? AND month = ? AND day = ?
142
    }, {}, @args );
223
143
224
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
144
    $dbh->do( q{
225
145
        INSERT
226
=cut
146
        INTO special_holidays(title, description, isexception, branchcode, year, month, day)
227
147
        VALUES (?, ?, ?, ?, ?, ?, ?)
228
sub insert_day_month_holiday {
148
    }, {}, @args ) unless ( $affected > 0 );
229
    my $self = shift @_;
230
    my %options = @_;
231
232
    my $dbh = C4::Context->dbh();
233
    my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ('', ?, NULL, ?, ?, ?,? )");
234
	$insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{title}, $options{description});
235
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{title} = $options{title};
236
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{description} = $options{description};
237
    return $self;
238
}
149
}
239
150
240
=head2 insert_single_holiday
151
=head2 ModRepeatingEvent
241
242
    insert_single_holiday(day => $day,
243
                          month => $month,
244
                          year => $year,
245
                          title => $title,
246
                          description => $description);
247
248
Inserts a new single holiday for $self->{branchcode}.
249
250
C<$day> Is the day month to make the date to insert.
251
252
C<$month> Is month to make the date to insert.
253
254
C<$year> Is year to make the date to insert.
255
152
256
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
153
  ModRepeatingEvent( $branchcode, $weekday, $month, $day, \%info )
257
154
258
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
155
Creates or updates a weekly- or yearly-repeating event. Either $weekday,
156
or $month and $day should be set, for a weekly or yearly event, respectively.
259
157
260
=cut
158
=cut
261
159
262
sub insert_single_holiday {
160
sub _get_compare {
263
    my $self = shift @_;
161
    my ( $colname, $value ) = @_;
264
    my %options = @_;
265
    
266
    @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o )
267
      if $options{date} && !$options{day};
268
269
	my $dbh = C4::Context->dbh();
270
    my $isexception = 0;
271
    my $insertHoliday = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)");
272
	$insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $options{description});
273
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
274
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
275
    return $self;
276
}
277
278
=head2 insert_exception_holiday
279
280
    insert_exception_holiday(day => $day,
281
                             month => $month,
282
                             year => $year,
283
                             title => $title,
284
                             description => $description);
285
286
Inserts a new exception holiday for $self->{branchcode}.
287
288
C<$day> Is the day month to make the date to insert.
289
290
C<$month> Is month to make the date to insert.
291
292
C<$year> Is year to make the date to insert.
293
294
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
295
296
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
297
298
=cut
299
300
sub insert_exception_holiday {
301
    my $self = shift @_;
302
    my %options = @_;
303
304
    @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o )
305
      if $options{date} && !$options{day};
306
307
    my $dbh = C4::Context->dbh();
308
    my $isexception = 1;
309
    my $insertException = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)");
310
	$insertException->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $options{description});
311
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
312
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
313
    return $self;
314
}
315
316
=head2 ModWeekdayholiday
317
318
    ModWeekdayholiday(weekday =>$weekday,
319
                      title => $title,
320
                      description => $description)
321
322
Modifies the title and description of a weekday for $self->{branchcode}.
323
324
C<$weekday> Is the title to update for the holiday.
325
162
326
C<$description> Is the description to update for the holiday.
163
    return ' AND ' . $colname . ' ' . ( defined( $value ) ? '=' : 'IS' ) . ' ?';
327
328
=cut
329
330
sub ModWeekdayholiday {
331
    my $self = shift @_;
332
    my %options = @_;
333
334
    my $dbh = C4::Context->dbh();
335
    my $updateHoliday = $dbh->prepare("UPDATE repeatable_holidays SET title = ?, description = ? WHERE branchcode = ? AND weekday = ?");
336
    $updateHoliday->execute( $options{title},$options{description},$self->{branchcode},$options{weekday}); 
337
    $self->{'week_days_holidays'}->{$options{weekday}}{title} = $options{title};
338
    $self->{'week_days_holidays'}->{$options{weekday}}{description} = $options{description};
339
    return $self;
340
}
164
}
341
165
342
=head2 ModDaymonthholiday
166
sub ModRepeatingEvent {
343
167
    my ( $branchcode, $weekday, $month, $day, $info ) = @_;
344
    ModDaymonthholiday(day => $day,
345
                       month => $month,
346
                       title => $title,
347
                       description => $description);
348
349
Modifies the title and description for a day/month holiday for $self->{branchcode}.
350
351
C<$day> The day of the month for the update.
352
353
C<$month> The month to be used for the update.
354
355
C<$title> The title to be updated for the holiday.
356
357
C<$description> The description to be update for the holiday.
358
359
=cut
360
361
sub ModDaymonthholiday {
362
    my $self = shift @_;
363
    my %options = @_;
364
365
    my $dbh = C4::Context->dbh();
366
    my $updateHoliday = $dbh->prepare("UPDATE repeatable_holidays SET title = ?, description = ? WHERE month = ? AND day = ? AND branchcode = ?");
367
       $updateHoliday->execute( $options{title},$options{description},$options{month},$options{day},$self->{branchcode}); 
368
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{title} = $options{title};
369
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{description} = $options{description};
370
    return $self;
371
}
372
373
=head2 ModSingleholiday
374
375
    ModSingleholiday(day => $day,
376
                     month => $month,
377
                     year => $year,
378
                     title => $title,
379
                     description => $description);
380
381
Modifies the title and description for a single holiday for $self->{branchcode}.
382
383
C<$day> Is the day of the month to make the update.
384
168
385
C<$month> Is the month to make the update.
169
    my $dbh = C4::Context->dbh;
170
    my $open = ( $info->{close_hour} != 0 );
386
171
387
C<$year> Is the year to make the update.
172
    if ($open) {
388
173
        $dbh->do( q{
389
C<$title> Is the title to update for the holiday formed by $year/$month/$day.
174
            DELETE FROM repeatable_holidays
390
175
            WHERE branchcode = ?
391
C<$description> Is the description to update for the holiday formed by $year/$month/$day.
176
        } . _get_compare( 'weekday', $weekday ) . _get_compare( 'month', $month ) . _get_compare( 'day', $day ), {}, $branchcode, $weekday, $month, $day );
392
393
=cut
394
395
sub ModSingleholiday {
396
    my $self = shift @_;
397
    my %options = @_;
398
399
    my $dbh = C4::Context->dbh();
400
    my $isexception = 0;
401
    my $updateHoliday = $dbh->prepare("UPDATE special_holidays SET title = ?, description = ? WHERE day = ? AND month = ? AND year = ? AND branchcode = ? AND isexception = ?");
402
      $updateHoliday->execute($options{title},$options{description},$options{day},$options{month},$options{year},$self->{branchcode},$isexception);    
403
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
404
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
405
    return $self;
406
}
407
408
=head2 ModExceptionholiday
409
410
    ModExceptionholiday(day => $day,
411
                        month => $month,
412
                        year => $year,
413
                        title => $title,
414
                        description => $description);
415
416
Modifies the title and description for an exception holiday for $self->{branchcode}.
417
418
C<$day> Is the day of the month for the holiday.
419
420
C<$month> Is the month for the holiday.
421
422
C<$year> Is the year for the holiday.
423
424
C<$title> Is the title to be modified for the holiday formed by $year/$month/$day.
425
426
C<$description> Is the description to be modified for the holiday formed by $year/$month/$day.
427
428
=cut
429
430
sub ModExceptionholiday {
431
    my $self = shift @_;
432
    my %options = @_;
433
434
    my $dbh = C4::Context->dbh();
435
    my $isexception = 1;
436
    my $updateHoliday = $dbh->prepare("UPDATE special_holidays SET title = ?, description = ? WHERE day = ? AND month = ? AND year = ? AND branchcode = ? AND isexception = ?");
437
    $updateHoliday->execute($options{title},$options{description},$options{day},$options{month},$options{year},$self->{branchcode},$isexception);    
438
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
439
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
440
    return $self;
441
}
442
443
=head2 delete_holiday
444
445
    delete_holiday(weekday => $weekday
446
                   day => $day,
447
                   month => $month,
448
                   year => $year);
449
450
Delete a holiday for $self->{branchcode}.
451
452
C<$weekday> Is the week day to delete.
453
454
C<$day> Is the day month to make the date to delete.
455
456
C<$month> Is month to make the date to delete.
457
458
C<$year> Is year to make the date to delete.
459
460
=cut
461
462
sub delete_holiday {
463
    my $self = shift @_;
464
    my %options = @_;
465
466
    # Verify what kind of holiday that day is. For example, if it is
467
    # a repeatable holiday, this should check if there are some exception
468
	# for that holiday rule. Otherwise, if it is a regular holiday, it´s 
469
    # ok just deleting it.
470
471
    my $dbh = C4::Context->dbh();
472
    my $isSingleHoliday = $dbh->prepare("SELECT id FROM special_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?) AND (year = ?)");
473
    $isSingleHoliday->execute($self->{branchcode}, $options{day}, $options{month}, $options{year});
474
    if ($isSingleHoliday->rows) {
475
        my $id = $isSingleHoliday->fetchrow;
476
        $isSingleHoliday->finish; # Close the last query
477
478
        my $deleteHoliday = $dbh->prepare("DELETE FROM special_holidays WHERE id = ?");
479
        $deleteHoliday->execute($id);
480
        delete($self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"});
481
    } else {
177
    } else {
482
        $isSingleHoliday->finish; # Close the last query
178
        my @args = ( ( map { $info->{$_} } qw(title description) ), $branchcode, $weekday, $month, $day );
483
179
484
        my $isWeekdayHoliday = $dbh->prepare("SELECT id FROM repeatable_holidays WHERE branchcode = ? AND weekday = ?");
180
        # The code below relies on $dbh->do returning 0 when the update affects no rows
485
        $isWeekdayHoliday->execute($self->{branchcode}, $options{weekday});
181
        my $affected = $dbh->do( q{
486
        if ($isWeekdayHoliday->rows) {
182
            UPDATE repeatable_holidays
487
            my $id = $isWeekdayHoliday->fetchrow;
183
            SET
488
            $isWeekdayHoliday->finish; # Close the last query
184
                title = ?, description = ?
489
185
            WHERE branchcode = ?
490
            my $updateExceptions = $dbh->prepare("UPDATE special_holidays SET isexception = 0 WHERE (WEEKDAY(CONCAT(special_holidays.year,'-',special_holidays.month,'-',special_holidays.day)) = ?) AND (branchcode = ?)");
186
        } . _get_compare( 'weekday', $weekday ) . _get_compare( 'month', $month ) . _get_compare( 'day', $day ), {}, @args );
491
            $updateExceptions->execute($options{weekday}, $self->{branchcode});
187
492
            $updateExceptions->finish; # Close the last query
188
        $dbh->do( q{
493
189
            INSERT
494
            my $deleteHoliday = $dbh->prepare("DELETE FROM repeatable_holidays WHERE id = ?");
190
            INTO repeatable_holidays(title, description, branchcode, weekday, month, day)
495
            $deleteHoliday->execute($id);
191
            VALUES (?, ?, ?, ?, ?, ?)
496
            delete($self->{'week_days_holidays'}->{$options{weekday}});
192
        }, {}, @args ) unless ( $affected > 0 );
497
        } else {
498
            $isWeekdayHoliday->finish; # Close the last query
499
500
            my $isDayMonthHoliday = $dbh->prepare("SELECT id FROM repeatable_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?)");
501
            $isDayMonthHoliday->execute($self->{branchcode}, $options{day}, $options{month});
502
            if ($isDayMonthHoliday->rows) {
503
                my $id = $isDayMonthHoliday->fetchrow;
504
                $isDayMonthHoliday->finish;
505
                my $updateExceptions = $dbh->prepare("UPDATE special_holidays SET isexception = 0 WHERE (special_holidays.branchcode = ?) AND (special_holidays.day = ?) and (special_holidays.month = ?)");
506
                $updateExceptions->execute($self->{branchcode}, $options{day}, $options{month});
507
                $updateExceptions->finish; # Close the last query
508
509
                my $deleteHoliday = $dbh->prepare("DELETE FROM repeatable_holidays WHERE (id = ?)");
510
                $deleteHoliday->execute($id);
511
                delete($self->{'day_month_holidays'}->{"$options{month}/$options{day}"});
512
            }
513
        }
514
    }
193
    }
515
    return $self;
516
}
517
=head2 delete_holiday_range
518
519
    delete_holiday_range(day => $day,
520
                   month => $month,
521
                   year => $year);
522
523
Delete a holiday range of dates for $self->{branchcode}.
524
525
C<$day> Is the day month to make the date to delete.
526
527
C<$month> Is month to make the date to delete.
528
529
C<$year> Is year to make the date to delete.
530
531
=cut
532
533
sub delete_holiday_range {
534
    my $self = shift;
535
    my %options = @_;
536
537
    my $dbh = C4::Context->dbh();
538
    my $sth = $dbh->prepare("DELETE FROM special_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?) AND (year = ?)");
539
    $sth->execute($self->{branchcode}, $options{day}, $options{month}, $options{year});
540
}
194
}
541
195
542
=head2 delete_holiday_range_repeatable
196
=head2 DelSingleEvent
543
197
544
    delete_holiday_range_repeatable(day => $day,
198
  DelSingleEvent( $branchcode, $date, \%info )
545
                   month => $month);
546
199
547
Delete a holiday for $self->{branchcode}.
200
Deletes an event for a single date. $date should be an ISO-formatted date string.
548
549
C<$day> Is the day month to make the date to delete.
550
551
C<$month> Is month to make the date to delete.
552
201
553
=cut
202
=cut
554
203
555
sub delete_holiday_range_repeatable {
204
sub DelSingleEvent {
556
    my $self = shift;
205
    my ( $branchcode, $date ) = @_;
557
    my %options = @_;
558
559
    my $dbh = C4::Context->dbh();
560
    my $sth = $dbh->prepare("DELETE FROM repeatable_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?)");
561
    $sth->execute($self->{branchcode}, $options{day}, $options{month});
562
}
563
564
=head2 delete_exception_holiday_range
565
206
566
    delete_exception_holiday_range(weekday => $weekday
207
    my ( $year, $month, $day ) = ( $date =~ /(\d+)-(\d+)-(\d+)/ );
567
                   day => $day,
208
    return unless ( $year && $month && $day );
568
                   month => $month,
569
                   year => $year);
570
209
571
Delete a holiday for $self->{branchcode}.
210
    C4::Context->dbh->do( q{
572
211
        DELETE FROM special_holidays
573
C<$day> Is the day month to make the date to delete.
212
        WHERE branchcode = ? AND year = ? AND month = ? AND day = ?
574
213
    }, {}, $branchcode, $year, $month, $day );
575
C<$month> Is month to make the date to delete.
576
577
C<$year> Is year to make the date to delete.
578
579
=cut
580
581
sub delete_exception_holiday_range {
582
    my $self = shift;
583
    my %options = @_;
584
585
    my $dbh = C4::Context->dbh();
586
    my $sth = $dbh->prepare("DELETE FROM special_holidays WHERE (branchcode = ?) AND (isexception = 1) AND (day = ?) AND (month = ?) AND (year = ?)");
587
    $sth->execute($self->{branchcode}, $options{day}, $options{month}, $options{year});
588
}
214
}
589
215
590
=head2 isHoliday
216
=head2 DelRepeatingEvent
591
592
    $isHoliday = isHoliday($day, $month $year);
593
594
C<$day> Is the day to check whether if is a holiday or not.
595
596
C<$month> Is the month to check whether if is a holiday or not.
597
598
C<$year> Is the year to check whether if is a holiday or not.
599
600
=cut
601
602
sub isHoliday {
603
    my ($self, $day, $month, $year) = @_;
604
	# FIXME - date strings are stored in non-padded metric format. should change to iso.
605
	# FIXME - should change arguments to accept C4::Dates object
606
	$month=$month+0;
607
	$year=$year+0;
608
	$day=$day+0;
609
    my $weekday = &Date::Calc::Day_of_Week($year, $month, $day) % 7; 
610
    my $weekDays   = $self->get_week_days_holidays();
611
    my $dayMonths  = $self->get_day_month_holidays();
612
    my $exceptions = $self->get_exception_holidays();
613
    my $singles    = $self->get_single_holidays();
614
    if (defined($exceptions->{"$year/$month/$day"})) {
615
        return 0;
616
    } else {
617
        if ((exists($weekDays->{$weekday})) ||
618
            (exists($dayMonths->{"$month/$day"})) ||
619
            (exists($singles->{"$year/$month/$day"}))) {
620
		 	return 1;
621
        } else {
622
            return 0;
623
        }
624
    }
625
217
626
}
218
  DelRepeatingEvent( $branchcode, $weekday, $month, $day )
627
219
628
=head2 copy_to_branch
220
Deletes a weekly- or yearly-repeating event. Either $weekday, or $month and
629
221
$day should be set, for a weekly or yearly event, respectively.
630
    $calendar->copy_to_branch($target_branch)
631
222
632
=cut
223
=cut
633
224
634
sub copy_to_branch {
225
sub DelRepeatingEvent {
635
    my ($self, $target_branch) = @_;
226
    my ( $branchcode, $weekday, $month, $day ) = @_;
636
637
    croak "No target_branch" unless $target_branch;
638
227
639
    my $target_calendar = C4::Calendar->new(branchcode => $target_branch);
228
    C4::Context->dbh->do( q{
640
229
        DELETE FROM repeatable_holidays
641
    my ($y, $m, $d) = Today();
230
        WHERE branchcode = ?
642
    my $today = sprintf ISO_DATE_FORMAT, $y,$m,$d;
231
    } . _get_compare( 'weekday', $weekday ) . _get_compare( 'month', $month ) . _get_compare( 'day', $day ), {}, $branchcode, $weekday, $month, $day );
643
644
    my $wdh = $self->get_week_days_holidays;
645
    $target_calendar->insert_week_day_holiday( weekday => $_, %{ $wdh->{$_} } )
646
      foreach keys %$wdh;
647
    $target_calendar->insert_day_month_holiday(%$_)
648
      foreach values %{ $self->get_day_month_holidays };
649
    $target_calendar->insert_exception_holiday(%$_)
650
      foreach grep { $_->{date} gt $today } values %{ $self->get_exception_holidays };
651
    $target_calendar->insert_single_holiday(%$_)
652
      foreach grep { $_->{date} gt $today } values %{ $self->get_single_holidays };
653
654
    return 1;
655
}
232
}
656
233
657
=head2 addDate
234
=head2 CopyAllEvents
658
235
659
    my ($day, $month, $year) = $calendar->addDate($date, $offset)
236
  CopyAllEvents( $from_branchcode, $to_branchcode )
660
237
661
C<$date> is a C4::Dates object representing the starting date of the interval.
238
Copies all events from one branch to another.
662
663
C<$offset> Is the number of days that this function has to count from $date.
664
239
665
=cut
240
=cut
666
241
667
sub addDate {
242
sub CopyAllEvents {
668
    my ($self, $startdate, $offset) = @_;
243
    my ( $from_branchcode, $to_branchcode ) = @_;
669
    my ($year,$month,$day) = split("-",$startdate->output('iso'));
244
670
	my $daystep = 1;
245
    C4::Context->dbh->do( q{
671
	if ($offset < 0) { # In case $offset is negative
246
        INSERT IGNORE INTO special_holidays(branchcode, year, month, day, isexception, title, description)
672
       # $offset = $offset*(-1);
247
        SELECT ?, year, month, day, isexception, title, description
673
		$daystep = -1;
248
        FROM special_holidays
674
    }
249
        WHERE branchcode = ?
675
	my $daysMode = C4::Context->preference('useDaysMode');
250
    }, {}, $to_branchcode, $from_branchcode );
676
    if ($daysMode eq 'Datedue') {
251
677
        ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset );
252
    C4::Context->dbh->do( q{
678
	 	while ($self->isHoliday($day, $month, $year)) {
253
        INSERT IGNORE INTO repeatable_holidays(branchcode, weekday, month, day, title, description)
679
            ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep);
254
        SELECT ?, weekday, month, day, title, description
680
        }
255
        FROM repeatable_holidays
681
    } elsif($daysMode eq 'Calendar') {
256
        WHERE branchcode = ?
682
        while ($offset !=  0) {
257
    }, {}, $to_branchcode, $from_branchcode );
683
            ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep);
684
            if (!($self->isHoliday($day, $month, $year))) {
685
                $offset = $offset - $daystep;
686
			}
687
        }
688
	} else { ## ($daysMode eq 'Days') 
689
        ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset );
690
    }
691
    return(C4::Dates->new( sprintf(ISO_DATE_FORMAT,$year,$month,$day),'iso'));
692
}
258
}
693
259
694
=head2 daysBetween
695
696
    my $daysBetween = $calendar->daysBetween($startdate, $enddate)
697
698
C<$startdate> and C<$enddate> are C4::Dates objects that define the interval.
699
700
Returns the number of non-holiday days in the interval.
701
useDaysMode syspref has no effect here.
702
=cut
703
704
sub daysBetween {
705
    my $self      = shift or return;
706
    my $startdate = shift or return;
707
    my $enddate   = shift or return;
708
    my ($yearFrom,$monthFrom,$dayFrom) = split("-",$startdate->output('iso'));
709
    my ($yearTo,  $monthTo,  $dayTo  ) = split("-",  $enddate->output('iso'));
710
    if (Date_to_Days($yearFrom,$monthFrom,$dayFrom) > Date_to_Days($yearTo,$monthTo,$dayTo)) {
711
        return 0;
712
        # we don't go backwards  ( FIXME - handle this error better )
713
    }
714
    my $count = 0;
715
    while (1) {
716
        ($yearFrom != $yearTo or $monthFrom != $monthTo or $dayFrom != $dayTo) or last; # if they all match, it's the last day
717
        unless ($self->isHoliday($dayFrom, $monthFrom, $yearFrom)) {
718
            $count++;
719
        }
720
        ($yearFrom, $monthFrom, $dayFrom) = &Date::Calc::Add_Delta_Days($yearFrom, $monthFrom, $dayFrom, 1);
721
    }
722
    return($count);
723
}
724
260
725
1;
261
1;
726
262
Lines 729-733 __END__ Link Here
729
=head1 AUTHOR
265
=head1 AUTHOR
730
266
731
Koha Physics Library UNLP <matias_veleda@hotmail.com>
267
Koha Physics Library UNLP <matias_veleda@hotmail.com>
268
Jesse Weaver <jweaver@bywatersolutions.com>
732
269
733
=cut
270
=cut
(-)a/C4/Circulation.pm (-87 lines)
Lines 3122-3214 sub CalcDateDue { Link Here
3122
    return $datedue;
3122
    return $datedue;
3123
}
3123
}
3124
3124
3125
3126
=head2 CheckRepeatableHolidays
3127
3128
  $countrepeatable = CheckRepeatableHoliday($itemnumber,$week_day,$branchcode);
3129
3130
This function checks if the date due is a repeatable holiday
3131
3132
C<$date_due>   = returndate calculate with no day check
3133
C<$itemnumber>  = itemnumber
3134
C<$branchcode>  = localisation of issue 
3135
3136
=cut
3137
3138
sub CheckRepeatableHolidays{
3139
my($itemnumber,$week_day,$branchcode)=@_;
3140
my $dbh = C4::Context->dbh;
3141
my $query = qq|SELECT count(*)  
3142
	FROM repeatable_holidays 
3143
	WHERE branchcode=?
3144
	AND weekday=?|;
3145
my $sth = $dbh->prepare($query);
3146
$sth->execute($branchcode,$week_day);
3147
my $result=$sth->fetchrow;
3148
return $result;
3149
}
3150
3151
3152
=head2 CheckSpecialHolidays
3153
3154
  $countspecial = CheckSpecialHolidays($years,$month,$day,$itemnumber,$branchcode);
3155
3156
This function check if the date is a special holiday
3157
3158
C<$years>   = the years of datedue
3159
C<$month>   = the month of datedue
3160
C<$day>     = the day of datedue
3161
C<$itemnumber>  = itemnumber
3162
C<$branchcode>  = localisation of issue 
3163
3164
=cut
3165
3166
sub CheckSpecialHolidays{
3167
my ($years,$month,$day,$itemnumber,$branchcode) = @_;
3168
my $dbh = C4::Context->dbh;
3169
my $query=qq|SELECT count(*) 
3170
	     FROM `special_holidays`
3171
	     WHERE year=?
3172
	     AND month=?
3173
	     AND day=?
3174
             AND branchcode=?
3175
	    |;
3176
my $sth = $dbh->prepare($query);
3177
$sth->execute($years,$month,$day,$branchcode);
3178
my $countspecial=$sth->fetchrow ;
3179
return $countspecial;
3180
}
3181
3182
=head2 CheckRepeatableSpecialHolidays
3183
3184
  $countspecial = CheckRepeatableSpecialHolidays($month,$day,$itemnumber,$branchcode);
3185
3186
This function check if the date is a repeatble special holidays
3187
3188
C<$month>   = the month of datedue
3189
C<$day>     = the day of datedue
3190
C<$itemnumber>  = itemnumber
3191
C<$branchcode>  = localisation of issue 
3192
3193
=cut
3194
3195
sub CheckRepeatableSpecialHolidays{
3196
my ($month,$day,$itemnumber,$branchcode) = @_;
3197
my $dbh = C4::Context->dbh;
3198
my $query=qq|SELECT count(*) 
3199
	     FROM `repeatable_holidays`
3200
	     WHERE month=?
3201
	     AND day=?
3202
             AND branchcode=?
3203
	    |;
3204
my $sth = $dbh->prepare($query);
3205
$sth->execute($month,$day,$branchcode);
3206
my $countspecial=$sth->fetchrow ;
3207
return $countspecial;
3208
}
3209
3210
3211
3212
sub CheckValidBarcode{
3125
sub CheckValidBarcode{
3213
my ($barcode) = @_;
3126
my ($barcode) = @_;
3214
my $dbh = C4::Context->dbh;
3127
my $dbh = C4::Context->dbh;
(-)a/C4/Installer/PerlDependencies.pm (+5 lines)
Lines 699-704 our $PERL_DEPS = { Link Here
699
        'required' => '0',
699
        'required' => '0',
700
        'min_ver'  => '0.73',
700
        'min_ver'  => '0.73',
701
    },
701
    },
702
    'Template::Plugin::JavaScript' => {
703
        'usage'    => 'Core',
704
        'required' => '1',
705
        'min_ver'  => '0.02',
706
    },
702
};
707
};
703
708
704
1;
709
1;
(-)a/C4/Overdues.pm (-124 lines)
Lines 306-435 sub _get_chargeable_units { Link Here
306
}
306
}
307
307
308
308
309
=head2 GetSpecialHolidays
310
311
    &GetSpecialHolidays($date_dues,$itemnumber);
312
313
return number of special days  between date of the day and date due
314
315
C<$date_dues> is the envisaged date of book return.
316
317
C<$itemnumber> is the book's item number.
318
319
=cut
320
321
sub GetSpecialHolidays {
322
    my ( $date_dues, $itemnumber ) = @_;
323
324
    # calcul the today date
325
    my $today = join "-", &Today();
326
327
    # return the holdingbranch
328
    my $iteminfo = GetIssuesIteminfo($itemnumber);
329
330
    # use sql request to find all date between date_due and today
331
    my $dbh = C4::Context->dbh;
332
    my $query =
333
      qq|SELECT DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') as date
334
FROM `special_holidays`
335
WHERE DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') >= ?
336
AND   DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') <= ?
337
AND branchcode=?
338
|;
339
    my @result = GetWdayFromItemnumber($itemnumber);
340
    my @result_date;
341
    my $wday;
342
    my $dateinsec;
343
    my $sth = $dbh->prepare($query);
344
    $sth->execute( $date_dues, $today, $iteminfo->{'branchcode'} )
345
      ;    # FIXME: just use NOW() in SQL instead of passing in $today
346
347
    while ( my $special_date = $sth->fetchrow_hashref ) {
348
        push( @result_date, $special_date );
349
    }
350
351
    my $specialdaycount = scalar(@result_date);
352
353
    for ( my $i = 0 ; $i < scalar(@result_date) ; $i++ ) {
354
        $dateinsec = UnixDate( $result_date[$i]->{'date'}, "%o" );
355
        ( undef, undef, undef, undef, undef, undef, $wday, undef, undef ) =
356
          localtime($dateinsec);
357
        for ( my $j = 0 ; $j < scalar(@result) ; $j++ ) {
358
            if ( $wday == ( $result[$j]->{'weekday'} ) ) {
359
                $specialdaycount--;
360
            }
361
        }
362
    }
363
364
    return $specialdaycount;
365
}
366
367
=head2 GetRepeatableHolidays
368
369
    &GetRepeatableHolidays($date_dues, $itemnumber, $difference,);
370
371
return number of day closed between date of the day and date due
372
373
C<$date_dues> is the envisaged date of book return.
374
375
C<$itemnumber> is item number.
376
377
C<$difference> numbers of between day date of the day and date due
378
379
=cut
380
381
sub GetRepeatableHolidays {
382
    my ( $date_dues, $itemnumber, $difference ) = @_;
383
    my $dateinsec = UnixDate( $date_dues, "%o" );
384
    my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
385
      localtime($dateinsec);
386
    my @result = GetWdayFromItemnumber($itemnumber);
387
    my @dayclosedcount;
388
    my $j;
389
390
    for ( my $i = 0 ; $i < scalar(@result) ; $i++ ) {
391
        my $k = $wday;
392
393
        for ( $j = 0 ; $j < $difference ; $j++ ) {
394
            if ( $result[$i]->{'weekday'} == $k ) {
395
                push( @dayclosedcount, $k );
396
            }
397
            $k++;
398
            ( $k = 0 ) if ( $k eq 7 );
399
        }
400
    }
401
    return scalar(@dayclosedcount);
402
}
403
404
405
=head2 GetWayFromItemnumber
406
407
    &Getwdayfromitemnumber($itemnumber);
408
409
return the different week day from repeatable_holidays table
410
411
C<$itemnumber> is  item number.
412
413
=cut
414
415
sub GetWdayFromItemnumber {
416
    my ($itemnumber) = @_;
417
    my $iteminfo = GetIssuesIteminfo($itemnumber);
418
    my @result;
419
    my $query = qq|SELECT weekday
420
    FROM repeatable_holidays
421
    WHERE branchcode=?
422
|;
423
    my $sth = C4::Context->dbh->prepare($query);
424
425
    $sth->execute( $iteminfo->{'branchcode'} );
426
    while ( my $weekday = $sth->fetchrow_hashref ) {
427
        push( @result, $weekday );
428
    }
429
    return @result;
430
}
431
432
433
=head2 GetIssuesIteminfo
309
=head2 GetIssuesIteminfo
434
310
435
    &GetIssuesIteminfo($itemnumber);
311
    &GetIssuesIteminfo($itemnumber);
(-)a/Koha/Calendar.pm (-18 lines)
Lines 339-356 sub clear_weekly_closed_days { Link Here
339
    return;
339
    return;
340
}
340
}
341
341
342
sub add_holiday {
343
    my $self = shift;
344
    my $new_dt = shift;
345
    my @dt = $self->single_holidays->as_list;
346
    push @dt, $new_dt;
347
    $self->{single_holidays} =
348
      DateTime::Set->from_datetimes( dates => \@dt );
349
    $single_holidays = $self->{single_holidays};
350
351
    return;
352
}
353
354
1;
342
1;
355
__END__
343
__END__
356
344
Lines 468-479 In test mode changes the testing set of closed days to a new set with Link Here
468
no closed days. TODO passing an array of closed days to this would
456
no closed days. TODO passing an array of closed days to this would
469
allow testing of more configurations
457
allow testing of more configurations
470
458
471
=head2 add_holiday
472
473
Passed a datetime object this will add it to the calendar's list of
474
closed days. This is for testing so that we can alter the Calenfar object's
475
list of specified dates
476
477
=head1 DIAGNOSTICS
459
=head1 DIAGNOSTICS
478
460
479
Will croak if not passed a branchcode in new
461
Will croak if not passed a branchcode in new
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc (-1 / +1 lines)
Lines 87-93 Link Here
87
<h5>Additional tools</h5>
87
<h5>Additional tools</h5>
88
<ul>
88
<ul>
89
    [% IF ( CAN_user_tools_edit_calendar ) %]
89
    [% IF ( CAN_user_tools_edit_calendar ) %]
90
	<li><a href="/cgi-bin/koha/tools/holidays.pl">Calendar</a></li>
90
	<li><a href="/cgi-bin/koha/tools/calendar.pl">Calendar</a></li>
91
    [% END %]
91
    [% END %]
92
    [% IF ( CAN_user_tools_manage_csv_profiles ) %]
92
    [% IF ( CAN_user_tools_manage_csv_profiles ) %]
93
	<li><a href="/cgi-bin/koha/tools/csv-profiles.pl">CSV profiles</a></li>
93
	<li><a href="/cgi-bin/koha/tools/csv-profiles.pl">CSV profiles</a></li>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt (+594 lines)
Line 0 Link Here
1
[% USE 'JavaScript' %]
2
[% USE 'KohaDates' %]
3
[% INCLUDE 'doc-head-open.inc' %]
4
<title>Koha &rsaquo; Tools &rsaquo; [% branchname %] Calendar</title>
5
[% INCLUDE 'doc-head-close.inc' %]
6
[% INCLUDE 'calendar.inc' %]
7
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
8
[% INCLUDE 'datatables.inc' %]
9
<script language="JavaScript" type="text/javascript">
10
//<![CDATA[
11
    [% IF (dateformat == 'metric') %]dt_add_type_uk_date();[% END %]
12
    var weekdays = new Array(_("Sundays"),_("Mondays"),_("Tuesdays"),_("Wednesdays"),_("Thursdays"),_("Fridays"),_("Saturdays"));
13
14
    var single_events = {
15
        [% FOREACH event IN single_events %]
16
        '[% event.event_date %]': {
17
            title: '[% event.title | js %]',
18
            description: '[% event.description | js %]',
19
            closed: [% event.closed %],
20
            eventType: 'single',
21
            open_hour: '[% event.open_hour %]',
22
            open_minute: '[% event.open_minute %]',
23
            close_hour: '[% event.close_hour %]',
24
            close_minute: '[% event.close_minute %]'
25
        },
26
        [% END %]
27
    };
28
29
    var weekly_events = {
30
        [% FOREACH event IN weekly_events %]
31
        [% event.weekday %]: {
32
            title: '[% event.title | js %]',
33
            description: '[% event.description | js %]',
34
            closed: [% event.closed %],
35
            eventType: 'weekly',
36
            weekday: [% event.weekday %],
37
            open_hour: '[% event.open_hour %]',
38
            open_minute: '[% event.open_minute %]',
39
            close_hour: '[% event.close_hour %]',
40
            close_minute: '[% event.close_minute %]'
41
        },
42
        [% END %]
43
    };
44
45
    var yearly_events = {
46
        [% FOREACH event IN yearly_events %]
47
        '[% event.month %]-[% event.day %]': {
48
            title: '[% event.title | js %]',
49
            description: '[% event.description | js %]',
50
            closed: [% event.closed %],
51
            eventType: 'yearly',
52
            month: [% event.month %],
53
            day: [% event.day %],
54
            open_hour: '[% event.open_hour %]',
55
            open_minute: '[% event.open_minute %]',
56
            close_hour: '[% event.close_hour %]',
57
            close_minute: '[% event.close_minute %]'
58
        },
59
        [% END %]
60
    };
61
62
    function eventOperation(formObject, opType) {
63
        var op = document.getElementsByName('op');
64
        op[0].value = opType;
65
        formObject.submit();
66
    }
67
68
    function zeroPad(value) {
69
        return value >= 10 ? value : ('0' + value);
70
    }
71
72
    // This function shows the "Show Event" panel //
73
    function showEvent(dayName, day, month, year, weekDay, event) {
74
        $("#newEvent").slideUp("fast");
75
        $("#showEvent").slideDown("fast");
76
        $('#showDaynameOutput').html(dayName);
77
        $('#showDayname').val(dayName);
78
        $('#showBranchNameOutput').html($("#branch :selected").text());
79
        $('#showBranchName').val($("#branch").val());
80
        $('#showDayOutput').html(day);
81
        $('#showDay').val(day);
82
        $('#showMonthOutput').html(month);
83
        $('#showMonth').val(month);
84
        $('#showYearOutput').html(year);
85
        $('#showYear').val(year);
86
        $('#showDescription').val(event.description);
87
        $('#showWeekday:first').val(weekDay);
88
        $('#showTitle').val(event.title);
89
        $('#showEventType').val(event.eventType);
90
91
        if (event.closed) {
92
            $('#showHoursTypeClosed')[0].checked = true;
93
        } else if (event.close_hour == 24) {
94
            $('#showHoursTypeOpen')[0].checked = true;
95
        } else {
96
            $('#showHoursTypeOpenSet')[0].checked = true;
97
            $('#showHoursTypeOpenSet').change();
98
            $('#showOpenTime').val(event.open_hour + ':' + zeroPad(event.open_minute));
99
            $('#showCloseTime').val(event.close_hour + ':' + zeroPad(event.close_minute));
100
        }
101
102
        $("#operationDelLabel").html(_("Delete this event."));
103
        if(event.eventType == 'weekly') {
104
            $("#holtype").attr("class","key repeatableweekly").html(_("Event repeating weekly"));
105
        } else if(event.eventType == 'yearly') {
106
            $("#holtype").attr("class","key repeatableyearly").html(_("Event repeating yearly"));
107
        } else {
108
            $("#holtype").attr("class","key event").html(_("Single event"));
109
        }
110
    }
111
112
    // This function shows the "Add Event" panel //
113
    function newEvent (dayName, day, month, year, weekDay) {
114
        $("#showEvent").slideUp("fast");
115
        $("#newEvent").slideDown("fast");
116
        $("#newDaynameOutput").html(dayName);
117
        $("#newDayname").val(dayName);
118
        $("#newBranchNameOutput").html($('#branch :selected').text());
119
        $("#newBranchName").val($('#branch').val());
120
        $("#newDayOutput").html(day);
121
        $("#newDay").val(day);
122
        $("#newMonthOutput").html(month);
123
        $("#newMonth").val(month);
124
        $("#newYearOutput").html(year);
125
        $("#newYear").val(year);
126
        $("#newWeekday:first").val(weekDay);
127
    }
128
129
    function hidePanel(aPanelName) {
130
        $("#"+aPanelName).slideUp("fast");
131
    }
132
133
    function changeBranch () {
134
        var branch = $("#branch option:selected").val();
135
        location.href='/cgi-bin/koha/tools/calendar.pl?branch=' + branch + '&calendardate=' + "[% calendardate %]";
136
    }
137
138
    /* This function gives css clases to each kind of day */
139
    function dateStatusHandler(date) {
140
        date = new Date(date);
141
        var day = date.getDate();
142
        var month = date.getMonth() + 1;
143
        var year = date.getFullYear();
144
        var weekDay = date.getDay();
145
        var dayMonth = month + '-' + day;
146
        var dateString = year + '-' + zeroPad(month) + '-' + zeroPad(day);
147
148
        if ( single_events[dateString] != null) {
149
            return [true, "event", "Single event: "+single_events[dateString].title];
150
        } else if ( yearly_events[dayMonth] != null ) {
151
            return [true, "repeatableyearly", "Yearly event: "+yearly_events[dayMonth].title];
152
        } else if ( weekly_events[weekDay] != null ){
153
            return [true, "repeatableweekly", "Weekly event: "+weekly_events[weekDay].title];
154
        } else {
155
            return [true, "normalday", "Normal day"];
156
        }
157
    }
158
159
    /* This function is in charge of showing the correct panel considering the kind of event */
160
    function dateChanged(calendar) {
161
        calendar = new Date(calendar);
162
        var day = calendar.getDate();
163
        var month = calendar.getMonth() + 1;
164
        var year = calendar.getFullYear();
165
        var weekDay = calendar.getDay();
166
        var dayName = weekdays[weekDay];
167
        var dayMonth = month + '-' + day;
168
        var dateString = year + '-' + zeroPad(month) + '-' + zeroPad(day);
169
        if ( single_events[dateString] != null ) {
170
            showEvent( dayName, day, month, year, weekDay, single_events[dateString] );
171
        } else if ( yearly_events[dayMonth] != null ) {
172
            showEvent( dayName, day, month, year, weekDay, yearly_events[dayMonth] );
173
        } else if ( weekly_events[weekDay] != null ) {
174
            showEvent( dayName, day, month, year, weekDay, weekly_events[weekDay] );
175
        } else {
176
            newEvent( dayName, day, month, year, weekDay );
177
        }
178
    };
179
180
    $(document).ready(function() {
181
182
        $(".hint").hide();
183
        $("#branch").change(function(){
184
            changeBranch();
185
        });
186
        $("#weekly-events,#single-events").dataTable($.extend(true, {}, dataTablesDefaults, {
187
            "sDom": 't',
188
            "bPaginate": false
189
        }));
190
        $("#yearly-events").dataTable($.extend(true, {}, dataTablesDefaults, {
191
            "sDom": 't',
192
            "aoColumns": [
193
                { "sType": "title-string" },null,null,null
194
            ],
195
            "bPaginate": false
196
        }));
197
        $("a.helptext").click(function(){
198
            $(this).parent().find(".hint").toggle(); return false;
199
        });
200
        $("#dateofrange").datepicker();
201
        $("#datecancelrange").datepicker();
202
        $("#dateofrange").each(function () { this.value = "" });
203
        $("#datecancelrange").each(function () { this.value = "" });
204
        $("#jcalendar-container").datepicker({
205
          beforeShowDay: function(thedate) {
206
            var day = thedate.getDate();
207
            var month = thedate.getMonth() + 1;
208
            var year = thedate.getFullYear();
209
            var dateString = year + '/' + month + '/' + day;
210
            return dateStatusHandler(dateString);
211
            },
212
            onSelect: function(dateText, inst) {
213
                dateChanged($(this).datepicker("getDate"));
214
            },
215
            defaultDate: new Date("[% keydate %]")
216
        });
217
        $(".hourssel input").change(function() {
218
            $(".hoursentry", this.form).toggle(this.value == 'openSet');
219
        }).each( function() { this.checked = false } );
220
    });
221
//]]>
222
</script>
223
<style type="text/css"> .key { padding : 3px; white-space:nowrap; line-height:230%; }
224
.ui-datepicker { font-size : 150%; }
225
.ui-datepicker th, .ui-datepicker .ui-datepicker-title select { font-size : 80%; }
226
.ui-datepicker td a { padding : .5em; }
227
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { font-size : 80%; }
228
.key { padding : 3px; white-space:nowrap; line-height:230%; }
229
.normalday { background-color :  #EDEDED; color :  Black; border : 1px solid #BCBCBC; }
230
.exception { background-color :  #b3d4ff; color :  Black; border : 1px solid #BCBCBC; }
231
.event {  background-color :  #ffaeae; color :  Black;  border : 1px solid #BCBCBC; }
232
.repeatableweekly {  background-color :  #FFFF99; color :  Black;  border : 1px solid #BCBCBC; }
233
.repeatableyearly {  background-color :  #FFCC66; color :  Black;  border : 1px solid #BCBCBC; }
234
td.exception a.ui-state-default { background:  #b3d4ff none; color :  Black; border : 1px solid #BCBCBC; }
235
td.event a.ui-state-default {  background:  #ffaeae none; color :  Black;  border : 1px solid #BCBCBC; }
236
td.repeatableweekly a.ui-state-default {  background:  #FFFF99 none; color :  Black;  border : 1px solid #BCBCBC; }
237
td.repeatableyearly a.ui-state-default {  background:  #FFCC66 none; color :  Black;  border : 1px solid #BCBCBC; }
238
.information { z-index : 1; background-color :  #DCD2F1; width : 300px; display : none; border : 1px solid #000000; color :  #000000; font-size :  8pt; font-weight :  bold; background-color :  #FFD700; cursor :  pointer; padding : 2px; }
239
.panel { z-index : 1; display : none; border : 3px solid #CCC; padding : 3px; margin-top: .3em;  background-color: #FEFEFE; } fieldset.brief { border : 0; margin-top: 0; }
240
#showEvent { margin : .5em 0; } h1 select { width: 20em; } div.yui-b fieldset.brief ol { font-size:100%; } div.yui-b fieldset.brief li, div.yui-b fieldset.brief li.radio  { padding:0.2em 0; } .help { margin:.3em 0;border:1px solid #EEE;padding:.3em .7em; font-size : 90%; } #single-events, #weekly-events, #yearly-events { font-size : 90%; margin-bottom : 1em;} .calendar td, .calendar th, .calendar .button, .calendar tbody .day { padding : .7em; font-size: 110%; } .calendar { width: auto; border : 0; }
241
li.hourssel {
242
    margin-top: .5em;
243
}
244
li.hourssel label {
245
    padding-left: .2em;
246
    padding-right: .5em;
247
}
248
li.hoursentry {
249
    margin-bottom: .5em;
250
}
251
li.hoursentry input {
252
    padding-left: .2em;
253
    padding-right: .5em;
254
}
255
</style>
256
</head>
257
<body id="tools_events" class="tools">
258
[% INCLUDE 'header.inc' %]
259
[% INCLUDE 'cat-search.inc' %]
260
261
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo; [% branchname %] Calendar</div>
262
263
<div id="doc3" class="yui-t1">
264
265
   <div id="bd">
266
    <div id="yui-main">
267
    <div class="yui-b">
268
    <h2>[% branchname %] Calendar</h2>
269
    <div class="yui-g">
270
    <div class="yui-u first">
271
        <label for="branch">Calendar for:</label>
272
            <select id="branch" name="branch">
273
                [% FOREACH branchloo IN branchloop %]
274
                    [% IF ( branchloo.selected ) %]
275
                        <option value="[% branchloo.value %]" selected="selected">[% branchloo.branchname %]</option>
276
                    [% ELSE %]
277
                        <option value="[% branchloo.value %]">[% branchloo.branchname %]</option>
278
                    [% END %]
279
                [% END %]
280
            </select>
281
282
    <!-- ******************************** FLAT PANELS ******************************************* -->
283
    <!-- *****           Makes all the flat panel to deal with events                     ***** -->
284
    <!-- **************************************************************************************** -->
285
286
    <!-- ********************** Panel for showing already loaded events *********************** -->
287
    <div class="panel" id="showEvent">
288
         <form action="/cgi-bin/koha/tools/calendar.pl" method="post">
289
             <input type="hidden" id="showEventType" name="eventType" value="" />
290
            <fieldset class="brief">
291
            <h3>Edit this event</h3>
292
            <span id="holtype"></span>
293
            <ol>
294
            <li>
295
                <strong>Library:</strong> <span id="showBranchNameOutput"></span>
296
                <input type="hidden" id="showBranchName" name="branchName" />
297
            </li>
298
            <li>
299
                <strong>From Date:</strong>
300
                <span id="showDaynameOutput"></span>,
301
302
                                [% IF ( dateformat == "us" ) %]<span id="showMonthOutput"></span>/<span id="showDayOutput"></span>/<span id="showYearOutput"></span>[% ELSIF ( dateformat == "metric" ) %]<span id="showDayOutput"></span>/<span id="showMonthOutput"></span>/<span id="showYearOutput"></span>[% ELSE %]<span id="showYearOutput"></span>/<span id="showMonthOutput"></span>/<span id="showDayOutput"></span>[% END %]
303
304
                <input type="hidden" id="showWeekday" name="weekday" />
305
                <input type="hidden" id="showDay" name="day" />
306
                <input type="hidden" id="showMonth" name="month" />
307
                <input type="hidden" id="showYear" name="year" />
308
            </li>
309
            <li class="dateinsert">
310
                <b>To Date : </b>
311
                <input type="text" id="datecancelrange" name="dateofrange" size="20" value="[% dateofrange %]" class="datepicker"/>
312
            </li>
313
            <li class="radio hourssel">
314
                <input type="radio" name="hoursType" id="showHoursTypeOpen" value="open" /><label for="showHoursTypeOpen">Open (will delete repeating events)</label>
315
                <input type="radio" name="hoursType" id="showHoursTypeClosed" value="closed" /><label for="showHoursTypeClosed">Closed</label>
316
            </li>
317
            <li class="radio hoursentry" style="display:none">
318
                <label for="showOpenTime">Open at:</label>
319
                <input type="time" name="openTime" id="showOpenTime" size="3" maxlength="5" value="0:00" pattern="(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])" />
320
                <label for="showCloseTime">Closed at:</label>
321
                <input type="time" name="closeTime" id="showCloseTime" size="3" maxlength="5" value="23:59" pattern="(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])" />
322
            </li>
323
            <li><label for="showTitle">Title: </label><input type="text" name="title" id="showTitle" size="35" /></li>
324
            <!-- showTitle is necessary for exception radio button to work properly -->
325
                <label for="showDescription">Description:</label>
326
                <textarea rows="2" cols="40" id="showDescription" name="description"></textarea>
327
            </li>
328
            <li class="radio"><input type="radio" name="op" id="showOperationDel" value="delete" /> <label for="showOperationDel" id="showOperationDelLabel">Delete this event</label>
329
                <a href="#" class="helptext">[?]</a>
330
                <div class="hint">This will delete this event rule.
331
            <li class="radio"><input type="radio" name="op" id="showOperationDelRange" value="deleterange" /> <label for="showOperationDelRange" id="showOperationDelLabelRange">Delete the single events on a range</label>.
332
                <a href="#" class="helptext">[?]</a>
333
                <div class="hint">This will delete the single events only. The repeatable events will not be deleted.</div>
334
            </li>
335
            <li class="radio"><input type="radio" name="op" id="showOperationDelRangeRepeat" value="deleterangerepeat" /> <label for="showOperationDelRangeRepeat" id="showOperationDelLabelRangeRepeat">Delete the repeated events on a range</label>.
336
                <a href="#" class="helptext">[?]</a>
337
                <div class="hint">This will delete the yearly repeated events only.</div>
338
            </li>
339
            <li class="radio"><input type="radio" name="op" id="showOperationEdit" value="save" checked="checked" /> <label for="showOperationEdit">Edit this event</label>
340
                <a href="#" class="helptext">[?]</a>
341
                <div class="hint">This will save changes to the event's title and description. If the information for a repeatable event is modified, it affects all of the dates on which the event is repeated.</div></li>
342
            </ol>
343
            <fieldset class="action">
344
                <input type="submit" name="submit" value="Save" />
345
                <a href="#" class="cancel" name="cancel2" onclick=" hidePanel('showEvent');">Cancel</a>
346
            </fieldset>
347
            </fieldset>
348
        </form>
349
    </div>
350
351
    <!-- ***************************** Panel to deal with new events **********************  -->
352
    <div class="panel" id="newEvent">
353
         <form action="/cgi-bin/koha/tools/calendar.pl" method="post">
354
            <input type="hidden" name="branchCodes" id="branchCodes" value="[% branchcodes %]" />
355
            <input type="hidden" name="op" value="save" />
356
            <fieldset class="brief">
357
            <h3>Add new event</h3>
358
359
        <ol>
360
            <li>
361
                <strong>Library:</strong>
362
                <span id="newBranchNameOutput"></span>
363
                <input type="hidden" id="newBranchName" name="branchName" />
364
            </li>
365
            <li>
366
                <strong>From date:</strong>
367
                <span id="newDaynameOutput"></span>,
368
369
                         [% IF ( dateformat == "us" ) %]<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>/<span id="newYearOutput"></span>[% ELSIF ( dateformat == "metric" ) %]<span id="newDayOutput"></span>/<span id="newMonthOutput"></span>/<span id="newYearOutput"></span>[% ELSE %]<span id="newYearOutput"></span>/<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>[% END %]
370
371
                <input type="hidden" id="newWeekday" name="weekday" />
372
                <input type="hidden" id="newDay" name="day" />
373
                <input type="hidden" id="newMonth" name="month" />
374
                <input type="hidden" id="newYear" name="year" />
375
            </li>
376
            <li class="dateinsert">
377
                <b>To date : </b>
378
                <input type="text" id="dateofrange" name="dateofrange" size="20" value="[% dateofrange %]" class="datepicker" />
379
            </li>
380
            <li class="radio hourssel">
381
                <input type="radio" name="hoursType" id="newHoursTypeOpen" value="open" /><label for="newHoursTypeOpen">Open (will not work for repeating events)</label>
382
                <input type="radio" name="hoursType" id="newHoursTypeClosed" value="closed" /><label for="newHoursTypeClosed">Closed</label>
383
            </li>
384
            <li class="radio hoursentry" style="display:none">
385
                <label for="newOpenTime">Open at:</label>
386
                <input type="time" name="openTime" id="newOpenTime" size="3" maxlength="5" value="0:00" pattern="(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])" />
387
                <label for="newCloseTime">Closed at:</label>
388
                <input type="time" name="closeTime" id="newCloseTime" size="3" maxlength="5" value="23:59" pattern="(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])" />
389
            </li>
390
            <li><label for="title">Title: </label><input type="text" name="title" id="title" size="35" /></li>
391
            <li><label for="newDescription">Description:</label>
392
                <textarea rows="2" cols="40" id="newDescription" name="description"></textarea>
393
            </li>
394
            <li class="radio"><input type="radio" name="eventType" id="newOperationOnce" value="single" checked="checked" />
395
                            <label for="newOperationOnce">Event only on this day</label>.
396
                            <a href="#" class="helptext">[?]</a>
397
                            <div class="hint">Make a single event. For example, selecting August 1st, 2012 will not affect August 1st in other years.</div>
398
                            </li>
399
            <li class="radio"><input type="radio" name="eventType" id="newOperationDay" value="weekly" />
400
                            <label for="newOperationDay">Event repeated weekly</label>.
401
                            <a href="#" class="helptext">[?]</a>
402
                            <div class="hint">Make this weekday an event, every week. For example, if your library is closed on Saturdays, use this option to make every Saturday a event.</div>
403
                            </li>
404
            <li class="radio"><input type="radio" name="eventType" id="newOperationYear" value="yearly" />
405
                            <label for="newOperationYear">Event repeated yearly</label>.
406
                            <a href="#" class="helptext">[?]</a>
407
                            <div class="hint">Make this day of the year an event, every year. For example, selecting August 1st will set the hours for August 1st every year.</div>
408
                            </li>
409
            <li class="radio"><input type="radio" name="eventType" id="newOperationField" value="singlerange" />
410
                            <label for="newOperationField">Events on a range</label>.
411
                            <a href="#" class="helptext">[?]</a>
412
                            <div class="hint">Make events for a range of days. For example, selecting August 1st, 2012 and August 10st, 2012 will make all days between 1st and 10st event, but will not affect August 1-10 in other years.</div>
413
                            </li>
414
            <li class="radio"><input type="radio" name="eventType" id="newOperationFieldyear" value="yearlyrange" />
415
                            <label for="newOperationFieldyear">Events repeated yearly on a range</label>.
416
                            <a href="#" class="helptext">[?]</a>
417
                            <div class="hint">Make a single event on a range repeated yearly. For example, selecting August 1st, 2012  and August 10st, 2012 will make all days between 1st and 10st event, and will affect August 1-10 in other years.</div>
418
                            </li>
419
                <li class="radio">
420
                <input type="checkbox" name="allBranches" id="allBranches" />
421
                <label for="allBranches">Copy to all libraries</label>.
422
                <a href="#" class="helptext">[?]</a>
423
                <div class="hint">If checked, this event will be copied to all libraries. If the event already exists for a library, no change is made.</div>
424
                </li></ol>
425
                <fieldset class="action">
426
                    <input type="submit" name="submit" value="Save" />
427
                    <a href="#" class="cancel" name="cancel2" onclick=" hidePanel('newEvent');">Cancel</a>
428
                </fieldset>
429
                </fieldset>
430
         </form>
431
    </div>
432
433
    <!-- *************************************************************************************** -->
434
    <!-- ******                          END OF FLAT PANELS                               ****** -->
435
    <!-- *************************************************************************************** -->
436
437
<!-- ************************************************************************************** -->
438
<!-- ******                              MAIN SCREEN CODE                            ****** -->
439
<!-- ************************************************************************************** -->
440
<h3>Calendar information</h3>
441
<div id="jcalendar-container"></div>
442
443
<div style="margin-top: 2em;">
444
<form action="/cgi-bin/koha/tools/calendar.pl" method="post">
445
    <input type="hidden" name="op" value="copyall" />
446
    <input type="hidden" name="from_branchcode" value="[% branch %]" />
447
  <label for="branchcode">Copy events to:</label>
448
  <select id="branchcode" name="branchcode" required>
449
    <option value=""></option>
450
    [% FOREACH branchloo IN branchloop %]
451
    <option value="[% branchloo.value %]">[% branchloo.branchname %]</option>
452
    [% END %]
453
  </select>
454
    <input type="submit" value="Copy" />
455
</form>
456
</div>
457
458
</div>
459
<div class="yui-u">
460
<div class="help">
461
<h4>Hints</h4>
462
    <ul>
463
        <li>Search in the calendar the day you want to set as event.</li>
464
        <li>Click the date to add or edit a event.</li>
465
        <li>Enter a title and description for the event.</li>
466
        <li>Specify how the event should repeat.</li>
467
        <li>Click Save to finish.</li>
468
    </ul>
469
<h4>Key</h4>
470
    <p>
471
        <span class="key normalday">Working day</span>
472
        <span class="key event">Unique event</span>
473
        <span class="key repeatableweekly">Event repeating weekly</span>
474
        <span class="key repeatableyearly">Event repeating yearly</span>
475
    </p>
476
</div>
477
<div id="event-list">
478
[% IF ( weekly_events ) %]
479
<h3>Weekly - Repeatable Events</h3>
480
<table id="weekly-events">
481
<thead>
482
<tr>
483
  <th class="repeatableweekly">Day of week</th>
484
  <th class="repeatableweekly">Title</th>
485
  <th class="repeatableweekly">Description</th>
486
  <th class="repeatableweekly">Hours</th>
487
</tr>
488
</thead>
489
<tbody>
490
  [% FOREACH event IN weekly_events %]
491
  <tr>
492
  <td>
493
<script type="text/javascript">
494
  document.write(weekdays[ [% event.weekday %]]);
495
</script>
496
  </td>
497
  <td>[% event.title %]</td>
498
  <td>[% event.description %]</td>
499
  <td>
500
    [% IF event.closed %]
501
    Closed
502
    [% ELSIF event.close_hour == 24 %]
503
    Open
504
    [% ELSE %]
505
    [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] -
506
    [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %]
507
    [% END %]
508
  </td>
509
  </tr>
510
  [% END %]
511
</tbody>
512
</table>
513
[% END %]
514
515
[% IF ( yearly_events ) %]
516
<h3>Yearly - Repeatable Events</h3>
517
<table id="yearly-events">
518
<thead>
519
<tr>
520
  [% IF ( dateformat == "metric" ) %]
521
  <th class="repeatableyearly">Day/Month</th>
522
  [% ELSE %]
523
  <th class="repeatableyearly">Month/Day</th>
524
  [% END %]
525
  <th class="repeatableyearly">Title</th>
526
  <th class="repeatableyearly">Description</th>
527
  <th class="repeatableyearly">Hours</th>
528
</tr>
529
</thead>
530
<tbody>
531
  [% FOREACH event IN yearly_events %]
532
  <tr>
533
  <td><span title="[% event.month_day_display %]">[% event.month_day_sort %]</span></td>
534
  <td>[% event.title %]</td>
535
  <td>[% event.description %]</td>
536
  <td>
537
    [% IF event.closed %]
538
    Closed
539
    [% ELSIF event.close_hour == 24 %]
540
    Open
541
    [% ELSE %]
542
    [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] -
543
    [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %]
544
    [% END %]
545
  </td>
546
  </tr>
547
  [% END %]
548
</tbody>
549
</table>
550
[% END %]
551
552
[% IF ( single_events ) %]
553
<h3>Single Events</h3>
554
<table id="single-events">
555
<thead>
556
<tr>
557
  <th class="event">Date</th>
558
  <th class="event">Title</th>
559
  <th class="event">Description</th>
560
  <th class="event">Hours</th>
561
</tr>
562
</thead>
563
<tbody>
564
    [% FOREACH event IN single_events %]
565
<tr>
566
  <td><a href="/cgi-bin/koha/tools/calendar.pl?branch=[% branch %]&amp;calendardate=[% event.event_date | $KohaDates %]"><span title="[% event.event_date %]">[% event.event_date | $KohaDates %]</span></a></td>
567
  <td>[% event.title %]</td>
568
  <td>[% event.description %]</td>
569
  <td>
570
    [% IF event.closed %]
571
    Closed
572
    [% ELSIF event.close_hour == 24 %]
573
    Open
574
    [% ELSE %]
575
    [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] -
576
    [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %]
577
    [% END %]
578
  </td>
579
</tr>
580
  [% END %]
581
</tbody>
582
</table>
583
[% END %]
584
</div>
585
</div>
586
</div>
587
</div>
588
</div>
589
590
<div class="yui-b noprint">
591
[% INCLUDE 'tools-menu.inc' %]
592
</div>
593
</div>
594
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt (-535 lines)
Lines 1-535 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Tools &rsaquo; [% branchname %] Calendar</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
[% INCLUDE 'calendar.inc' %]
5
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
6
[% INCLUDE 'datatables.inc' %]
7
<script language="JavaScript" type="text/javascript">
8
//<![CDATA[
9
    var weekdays = new Array(_("Sundays"),_("Mondays"),_("Tuesdays"),_("Wednesdays"),_("Thursdays"),_("Fridays"),_("Saturdays"));
10
11
    /* Creates all the structures to deal with all diferents kinds of holidays */
12
    var week_days = new Array();
13
    var holidays = new Array();
14
    var holidates = new Array();
15
    var exception_holidays = new Array();
16
    var day_month_holidays = new Array();
17
    var hola= "[% code %]";
18
    [% FOREACH WEEK_DAYS_LOO IN WEEK_DAYS_LOOP %]
19
    week_days["[% WEEK_DAYS_LOO.KEY %]"] = {title:"[% WEEK_DAYS_LOO.TITLE %]", description:"[% WEEK_DAYS_LOO.DESCRIPTION %]"};
20
    [% END %]
21
    [% FOREACH HOLIDAYS_LOO IN HOLIDAYS_LOOP %]
22
    holidates.push("[% HOLIDAYS_LOO.KEY %]");
23
    holidays["[% HOLIDAYS_LOO.KEY %]"] = {title:"[% HOLIDAYS_LOO.TITLE %]", description:"[% HOLIDAYS_LOO.DESCRIPTION %]"};
24
25
    [% END %]
26
    [% FOREACH EXCEPTION_HOLIDAYS_LOO IN EXCEPTION_HOLIDAYS_LOOP %]
27
    exception_holidays["[% EXCEPTION_HOLIDAYS_LOO.KEY %]"] = {title:"[% EXCEPTION_HOLIDAYS_LOO.TITLE %]", description:"[% EXCEPTION_HOLIDAYS_LOO.DESCRIPTION %]"};
28
    [% END %]
29
    [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN DAY_MONTH_HOLIDAYS_LOOP %]
30
    day_month_holidays["[% DAY_MONTH_HOLIDAYS_LOO.KEY %]"] = {title:"[% DAY_MONTH_HOLIDAYS_LOO.TITLE %]", description:"[% DAY_MONTH_HOLIDAYS_LOO.DESCRIPTION %]"};
31
    [% END %]
32
33
    function holidayOperation(formObject, opType) {
34
        var op = document.getElementsByName('operation');
35
        op[0].value = opType;
36
        formObject.submit();
37
    }
38
39
    // This function shows the "Show Holiday" panel //
40
    function showHoliday (exceptionPosibility, dayName, day, month, year, weekDay, title, description, holidayType) {
41
        $("#newHoliday").slideUp("fast");
42
        $("#showHoliday").slideDown("fast");
43
        $('#showDaynameOutput').html(dayName);
44
        $('#showDayname').val(dayName);
45
        $('#showBranchNameOutput').html($("#branch :selected").text());
46
        $('#showBranchName').val($("#branch").val());
47
        $('#showDayOutput').html(day);
48
        $('#showDay').val(day);
49
        $('#showMonthOutput').html(month);
50
        $('#showMonth').val(month);
51
        $('#showYearOutput').html(year);
52
        $('#showYear').val(year);
53
        $('#showDescription').val(description);
54
        $('#showWeekday:first').val(weekDay);
55
        $('#showTitle').val(title);
56
        $('#showHolidayType').val(holidayType);
57
58
        if (holidayType == 'exception') {
59
            $("#showOperationDelLabel").html(_("Delete this exception."));
60
            $("#holtype").attr("class","key exception").html(_("Holiday exception"));
61
        } else if(holidayType == 'weekday') {
62
            $("#showOperationDelLabel").html(_("Delete this holiday."));
63
            $("#holtype").attr("class","key repeatableweekly").html(_("Holiday repeating weekly"));
64
        } else if(holidayType == 'daymonth') {
65
            $("#showOperationDelLabel").html(_("Delete this holiday."));
66
            $("#holtype").attr("class","key repeatableyearly").html(_("Holiday repeating yearly"));
67
        } else {
68
            $("#showOperationDelLabel").html(_("Delete this holiday."));
69
            $("#holtype").attr("class","key holiday").html(_("Unique holiday"));
70
        }
71
        
72
        if (exceptionPosibility == 1) {
73
            $("#exceptionPosibility").parent().show();
74
        } else {
75
            $("#exceptionPosibility").parent().hide();
76
        }
77
    }
78
79
    // This function shows the "Add Holiday" panel //
80
    function newHoliday (dayName, day, month, year, weekDay) {
81
        $("#showHoliday").slideUp("fast");
82
        $("#newHoliday").slideDown("fast");
83
        $("#newDaynameOutput").html(dayName);
84
        $("#newDayname").val(dayName);
85
        $("#newBranchNameOutput").html($('#branch :selected').text());
86
        $("#newBranchName").val($('#branch').val());
87
        $("#newDayOutput").html(day);
88
        $("#newDay").val(day);
89
        $("#newMonthOutput").html(month);
90
        $("#newMonth").val(month);
91
        $("#newYearOutput").html(year);
92
        $("#newYear").val(year);
93
        $("#newWeekday:first").val(weekDay);
94
    }
95
96
    function hidePanel(aPanelName) {
97
        $("#"+aPanelName).slideUp("fast");
98
    }
99
100
    function changeBranch () {
101
        var branch = $("#branch option:selected").val();
102
        location.href='/cgi-bin/koha/tools/holidays.pl?branch=' + branch + '&calendardate=' + "[% calendardate %]";
103
    }
104
105
    function Help() {
106
        newin=window.open("/cgi-bin/koha/help.pl","KohaHelp",'width=600,height=600,toolbar=false,scrollbars=yes');
107
    }
108
109
    /* This function gives css clases to each kind of day */
110
    function dateStatusHandler(date) {
111
        date = new Date(date);
112
        var day = date.getDate();
113
        var month = date.getMonth() + 1;
114
        var year = date.getFullYear();
115
        var weekDay = date.getDay();
116
        var dayMonth = month + '/' + day;
117
        var dateString = year + '/' + month + '/' + day;
118
        if (exception_holidays[dateString] != null) {
119
            return [true, "exception", "Exception: "+exception_holidays[dateString].title];
120
        } else if ( week_days[weekDay] != null ){
121
            return [true, "repeatableweekly", "Weekly holdiay: "+week_days[weekDay].title];
122
        } else if ( day_month_holidays[dayMonth] != null ) {
123
            return [true, "repeatableyearly", "Yearly holdiay: "+day_month_holidays[dayMonth].title];
124
        } else if (holidays[dateString] != null) {
125
            return [true, "holiday", "Single holiday: "+holidays[dateString].title];
126
        } else {
127
            return [true, "normalday", "Normal day"];
128
        }
129
    }
130
131
    /* This function is in charge of showing the correct panel considering the kind of holiday */
132
    function dateChanged(calendar) {
133
        calendar = new Date(calendar);
134
        var day = calendar.getDate();
135
        var month = calendar.getMonth() + 1;
136
        var year = calendar.getFullYear();
137
        var weekDay = calendar.getDay();
138
        var dayName = weekdays[weekDay];
139
        var dayMonth = month + '/' + day;
140
        var dateString = year + '/' + month + '/' + day;
141
            if (holidays[dateString] != null) {
142
                showHoliday(0, dayName, day, month, year, weekDay, holidays[dateString].title,     holidays[dateString].description, 'ymd');
143
            } else if (exception_holidays[dateString] != null) {
144
                showHoliday(0, dayName, day, month, year, weekDay, exception_holidays[dateString].title, exception_holidays[dateString].description, 'exception');
145
            } else if (week_days[weekDay] != null) {
146
                showHoliday(1, dayName, day, month, year, weekDay, week_days[weekDay].title,     week_days[weekDay].description, 'weekday');
147
            } else if (day_month_holidays[dayMonth] != null) {
148
                showHoliday(1, dayName, day, month, year, weekDay, day_month_holidays[dayMonth].title, day_month_holidays[dayMonth].description, 'daymonth');
149
            } else {
150
                newHoliday(dayName, day, month, year, weekDay);
151
            }
152
    };
153
154
    $(document).ready(function() {
155
156
        $(".hint").hide();
157
        $("#branch").change(function(){
158
            changeBranch();
159
        });
160
        $("#holidayweeklyrepeatable").dataTable($.extend(true, {}, dataTablesDefaults, {
161
            "sDom": 't',
162
            "bPaginate": false
163
        }));
164
        $("#holidayexceptions,#holidaysyearlyrepeatable,#holidaysunique").dataTable($.extend(true, {}, dataTablesDefaults, {
165
            "sDom": 't',
166
            "aoColumns": [
167
                { "sType": "title-string" },null,null
168
            ],
169
            "bPaginate": false
170
        }));
171
        $("a.helptext").click(function(){
172
            $(this).parent().find(".hint").toggle(); return false;
173
        });
174
        $("#dateofrange").datepicker();
175
        $("#datecancelrange").datepicker();
176
        $("#dateofrange").each(function () { this.value = "" });
177
        $("#datecancelrange").each(function () { this.value = "" });
178
        $("#jcalendar-container").datepicker({
179
          beforeShowDay: function(thedate) {
180
            var day = thedate.getDate();
181
            var month = thedate.getMonth() + 1;
182
            var year = thedate.getFullYear();
183
            var dateString = year + '/' + month + '/' + day;
184
            return dateStatusHandler(dateString);
185
            },
186
        onSelect: function(dateText, inst) {
187
            dateChanged($(this).datepicker("getDate"));
188
        },
189
        defaultDate: new Date("[% keydate %]")
190
    });
191
    });
192
//]]>
193
</script>
194
<style type="text/css"> .key { padding : 3px; white-space:nowrap; line-height:230%; }
195
.ui-datepicker { font-size : 150%; }
196
.ui-datepicker th, .ui-datepicker .ui-datepicker-title select { font-size : 80%; }
197
.ui-datepicker td a { padding : .5em; }
198
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { font-size : 80%; }
199
.key { padding : 3px; white-space:nowrap; line-height:230%; }
200
.normalday { background-color :  #EDEDED; color :  Black; border : 1px solid #BCBCBC; }
201
.exception { background-color :  #b3d4ff; color :  Black; border : 1px solid #BCBCBC; }
202
.holiday {  background-color :  #ffaeae; color :  Black;  border : 1px solid #BCBCBC; }
203
.repeatableweekly {  background-color :  #FFFF99; color :  Black;  border : 1px solid #BCBCBC; }
204
.repeatableyearly {  background-color :  #FFCC66; color :  Black;  border : 1px solid #BCBCBC; }
205
td.exception a.ui-state-default { background:  #b3d4ff none; color :  Black; border : 1px solid #BCBCBC; }
206
td.holiday a.ui-state-default {  background:  #ffaeae none; color :  Black;  border : 1px solid #BCBCBC; }
207
td.repeatableweekly a.ui-state-default {  background:  #D8EFB3 none; color :  Black;  border : 1px solid #BCBCBC; }
208
td.repeatableyearly a.ui-state-default {  background:  #FFFF99 none; color :  Black;  border : 1px solid #BCBCBC; }
209
.information { z-index : 1; background-color :  #DCD2F1; width : 300px; display : none; border : 1px solid #000000; color :  #000000; font-size :  8pt; font-weight :  bold; background-color :  #FFD700; cursor :  pointer; padding : 2px; }
210
.panel { z-index : 1; display : none; border : 3px solid #CCC; padding : 3px; margin-top: .3em;  background-color: #FEFEFE; } fieldset.brief { border : 0; margin-top: 0; }
211
#showHoliday { margin : .5em 0; } h1 select { width: 20em; } div.yui-b fieldset.brief ol { font-size:100%; } div.yui-b fieldset.brief li, div.yui-b fieldset.brief li.radio  { padding:0.2em 0; } .help { margin:.3em 0;border:1px solid #EEE;padding:.3em .7em; font-size : 90%; } #holidayweeklyrepeatable, #holidaysyearlyrepeatable, #holidaysunique, #holidayexceptions { font-size : 90%; margin-bottom : 1em;} .calendar td, .calendar th, .calendar .button, .calendar tbody .day { padding : .7em; font-size: 110%; } .calendar { width: auto; border : 0; }
212
</style>
213
</head>
214
<body id="tools_holidays" class="tools">
215
[% INCLUDE 'header.inc' %]
216
[% INCLUDE 'cat-search.inc' %]
217
218
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo; [% branchname %] Calendar</div>
219
220
<div id="doc3" class="yui-t1">
221
   
222
   <div id="bd">
223
    <div id="yui-main">
224
    <div class="yui-b">
225
    <h2>[% branchname %] Calendar</h2>
226
    <div class="yui-g">
227
    <div class="yui-u first">
228
        <label for="branch">Define the holidays for:</label>
229
            <select id="branch" name="branch">
230
                [% FOREACH branchloo IN branchloop %]
231
                    [% IF ( branchloo.selected ) %]
232
                        <option value="[% branchloo.value %]" selected="selected">[% branchloo.branchname %]</option>
233
                    [% ELSE %]
234
                        <option value="[% branchloo.value %]">[% branchloo.branchname %]</option>
235
                    [% END %]
236
                [% END %]
237
            </select>
238
    
239
    <!-- ******************************** FLAT PANELS ******************************************* -->
240
    <!-- *****           Makes all the flat panel to deal with holidays                     ***** -->
241
    <!-- **************************************************************************************** -->
242
243
    <!-- ********************** Panel for showing already loaded holidays *********************** -->
244
    <div class="panel" id="showHoliday">
245
         <form action="/cgi-bin/koha/tools/exceptionHolidays.pl" method="post">
246
             <input type="hidden" id="showHolidayType" name="showHolidayType" value="" />
247
            <fieldset class="brief">
248
            <h3>Edit this holiday</h3>
249
            <span id="holtype"></span>
250
            <ol>
251
            <li>
252
                <strong>Library:</strong> <span id="showBranchNameOutput"></span>
253
                <input type="hidden" id="showBranchName" name="showBranchName" />
254
            </li>
255
            <li>
256
                <strong>From Date:</strong>
257
                <span id="showDaynameOutput"></span>, 
258
                
259
                                [% IF ( dateformat == "us" ) %]<span id="showMonthOutput"></span>/<span id="showDayOutput"></span>/<span id="showYearOutput"></span>[% ELSIF ( dateformat == "metric" ) %]<span id="showDayOutput"></span>/<span id="showMonthOutput"></span>/<span id="showYearOutput"></span>[% ELSE %]<span id="showYearOutput"></span>/<span id="showMonthOutput"></span>/<span id="showDayOutput"></span>[% END %]
260
261
                <input type="hidden" id="showDayname" name="showDayname" />
262
                <input type="hidden" id="showWeekday" name="showWeekday" />
263
                <input type="hidden" id="showDay" name="showDay" />
264
                <input type="hidden" id="showMonth" name="showMonth" />
265
                <input type="hidden" id="showYear" name="showYear" />
266
            </li>
267
            <li class="dateinsert">
268
                <b>To Date : </b>
269
                <input type="text" id="datecancelrange" name="datecancelrange" size="20" value="[% datecancelrange %]" class="datepicker"/>
270
            </li>
271
            <li><label for="showTitle">Title: </label><input type="text" name="showTitle" id="showTitle" size="35" /></li>
272
            <!-- showTitle is necessary for exception radio button to work properly --> 
273
                <label for="showDescription">Description:</label>
274
                <textarea rows="2" cols="40" id="showDescription" name="showDescription"></textarea>    
275
            </li>
276
            <li class="radio"><div id="exceptionPosibility" style="position:static">
277
                <input type="radio" name="showOperation" id="showOperationExc" value="exception" /> <label for="showOperationExc">Generate an exception for this repeated holiday.</label>
278
                <a href="#" class="helptext">[?]</a>
279
                <div class="hint">You can make an exception for this holiday rule. This means that you will be able to say that for a repeatable holiday there is one day which is going to be an exception.</div>
280
            </div></li>
281
            <li class="radio"><input type="radio" name="showOperation" id="showOperationExcRange" value="exceptionrange" />
282
                <label for="newOperationFieldException">Generate exceptions on a range of dates.</label>
283
                <a href="#" class="helptext">[?]</a>
284
                <div class="hint">You can make an exception on a range of dates repeated yearly.</div>
285
            </li>
286
            <li class="radio"><input type="radio" name="showOperation" id="showOperationDel" value="delete" /> <label for="showOperationDel" id="showOperationDelLabel">Delete this holiday</label>
287
                <a href="#" class="helptext">[?]</a>
288
                <div class="hint">This will delete this holiday rule. If it is a repeatable holiday, this option checks for possible exceptions. If an exception exists, this option will remove the exception and set the date to a regular holiday.</div></li>
289
            <li class="radio"><input type="radio" name="showOperation" id="showOperationDelRange" value="deleterange" /> <label for="showOperationDelRange" id="showOperationDelLabelRange">Delete the single holidays on a range</label>.
290
                <a href="#" class="helptext">[?]</a>
291
                <div class="hint">This will delete the single holidays rules only. The repeatable holidays and exceptions will not be deleted.</div>
292
            </li>
293
            <li class="radio"><input type="radio" name="showOperation" id="showOperationDelRangeRepeat" value="deleterangerepeat" /> <label for="showOperationDelRangeRepeat" id="showOperationDelLabelRangeRepeat">Delete the repeated holidays on a range</label>.
294
                <a href="#" class="helptext">[?]</a>
295
                <div class="hint">This will delete the repeated holidays rules only. The repeatable holidays will be deleted but not the exceptions.</div>
296
            </li>
297
            <li class="radio"><input type="radio" name="showOperation" id="showOperationDelRangeRepeatExcept" value="deleterangerepeatexcept" /> <label for="showOperationDelRangeRepeatExcept" id="showOperationDelLabelRangeRepeatExcept">Delete the exceptions on a range</label>.
298
                <a href="#" class="helptext">[?]</a>
299
                <div class="hint">This will delete the exceptions inside a given range. Be careful about your scope range if it is oversized you could slow down Koha.</div>
300
            </li>
301
            <li class="radio"><input type="radio" name="showOperation" id="showOperationEdit" value="edit" checked="checked" /> <label for="showOperationEdit">Edit this holiday</label>
302
                <a href="#" class="helptext">[?]</a>
303
                <div class="hint">This will save changes to the holiday's title and description. If the information for a repeatable holiday is modified, it affects all of the dates on which the holiday is repeated.</div></li>
304
            </ol>
305
            <fieldset class="action">
306
                <input type="submit" name="submit" value="Save" />
307
                <a href="#" class="cancel" name="cancel2" onclick=" hidePanel('showHoliday');">Cancel</a>
308
            </fieldset>
309
            </fieldset>
310
        </form>
311
    </div>
312
313
    <!-- ***************************** Panel to deal with new holidays **********************  -->
314
    <div class="panel" id="newHoliday">
315
         <form action="/cgi-bin/koha/tools/newHolidays.pl" method="post">
316
                <input type="hidden" name="branchCodes" id="branchCodes" value="[% branchcodes %]" /> 
317
            <fieldset class="brief">
318
            <h3>Add new holiday</h3>
319
            <ol>
320
            <li>
321
                <strong>Library:</strong>
322
                <span id="newBranchNameOutput"></span>
323
                <input type="hidden" id="newBranchName" name="newBranchName" />
324
            </li>
325
            <li>
326
                <strong>From date:</strong>
327
                <span id="newDaynameOutput"></span>, 
328
329
                         [% IF ( dateformat == "us" ) %]<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>/<span id="newYearOutput"></span>[% ELSIF ( dateformat == "metric" ) %]<span id="newDayOutput"></span>/<span id="newMonthOutput"></span>/<span id="newYearOutput"></span>[% ELSE %]<span id="newYearOutput"></span>/<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>[% END %]
330
331
                <input type="hidden" id="newDayname" name="showDayname" />
332
                <input type="hidden" id="newWeekday" name="newWeekday" />
333
                <input type="hidden" id="newDay" name="newDay" />
334
                <input type="hidden" id="newMonth" name="newMonth" />
335
                <input type="hidden" id="newYear" name="newYear" />
336
            </li>
337
            <li class="dateinsert">
338
                <b>To date : </b>
339
                <input type="text" id="dateofrange" name="dateofrange" size="20" value="[% dateofrange %]" class="datepicker" />
340
            </li>
341
            <li><label for="title">Title: </label><input type="text" name="newTitle" id="title" size="35" /></li>
342
            <li><label for="newDescription">Description:</label>
343
                <textarea rows="2" cols="40" id="newDescription" name="newDescription"></textarea>
344
            </li>
345
            <li class="radio"><input type="radio" name="newOperation" id="newOperationOnce" value="holiday" checked="checked" />
346
            <label for="newOperationOnce">Holiday only on this day</label>.
347
            <a href="#" class="helptext">[?]</a>
348
            <div class="hint">Make a single holiday. For example, selecting August 1st, 2012 will make it a holiday, but will not affect August 1st in other years.</div>
349
            </li>
350
            <li class="radio"><input type="radio" name="newOperation" id="newOperationDay" value="weekday" />
351
                            <label for="newOperationDay">Holiday repeated every same day of the week</label>.
352
                            <a href="#" class="helptext">[?]</a>
353
                            <div class="hint">Make this weekday a holiday, every week. For example, if your library is closed on Saturdays, use this option to make every Saturday a holiday.</div>
354
                            </li>
355
            <li class="radio"><input type="radio" name="newOperation" id="newOperationYear" value="repeatable" />
356
                            <label for="newOperationYear">Holiday repeated yearly on the same date</label>.
357
                            <a href="#" class="helptext">[?]</a>
358
                            <div class="hint">This will take this day and month as a reference to make it a holiday. Through this option, you can repeat this rule for every year. For example, selecting August 1st will make August 1st a holiday every year.</div>
359
                            </li>
360
            <li class="radio"><input type="radio" name="newOperation" id="newOperationField" value="holidayrange" />
361
                            <label for="newOperationField">Holidays on a range</label>.
362
                            <a href="#" class="helptext">[?]</a>
363
                            <div class="hint">Make a single holiday on a range. For example, selecting August 1st, 2012  and August 10st, 2012 will make all days between 1st and 10st holiday, but will not affect August 1-10 in other years.</div>
364
                            </li>
365
            <li class="radio"><input type="radio" name="newOperation" id="newOperationFieldyear" value="holidayrangerepeat" />
366
                            <label for="newOperationFieldyear">Holidays repeated yearly on a range</label>.
367
                            <a href="#" class="helptext">[?]</a>
368
                            <div class="hint">Make a single holiday on a range repeated yearly. For example, selecting August 1st, 2012  and August 10st, 2012 will make all days between 1st and 10st holiday, and will affect August 1-10 in other years.</div>
369
                            </li>
370
                <li class="radio">
371
                <input type="checkbox" name="allBranches" id="allBranches" />
372
                <label for="allBranches">Copy to all libraries</label>.
373
                <a href="#" class="helptext">[?]</a>
374
                <div class="hint">If checked, this holiday will be copied to all libraries. If the holiday already exists for a library, no change is made.</div>
375
                </li></ol>
376
                <fieldset class="action">
377
                    <input type="submit" name="submit" value="Save" />
378
                    <a href="#" class="cancel" name="cancel2" onclick=" hidePanel('newHoliday');">Cancel</a>
379
                </fieldset>
380
                </fieldset>
381
         </form>
382
    </div>
383
384
    <!-- *************************************************************************************** -->
385
    <!-- ******                          END OF FLAT PANELS                               ****** -->
386
    <!-- *************************************************************************************** -->
387
388
<!-- ************************************************************************************** -->
389
<!-- ******                              MAIN SCREEN CODE                            ****** -->
390
<!-- ************************************************************************************** -->
391
<h3>Calendar information</h3>
392
<div id="jcalendar-container"></div>
393
394
<div style="margin-top: 2em;">
395
<form action="copy-holidays.pl" method="post">
396
    <input type="hidden" name="from_branchcode" value="[% branch %]" />
397
  <label for="branchcode">Copy holidays to:</label>
398
  <select id="branchcode" name="branchcode">
399
    <option value=""></option>
400
    [% FOREACH branchloo IN branchloop %]
401
    <option value="[% branchloo.value %]">[% branchloo.branchname %]</option>
402
    [% END %]
403
  </select>
404
    <input type="submit" value="Copy" />
405
</form>
406
</div>
407
408
</div>
409
<div class="yui-u">
410
<div class="help">
411
<h4>Hints</h4>
412
    <ul>
413
        <li>Search in the calendar the day you want to set as holiday.</li>
414
        <li>Click the date to add or edit a holiday.</li>
415
        <li>Enter a title and description for the holdiay.</li>
416
        <li>Specify how the holiday should repeat.</li>
417
        <li>Click Save to finish.</li>
418
    </ul>
419
<h4>Key</h4>
420
    <p>
421
        <span class="key normalday">Working day</span>
422
        <span class="key holiday">Unique holiday</span>
423
        <span class="key repeatableweekly">Holiday repeating weekly</span>
424
        <span class="key repeatableyearly">Holiday repeating yearly</span>
425
        <span class="key exception">Holiday exception</span>
426
    </p>
427
</div>
428
<div id="holiday-list">
429
<!-- Exceptions First -->
430
<!--   this will probably always have the least amount of data -->
431
[% IF ( EXCEPTION_HOLIDAYS_LOOP ) %]
432
<h3>Exceptions</h3>
433
  <table id="holidayexceptions">
434
<thead><tr>
435
  <th class="exception">Date</th>
436
  <th class="exception">Title</th>
437
  <th class="exception">Description</th>
438
</tr>
439
</thead>
440
<tbody>
441
  [% FOREACH EXCEPTION_HOLIDAYS_LOO IN EXCEPTION_HOLIDAYS_LOOP %]
442
  <tr>
443
  <td><a href="/cgi-bin/koha/tools/holidays.pl?branch=[% branch %]&amp;calendardate=[% EXCEPTION_HOLIDAYS_LOO.DATE %]"><span title="[% EXCEPTION_HOLIDAYS_LOO.DATE_SORT %]">[% EXCEPTION_HOLIDAYS_LOO.DATE %]</span></a></td>
444
  <td>[% EXCEPTION_HOLIDAYS_LOO.TITLE %]</td>
445
  <td>[% EXCEPTION_HOLIDAYS_LOO.DESCRIPTION %]</td> 
446
  </tr>
447
  [% END %] 
448
</tbody>
449
</table>
450
[% END %]
451
452
[% IF ( WEEK_DAYS_LOOP ) %]
453
<h3>Weekly - Repeatable Holidays</h3>
454
<table id="holidayweeklyrepeatable">
455
<thead>
456
<tr>
457
  <th class="repeatableweekly">Day of week</th>
458
  <th class="repeatableweekly">Title</th>
459
  <th class="repeatableweekly">Description</th>
460
</tr>
461
</thead>
462
<tbody>
463
  [% FOREACH WEEK_DAYS_LOO IN WEEK_DAYS_LOOP %]
464
  <tr>
465
  <td>
466
<script type="text/javascript">
467
  document.write(weekdays[ [% WEEK_DAYS_LOO.KEY %]]);
468
</script>
469
  </td> 
470
  <td>[% WEEK_DAYS_LOO.TITLE %]</td> 
471
  <td>[% WEEK_DAYS_LOO.DESCRIPTION %]</td> 
472
  </tr>
473
  [% END %] 
474
</tbody>
475
</table>
476
[% END %]
477
478
[% IF ( DAY_MONTH_HOLIDAYS_LOOP ) %]
479
<h3>Yearly - Repeatable Holidays</h3>
480
<table id="holidaysyearlyrepeatable">
481
<thead>
482
<tr>
483
  [% IF ( dateformat == "metric" ) %]
484
  <th class="repeatableyearly">Day/Month</th>
485
  [% ELSE %]
486
  <th class="repeatableyearly">Month/Day</th>
487
  [% END %]
488
  <th class="repeatableyearly">Title</th>
489
  <th class="repeatableyearly">Description</th>
490
</tr>
491
</thead>
492
<tbody>
493
  [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN DAY_MONTH_HOLIDAYS_LOOP %]
494
  <tr>
495
  <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT %]">[% DAY_MONTH_HOLIDAYS_LOO.DATE %]</span></td>
496
  <td>[% DAY_MONTH_HOLIDAYS_LOO.TITLE %]</td> 
497
  <td>[% DAY_MONTH_HOLIDAYS_LOO.DESCRIPTION %]</td> 
498
  </tr>
499
  [% END %] 
500
</tbody>
501
</table>
502
[% END %]
503
504
[% IF ( HOLIDAYS_LOOP ) %]
505
<h3>Unique Holidays</h3>
506
<table id="holidaysunique">
507
<thead>
508
<tr>
509
  <th class="holiday">Date</th>
510
  <th class="holiday">Title</th>
511
  <th class="holiday">Description</th>
512
</tr>
513
</thead>
514
<tbody>
515
    [% FOREACH HOLIDAYS_LOO IN HOLIDAYS_LOOP %]
516
<tr>
517
  <td><a href="/cgi-bin/koha/tools/holidays.pl?branch=[% branch %]&amp;calendardate=[% HOLIDAYS_LOO.DATE %]"><span title="[% HOLIDAYS_LOO.DATE_SORT %]">[% HOLIDAYS_LOO.DATE %]</span></a></td>
518
  <td>[% HOLIDAYS_LOO.TITLE %]</td>
519
  <td>[% HOLIDAYS_LOO.DESCRIPTION %]</td>
520
</tr>
521
  [% END %] 
522
</tbody>
523
</table>
524
[% END %]
525
</div>
526
</div>
527
</div>
528
</div>
529
</div>
530
531
<div class="yui-b noprint">
532
[% INCLUDE 'tools-menu.inc' %]
533
</div>
534
</div>
535
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt (-1 / +1 lines)
Lines 73-79 Link Here
73
<h3>Additional tools</h3>
73
<h3>Additional tools</h3>
74
<dl>
74
<dl>
75
    [% IF ( CAN_user_tools_edit_calendar ) %]
75
    [% IF ( CAN_user_tools_edit_calendar ) %]
76
    <dt><a href="/cgi-bin/koha/tools/holidays.pl">Calendar</a></dt>
76
    <dt><a href="/cgi-bin/koha/tools/calendar.pl">Calendar</a></dt>
77
    <dd>Define days when the library is closed</dd>
77
    <dd>Define days when the library is closed</dd>
78
    [% END %]
78
    [% END %]
79
79
(-)a/misc/cronjobs/staticfines.pl (-3 / +8 lines)
Lines 40-48 use Date::Calc qw/Date_to_Days/; Link Here
40
use C4::Context;
40
use C4::Context;
41
use C4::Circulation;
41
use C4::Circulation;
42
use C4::Overdues;
42
use C4::Overdues;
43
use C4::Calendar qw();    # don't need any exports from Calendar
44
use C4::Biblio;
43
use C4::Biblio;
45
use C4::Debug;            # supplying $debug and $cgi_debug
44
use C4::Debug;            # supplying $debug and $cgi_debug
45
use Koha::Calendar;
46
46
use Getopt::Long;
47
use Getopt::Long;
47
use List::MoreUtils qw/none/;
48
use List::MoreUtils qw/none/;
48
use Koha::DateUtils;
49
use Koha::DateUtils;
Lines 172-181 for ( my $i = 0 ; $i < scalar(@$data) ; $i++ ) { Link Here
172
173
173
    my $calendar;
174
    my $calendar;
174
    unless ( defined( $calendars{$branchcode} ) ) {
175
    unless ( defined( $calendars{$branchcode} ) ) {
175
        $calendars{$branchcode} = C4::Calendar->new( branchcode => $branchcode );
176
        $calendars{$branchcode} = Koha::Calendar->new( branchcode => $branchcode );
176
    }
177
    }
177
    $calendar = $calendars{$branchcode};
178
    $calendar = $calendars{$branchcode};
178
    my $isHoliday = $calendar->isHoliday( $tday, $tmonth, $tyear );
179
    my $isHoliday = $calendar->is_holiday( DateTime->new(
180
        year => $tyear,
181
        month => $tmonth,
182
        day => $tday
183
    ) );
179
184
180
    # Reassing datedue_days if -delay specified in commandline
185
    # Reassing datedue_days if -delay specified in commandline
181
    $bigdebug and warn "Using commandline supplied delay : $delay" if ($delay);
186
    $bigdebug and warn "Using commandline supplied delay : $delay" if ($delay);
(-)a/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl (-18 / +13 lines)
Lines 37-43 use C4::Items; Link Here
37
use C4::Letters;
37
use C4::Letters;
38
use C4::Overdues;
38
use C4::Overdues;
39
use C4::Dates;
39
use C4::Dates;
40
use C4::Calendar;
40
use Koha::Calendar;
41
41
42
sub usage {
42
sub usage {
43
    pod2usage( -verbose => 2 );
43
    pod2usage( -verbose => 2 );
Lines 311-333 sub GetWaitingHolds { Link Here
311
          sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] );
311
          sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] );
312
        $issue->{'level'} = 1;   # only one level for Hold Waiting notifications
312
        $issue->{'level'} = 1;   # only one level for Hold Waiting notifications
313
313
314
        my $days_to_subtract = 0;
314
        my $calendar = Koha::Calendar->new( branchcode => $issue->{'site'} );
315
        my $calendar = C4::Calendar->new( branchcode => $issue->{'site'} );
315
        $issue->{'days_since_waiting'} = $calendar->days_between(
316
        while (
316
            DateTime->new(
317
            $calendar->isHoliday(
317
                year => $waitingdate[0],
318
                reverse(
318
                month => $waitingdate[1],
319
                    Add_Delta_Days(
319
                day => $waitingdate[2],
320
                        $waitingdate[0], $waitingdate[1],
320
                time_zone => C4::Context->tz,
321
                        $waitingdate[2], $days_to_subtract
321
            ),
322
                    )
322
            DateTime->now(
323
                )
323
                time_zone => C4::Context->tz,
324
            )
324
            ),
325
          )
325
        );
326
        {
327
            $days_to_subtract++;
328
        }
329
        $issue->{'days_since_waiting'} =
330
          $issue->{'days_since_waiting'} - $days_to_subtract;
331
326
332
        if (
327
        if (
333
            (
328
            (
(-)a/t/Calendar.t (-5 / +1 lines)
Lines 4-20 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 => 35;
7
use Test::More tests => 34;
8
use Test::MockModule;
8
use Test::MockModule;
9
use DBD::Mock;
9
use DBD::Mock;
10
use Koha::DateUtils;
10
use Koha::DateUtils;
11
11
12
BEGIN {
12
BEGIN {
13
    use_ok('Koha::Calendar');
13
    use_ok('Koha::Calendar');
14
15
    # This was the only test C4 had
16
    # Remove when no longer used
17
    use_ok('C4::Calendar');
18
}
14
}
19
15
20
my $module_context = new Test::MockModule('C4::Context');
16
my $module_context = new Test::MockModule('C4::Context');
(-)a/t/db_dependent/Calendar.t (+77 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
use Test::More tests => 14;
4
5
use C4::Calendar;
6
7
my $new_holiday = { open_hour    => 0,
8
                    open_minute  => 0,
9
                    close_hour   => 0,
10
                    close_minute => 0,
11
                    title        => 'example week_day_holiday',
12
                    description  => 'This is an example week_day_holiday used for testing' };
13
14
# Weekly events
15
ModRepeatingEvent( 'UPL', 1, undef, undef, $new_holiday );
16
17
my $weekly_events = GetWeeklyEvents( 'UPL' );
18
is( $weekly_events->[0]->{'title'}, $new_holiday->{'title'}, 'weekly title' );
19
is( $weekly_events->[0]->{'description'}, $new_holiday->{'description'}, 'weekly description' );
20
21
$new_holiday->{close_hour} = 24;
22
23
ModRepeatingEvent( 'UPL', 1, undef, undef, $new_holiday );
24
$weekly_events = GetWeeklyEvents( 'UPL' );
25
is( scalar @$weekly_events, 0, 'weekly modification, not insertion' );
26
27
$new_holiday->{close_hour} = 0;
28
ModRepeatingEvent( 'UPL', 1, undef, undef, $new_holiday );
29
30
# Yearly events
31
32
ModRepeatingEvent( 'UPL', undef, 6, 26, $new_holiday );
33
34
my $yearly_events = GetYearlyEvents( 'UPL' );
35
is( $yearly_events->[0]->{'title'}, $new_holiday->{'title'}, 'yearly title' );
36
is( $yearly_events->[0]->{'description'}, $new_holiday->{'description'}, 'yearly description' );
37
38
$new_holiday->{close_hour} = 24;
39
40
ModRepeatingEvent( 'UPL', undef, 6, 26, $new_holiday );
41
$yearly_events = GetYearlyEvents( 'UPL' );
42
is( scalar @$yearly_events, 0, 'yearly modification, not insertion' );
43
44
$new_holiday->{close_hour} = 0;
45
ModRepeatingEvent( 'UPL', undef, 6, 26, $new_holiday );
46
47
# Single events
48
49
ModSingleEvent( 'UPL', '2013-03-17', $new_holiday );
50
51
my $single_events = GetSingleEvents( 'UPL' );
52
is( $single_events->[0]->{'title'}, $new_holiday->{'title'}, 'single title' );
53
is( $single_events->[0]->{'description'}, $new_holiday->{'description'}, 'single description' );
54
is( $single_events->[0]->{'closed'}, 1, 'single closed' );
55
56
$new_holiday->{close_hour} = 24;
57
58
ModSingleEvent( 'UPL', '2013-03-17', $new_holiday );
59
$single_events = GetSingleEvents( 'UPL' );
60
is( scalar @$single_events, 1, 'single modification, not insertion' );
61
is( $single_events->[0]->{'closed'}, 0, 'single closed' );
62
63
64
# delete
65
66
DelRepeatingEvent( 'UPL', 1, undef, undef );
67
$weekly_events = GetWeeklyEvents( 'UPL' );
68
is( scalar @$weekly_events, 0, 'weekly deleted' );
69
70
DelRepeatingEvent( 'UPL', undef, 6, 26 );
71
$yearly_events = GetYearlyEvents( 'UPL' );
72
is( scalar @$yearly_events, 0, 'yearly deleted' );
73
74
DelSingleEvent( 'UPL', '2013-03-17' );
75
76
$single_events = GetSingleEvents( 'UPL' );
77
is( scalar @$single_events, 0, 'single deleted' );
(-)a/t/db_dependent/Holidays.t (-14 / +1 lines)
Lines 5-22 use DateTime; Link Here
5
use DateTime::TimeZone;
5
use DateTime::TimeZone;
6
6
7
use C4::Context;
7
use C4::Context;
8
use Test::More tests => 10;
8
use Test::More tests => 6;
9
9
10
BEGIN { use_ok('Koha::Calendar'); }
10
BEGIN { use_ok('Koha::Calendar'); }
11
BEGIN { use_ok('C4::Calendar'); }
12
11
13
my $branchcode = 'MPL';
12
my $branchcode = 'MPL';
14
13
15
my $koha_calendar = Koha::Calendar->new( branchcode => $branchcode );
14
my $koha_calendar = Koha::Calendar->new( branchcode => $branchcode );
16
my $c4_calendar = C4::Calendar->new( branchcode => $branchcode );
17
15
18
isa_ok( $koha_calendar, 'Koha::Calendar', 'Koha::Calendar class returned' );
16
isa_ok( $koha_calendar, 'Koha::Calendar', 'Koha::Calendar class returned' );
19
isa_ok( $c4_calendar,   'C4::Calendar',   'C4::Calendar class returned' );
20
17
21
my $sunday = DateTime->new(
18
my $sunday = DateTime->new(
22
    year  => 2011,
19
    year  => 2011,
Lines 43-55 is( $koha_calendar->is_holiday($sunday), 1, 'Sunday is a closed day' ); Link Here
43
is( $koha_calendar->is_holiday($monday),    0, 'Monday is not a closed day' );
40
is( $koha_calendar->is_holiday($monday),    0, 'Monday is not a closed day' );
44
is( $koha_calendar->is_holiday($christmas), 1, 'Christmas is a closed day' );
41
is( $koha_calendar->is_holiday($christmas), 1, 'Christmas is a closed day' );
45
is( $koha_calendar->is_holiday($newyear), 1, 'New Years day is a closed day' );
42
is( $koha_calendar->is_holiday($newyear), 1, 'New Years day is a closed day' );
46
47
my $custom_holiday = DateTime->new(
48
    year  => 2013,
49
    month => 11,
50
    day   => 12,
51
);
52
is( $koha_calendar->is_holiday($custom_holiday), 0, '2013-11-10 does not start off as a holiday' );
53
$koha_calendar->add_holiday($custom_holiday);
54
is( $koha_calendar->is_holiday($custom_holiday), 1, 'able to add holiday for testing' );
55
(-)a/tools/calendar.pl (+261 lines)
Line 0 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 under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 2 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
16
# Suite 330, Boston, MA  02111-1307 USA
17
18
#####Sets holiday periods for each branch. Datedues will be extended if branch is closed -TG
19
20
use Modern::Perl;
21
22
use CGI;
23
24
use C4::Auth;
25
use C4::Output;
26
27
use C4::Branch; # GetBranches
28
use C4::Calendar;
29
30
my $input = new CGI;
31
32
my $dbh = C4::Context->dbh();
33
# Get the template to use
34
my ($template, $loggedinuser, $cookie)
35
    = get_template_and_user({template_name => "tools/calendar.tmpl",
36
                             type => "intranet",
37
                             query => $input,
38
                             authnotrequired => 0,
39
                             flagsrequired => {tools => 'edit_calendar'},
40
                             debug => 1,
41
                           });
42
43
# keydate - date passed to calendar.js.  calendar.js does not process dashes within a date.
44
my $keydate;
45
# calendardate - date passed in url for human readability (syspref)
46
my $calendardate;
47
my $today = C4::Dates->new();
48
my $calendarinput = C4::Dates->new($input->param('calendardate')) || $today;
49
# if the url has an invalid date default to 'now.'
50
unless($calendardate = $calendarinput->output('syspref')) {
51
  $calendardate = $today->output('syspref');
52
}
53
unless($keydate = $calendarinput->output('iso')) {
54
  $keydate = $today->output('iso');
55
}
56
$keydate =~ s/-/\//g;
57
58
my $branch= $input->param('branchName') || $input->param('branch') || C4::Context->userenv->{'branch'};
59
# Set all the branches.
60
my $onlymine=(C4::Context->preference('IndependentBranches') &&
61
              C4::Context->userenv &&
62
              C4::Context->userenv->{flags} % 2 !=1  &&
63
              C4::Context->userenv->{branch}?1:0);
64
if ( $onlymine ) {
65
    $branch = C4::Context->userenv->{'branch'};
66
}
67
my $branchname = GetBranchName($branch);
68
my $branches   = GetBranches($onlymine);
69
my @branchloop;
70
for my $thisbranch (
71
    sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} }
72
    keys %{$branches} ) {
73
    push @branchloop,
74
      { value      => $thisbranch,
75
        selected   => $thisbranch eq $branch,
76
        branchname => $branches->{$thisbranch}->{'branchname'},
77
      };
78
}
79
80
# branches calculated - put branch codes in a single string so they can be passed in a form
81
my $branchcodes = join '|', keys %{$branches};
82
83
my $op = $input->param( 'op' ) // '';
84
85
my @ranged_dates;
86
87
if ( my $dateofrange = $input->param( 'dateofrange' ) ) {
88
    my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' );
89
90
    my ( $start_year, $start_month, $start_day ) = split( /-/, $date );
91
    my ( $end_year, $end_month, $end_day ) = split( /-/, C4::Dates->new( $dateofrange )->output( 'iso' ) );
92
93
    if ( $end_year && $end_month && $end_day ){
94
        my $first_dt = DateTime->new(year => $start_year, month => $start_month, day => $start_day);
95
        my $end_dt   = DateTime->new(year => $end_year, month => $end_month, day => $end_day);
96
97
        for ( my $dt = $first_dt->clone(); $dt <= $end_dt; $dt->add(days => 1) ) {
98
            push @ranged_dates, $dt->clone();
99
        }
100
    }
101
}
102
103
my @branches;
104
if ( $input->param( 'allBranches' ) || !$input->param( 'branchName' ) ) {
105
    @branches = split /\|/, $input->param( 'branchcodes' );
106
} else {
107
    @branches = ( $input->param( 'branchName' ) );
108
}
109
110
if ( $op eq 'save' ) {
111
    my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' );
112
113
    local our ( $open_hour, $open_minute, $close_hour, $close_minute );
114
115
    if ( $input->param( 'hoursType' ) eq 'open' ) {
116
        ( $open_hour, $open_minute ) = ( 0, 0 );
117
        ( $close_hour, $close_minute ) = ( 24, 0 );
118
    } elsif ( $input->param( 'hoursType' ) eq 'closed' ) {
119
        ( $open_hour, $open_minute ) = ( 0, 0 );
120
        ( $close_hour, $close_minute ) = ( 0, 0 );
121
    } else {
122
        ( $open_hour, $open_minute ) = ( $input->param( 'openTime' ) =~ /(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])/ );
123
        ( $close_hour, $close_minute ) = ( $input->param( 'closeTime' ) =~ /(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])/ );
124
    }
125
126
    foreach our $branchcode ( @branches ) {
127
        my %event_types = (
128
            'single' => sub {
129
                ModSingleEvent( $branchcode, $date, {
130
                    title => $input->param( 'title' ),
131
                    description => $input->param( 'description' ),
132
                    open_hour => $open_hour,
133
                    open_minute => $open_minute,
134
                    close_hour => $close_hour,
135
                    close_minute => $close_minute
136
                } );
137
            },
138
139
            'weekly' => sub {
140
                ModRepeatingEvent( $branchcode, $input->param( 'weekday' ), undef, undef, {
141
                    title => $input->param( 'title' ),
142
                    description => $input->param( 'description' ),
143
                    open_hour => $open_hour,
144
                    open_minute => $open_minute,
145
                    close_hour => $close_hour,
146
                    close_minute => $close_minute
147
                } );
148
            },
149
150
            'yearly' => sub {
151
                ModRepeatingEvent( $branchcode, undef, $input->param( 'month' ), $input->param( 'day' ), {
152
                    title => $input->param( 'title' ),
153
                    description => $input->param( 'description' ),
154
                    open_hour => $open_hour,
155
                    open_minute => $open_minute,
156
                    close_hour => $close_hour,
157
                    close_minute => $close_minute
158
                } );
159
            },
160
161
            'singlerange' => sub {
162
                foreach my $dt ( @ranged_dates ) {
163
                    ModSingleEvent( $branchcode, $dt->ymd, {
164
                        title => $input->param( 'title' ),
165
                        description => $input->param( 'description' ),
166
                        open_hour => $open_hour,
167
                        open_minute => $open_minute,
168
                        close_hour => $close_hour,
169
                        close_minute => $close_minute
170
                    } );
171
                }
172
            },
173
174
            'yearlyrange' => sub {
175
                foreach my $dt ( @ranged_dates ) {
176
                    ModRepeatingEvent( $branchcode, undef, $dt->month, $dt->day, {
177
                        title => $input->param( 'title' ),
178
                        description => $input->param( 'description' ),
179
                        open_hour => $open_hour,
180
                        open_minute => $open_minute,
181
                        close_hour => $close_hour,
182
                        close_minute => $close_minute
183
                    } );
184
                }
185
            },
186
        );
187
188
        # Choose from the above options
189
        $event_types{ $input->param( 'eventType' ) }->();
190
    }
191
} elsif ( $op eq 'delete' ) {
192
    my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' );
193
194
    foreach my $branchcode ( @branches ) {
195
        my %event_types = (
196
            'single' => sub {
197
                DelSingleEvent( $branchcode, $date );
198
            },
199
200
            'weekly' => sub {
201
                DelRepeatingEvent( $branchcode, $input->param( 'weekday' ), undef, undef );
202
            },
203
204
            'yearly' => sub {
205
                DelRepeatingEvent( $branchcode, undef, $input->param( 'month' ), $input->param( 'day' ) );
206
            },
207
        );
208
209
        # Choose from the above options
210
        $event_types{ $input->param( 'eventType' ) }->();
211
    }
212
} elsif ( $op eq 'deleterange' ) {
213
    foreach my $branchcode ( @branches ) {
214
        foreach my $dt ( @ranged_dates ) {
215
            DelSingleEvent( $branchcode, $dt->ymd );
216
        }
217
    }
218
} elsif ( $op eq 'deleterangerepeat' ) {
219
    foreach my $branchcode ( @branches ) {
220
        foreach my $dt ( @ranged_dates ) {
221
            DelRepeatingEvent( $branchcode, undef, $dt->month, $dt->day );
222
        }
223
    }
224
} elsif ( $op eq 'copyall' ) {
225
    CopyAllEvents( $input->param( 'from_branchcode' ), $input->param( 'branchcode' ) );
226
}
227
228
my $yearly_events = GetYearlyEvents($branch);
229
foreach my $event ( @$yearly_events ) {
230
    # Determine date format on month and day.
231
    my $day_monthdate;
232
    my $day_monthdate_sort;
233
    if (C4::Context->preference("dateformat") eq "metric") {
234
      $day_monthdate_sort = "$event->{month}-$event->{day}";
235
      $day_monthdate = "$event->{day}/$event->{month}";
236
    } elsif (C4::Context->preference("dateformat") eq "us") {
237
      $day_monthdate = "$event->{month}/$event->{day}";
238
      $day_monthdate_sort = $day_monthdate;
239
    } else {
240
      $day_monthdate = "$event->{month}-$event->{day}";
241
      $day_monthdate_sort = $day_monthdate;
242
    }
243
244
    $event->{month_day_display} = $day_monthdate;
245
    $event->{month_day_sort} = $day_monthdate_sort;
246
}
247
248
$template->param(
249
    weekly_events            => GetWeeklyEvents($branch),
250
    yearly_events            => $yearly_events,
251
    single_events            => GetSingleEvents($branch),
252
    branchloop               => \@branchloop,
253
    calendardate             => $calendardate,
254
    keydate                  => $keydate,
255
    branchcodes              => $branchcodes,
256
    branch                   => $branch,
257
    branchname               => $branchname,
258
);
259
260
# Shows the template with the real values replaced
261
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/tools/copy-holidays.pl (-39 lines)
Lines 1-39 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2012 Catalyst IT
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
23
use CGI;
24
25
use C4::Auth;
26
use C4::Output;
27
28
29
use C4::Calendar;
30
31
my $input               = new CGI;
32
my $dbh                 = C4::Context->dbh();
33
34
my $branchcode          = $input->param('branchcode');
35
my $from_branchcode     = $input->param('from_branchcode');
36
37
C4::Calendar->new(branchcode => $from_branchcode)->copy_to_branch($branchcode) if $from_branchcode && $branchcode;
38
39
print $input->redirect("/cgi-bin/koha/tools/holidays.pl?branch=".($branchcode || $from_branchcode));
(-)a/tools/exceptionHolidays.pl (-145 lines)
Lines 1-145 Link Here
1
#!/usr/bin/perl
2
3
use strict;
4
use warnings;
5
6
use CGI;
7
8
use C4::Auth;
9
use C4::Output;
10
use DateTime;
11
12
use C4::Calendar;
13
14
my $input = new CGI;
15
my $dbh = C4::Context->dbh();
16
17
my $branchcode = $input->param('showBranchName');
18
my $weekday = $input->param('showWeekday');
19
my $day = $input->param('showDay');
20
my $month = $input->param('showMonth');
21
my $year = $input->param('showYear');
22
my $day1;
23
my $month1;
24
my $year1;
25
my $title = $input->param('showTitle');
26
my $description = $input->param('showDescription');
27
my $holidaytype = $input->param('showHolidayType');
28
my $datecancelrange = $input->param('datecancelrange');
29
my $calendardate = sprintf("%04d-%02d-%02d", $year, $month, $day);
30
my $isodate = C4::Dates->new($calendardate, 'iso');
31
$calendardate = $isodate->output('syspref');
32
33
my $calendar = C4::Calendar->new(branchcode => $branchcode);
34
35
$title || ($title = '');
36
if ($description) {
37
    $description =~ s/\r/\\r/g;
38
    $description =~ s/\n/\\n/g;
39
} else {
40
    $description = '';
41
}   
42
43
# We format the date
44
my @dateend = split(/[\/-]/, $datecancelrange);
45
if (C4::Context->preference("dateformat") eq "metric") {
46
    $day1 = $dateend[0];
47
    $month1 = $dateend[1];
48
    $year1 = $dateend[2];
49
}elsif (C4::Context->preference("dateformat") eq "us") {
50
    $month1 = $dateend[0];
51
    $day1 = $dateend[1];
52
    $year1 = $dateend[2];
53
} else {
54
    $year1 = $dateend[0];
55
    $month1 = $dateend[1];
56
    $day1 = $dateend[2];
57
}
58
59
# We make an array with holiday's days
60
my @holiday_list;
61
if ($year1 && $month1 && $day1){
62
            my $first_dt = DateTime->new(year => $year, month  => $month,  day => $day);
63
            my $end_dt   = DateTime->new(year => $year1, month  => $month1,  day => $day1);
64
65
            for (my $dt = $first_dt->clone();
66
                $dt <= $end_dt;
67
                $dt->add(days => 1) )
68
                {
69
                push @holiday_list, $dt->clone();
70
                }
71
}
72
if ($input->param('showOperation') eq 'exception') {
73
	$calendar->insert_exception_holiday(day => $day,
74
										month => $month,
75
									    year => $year,
76
						                title => $title,
77
						                description => $description);
78
} elsif ($input->param('showOperation') eq 'exceptionrange' ) {
79
        if (@holiday_list){
80
            foreach my $date (@holiday_list){
81
                $calendar->insert_exception_holiday(
82
                    day         => $date->{local_c}->{day},
83
                    month       => $date->{local_c}->{month},
84
                    year       => $date->{local_c}->{year},
85
                    title       => $title,
86
                    description => $description
87
                    );
88
            }
89
        }
90
} elsif ($input->param('showOperation') eq 'edit') {
91
    if($holidaytype eq 'weekday') {
92
      $calendar->ModWeekdayholiday(weekday => $weekday,
93
                                   title => $title,
94
                                   description => $description);
95
    } elsif ($holidaytype eq 'daymonth') {
96
      $calendar->ModDaymonthholiday(day => $day,
97
                                    month => $month,
98
                                    title => $title,
99
                                    description => $description);
100
    } elsif ($holidaytype eq 'ymd') {
101
      $calendar->ModSingleholiday(day => $day,
102
                                  month => $month,
103
                                  year => $year,
104
                                  title => $title,
105
                                  description => $description);
106
    } elsif ($holidaytype eq 'exception') {
107
      $calendar->ModExceptionholiday(day => $day,
108
                                  month => $month,
109
                                  year => $year,
110
                                  title => $title,
111
                                  description => $description);
112
    }
113
} elsif ($input->param('showOperation') eq 'delete') {
114
	$calendar->delete_holiday(weekday => $weekday,
115
	                          day => $day,
116
  	                          month => $month,
117
				              year => $year);
118
}elsif ($input->param('showOperation') eq 'deleterange') {
119
    if (@holiday_list){
120
        foreach my $date (@holiday_list){
121
            $calendar->delete_holiday_range(weekday => $weekday,
122
                                            day => $date->{local_c}->{day},
123
                                            month => $date->{local_c}->{month},
124
                                            year => $date->{local_c}->{year});
125
            }
126
    }
127
}elsif ($input->param('showOperation') eq 'deleterangerepeat') {
128
    if (@holiday_list){
129
        foreach my $date (@holiday_list){
130
           $calendar->delete_holiday_range_repeatable(weekday => $weekday,
131
                                         day => $date->{local_c}->{day},
132
                                         month => $date->{local_c}->{month});
133
        }
134
    }
135
}elsif ($input->param('showOperation') eq 'deleterangerepeatexcept') {
136
    if (@holiday_list){
137
        foreach my $date (@holiday_list){
138
           $calendar->delete_exception_holiday_range(weekday => $weekday,
139
                                         day => $date->{local_c}->{day},
140
                                         month => $date->{local_c}->{month},
141
                                         year => $date->{local_c}->{year});
142
        }
143
    }
144
}
145
print $input->redirect("/cgi-bin/koha/tools/holidays.pl?branch=$branchcode&calendardate=$calendardate");
(-)a/tools/holidays.pl (-164 lines)
Lines 1-164 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 under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 2 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
16
# Suite 330, Boston, MA  02111-1307 USA
17
18
#####Sets holiday periods for each branch. Datedues will be extended if branch is closed -TG
19
use strict;
20
use warnings;
21
22
use CGI;
23
24
use C4::Auth;
25
use C4::Output;
26
27
use C4::Branch; # GetBranches
28
use C4::Calendar;
29
30
my $input = new CGI;
31
32
my $dbh = C4::Context->dbh();
33
# Get the template to use
34
my ($template, $loggedinuser, $cookie)
35
    = get_template_and_user({template_name => "tools/holidays.tmpl",
36
                             type => "intranet",
37
                             query => $input,
38
                             authnotrequired => 0,
39
                             flagsrequired => {tools => 'edit_calendar'},
40
                             debug => 1,
41
                           });
42
43
# keydate - date passed to calendar.js.  calendar.js does not process dashes within a date.
44
my $keydate;
45
# calendardate - date passed in url for human readability (syspref)
46
my $calendardate;
47
my $today = C4::Dates->new();
48
my $calendarinput = C4::Dates->new($input->param('calendardate')) || $today;
49
# if the url has an invalid date default to 'now.'
50
unless($calendardate = $calendarinput->output('syspref')) {
51
  $calendardate = $today->output('syspref');
52
}
53
unless($keydate = $calendarinput->output('iso')) {
54
  $keydate = $today->output('iso');
55
}
56
$keydate =~ s/-/\//g;
57
58
my $branch= $input->param('branch') || C4::Context->userenv->{'branch'};
59
# Set all the branches.
60
my $onlymine =
61
  (      C4::Context->preference('IndependentBranches')
62
      && C4::Context->userenv
63
      && !C4::Context->IsSuperLibrarian()
64
      && C4::Context->userenv->{branch} ? 1 : 0 );
65
if ( $onlymine ) { 
66
    $branch = C4::Context->userenv->{'branch'};
67
}
68
my $branchname = GetBranchName($branch);
69
my $branches   = GetBranches($onlymine);
70
my @branchloop;
71
for my $thisbranch (
72
    sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} }
73
    keys %{$branches} ) {
74
    push @branchloop,
75
      { value      => $thisbranch,
76
        selected   => $thisbranch eq $branch,
77
        branchname => $branches->{$thisbranch}->{'branchname'},
78
      };
79
}
80
81
# branches calculated - put branch codes in a single string so they can be passed in a form
82
my $branchcodes = join '|', keys %{$branches};
83
84
# Get all the holidays
85
86
my $calendar = C4::Calendar->new(branchcode => $branch);
87
my $week_days_holidays = $calendar->get_week_days_holidays();
88
my @week_days;
89
foreach my $weekday (keys %$week_days_holidays) {
90
# warn "WEEK DAY : $weekday";
91
    my %week_day;
92
    %week_day = (KEY => $weekday,
93
                 TITLE => $week_days_holidays->{$weekday}{title},
94
                 DESCRIPTION => $week_days_holidays->{$weekday}{description});
95
    push @week_days, \%week_day;
96
}
97
98
my $day_month_holidays = $calendar->get_day_month_holidays();
99
my @day_month_holidays;
100
foreach my $monthDay (keys %$day_month_holidays) {
101
    # Determine date format on month and day.
102
    my $day_monthdate;
103
    my $day_monthdate_sort;
104
    if (C4::Context->preference("dateformat") eq "metric") {
105
      $day_monthdate_sort = "$day_month_holidays->{$monthDay}{month}-$day_month_holidays->{$monthDay}{day}";
106
      $day_monthdate = "$day_month_holidays->{$monthDay}{day}/$day_month_holidays->{$monthDay}{month}";
107
    } elsif (C4::Context->preference("dateformat") eq "us") {
108
      $day_monthdate = "$day_month_holidays->{$monthDay}{month}/$day_month_holidays->{$monthDay}{day}";
109
      $day_monthdate_sort = $day_monthdate;
110
    } else {
111
      $day_monthdate = "$day_month_holidays->{$monthDay}{month}-$day_month_holidays->{$monthDay}{day}";
112
      $day_monthdate_sort = $day_monthdate;
113
    }
114
    my %day_month;
115
    %day_month = (KEY => $monthDay,
116
                  DATE_SORT => $day_monthdate_sort,
117
                  DATE => $day_monthdate,
118
                  TITLE => $day_month_holidays->{$monthDay}{title},
119
                  DESCRIPTION => $day_month_holidays->{$monthDay}{description});
120
    push @day_month_holidays, \%day_month;
121
}
122
123
my $exception_holidays = $calendar->get_exception_holidays();
124
my @exception_holidays;
125
foreach my $yearMonthDay (keys %$exception_holidays) {
126
    my $exceptiondate = C4::Dates->new($exception_holidays->{$yearMonthDay}{date}, "iso");
127
    my %exception_holiday;
128
    %exception_holiday = (KEY => $yearMonthDay,
129
                          DATE_SORT => $exception_holidays->{$yearMonthDay}{date},
130
                          DATE => $exceptiondate->output("syspref"),
131
                          TITLE => $exception_holidays->{$yearMonthDay}{title},
132
                          DESCRIPTION => $exception_holidays->{$yearMonthDay}{description});
133
    push @exception_holidays, \%exception_holiday;
134
}
135
136
my $single_holidays = $calendar->get_single_holidays();
137
my @holidays;
138
foreach my $yearMonthDay (keys %$single_holidays) {
139
    my $holidaydate = C4::Dates->new($single_holidays->{$yearMonthDay}{date}, "iso");
140
    my %holiday;
141
    %holiday = (KEY => $yearMonthDay,
142
                DATE_SORT => $single_holidays->{$yearMonthDay}{date},
143
                DATE => $holidaydate->output("syspref"),
144
                TITLE => $single_holidays->{$yearMonthDay}{title},
145
                DESCRIPTION => $single_holidays->{$yearMonthDay}{description});
146
    push @holidays, \%holiday;
147
}
148
149
$template->param(
150
    WEEK_DAYS_LOOP           => \@week_days,
151
    branchloop               => \@branchloop,
152
    HOLIDAYS_LOOP            => \@holidays,
153
    EXCEPTION_HOLIDAYS_LOOP  => \@exception_holidays,
154
    DAY_MONTH_HOLIDAYS_LOOP  => \@day_month_holidays,
155
    calendardate             => $calendardate,
156
    keydate                  => $keydate,
157
    branchcodes              => $branchcodes,
158
    branch                   => $branch,
159
    branchname               => $branchname,
160
    branch                   => $branch,
161
);
162
163
# Shows the template with the real values replaced
164
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/tools/newHolidays.pl (-145 lines)
Lines 1-144 Link Here
1
#!/usr/bin/perl
2
3
use strict;
4
use warnings;
5
6
use CGI;
7
8
use C4::Auth;
9
use C4::Output;
10
11
12
use C4::Calendar;
13
use DateTime;
14
15
my $input               = new CGI;
16
my $dbh                 = C4::Context->dbh();
17
18
our $branchcode          = $input->param('newBranchName');
19
my $originalbranchcode  = $branchcode;
20
our $weekday             = $input->param('newWeekday');
21
our $day                 = $input->param('newDay');
22
our $month               = $input->param('newMonth');
23
our $year                = $input->param('newYear');
24
my $day1;
25
my $month1;
26
my $year1;
27
my $dateofrange         = $input->param('dateofrange');
28
our $title               = $input->param('newTitle');
29
our $description         = $input->param('newDescription');
30
our $newoperation        = $input->param('newOperation');
31
my $allbranches         = $input->param('allBranches');
32
33
my $calendardate        = sprintf("%04d-%02d-%02d", $year, $month, $day);
34
my $isodate             = C4::Dates->new($calendardate, 'iso');
35
$calendardate           = $isodate->output('syspref');
36
37
my @dateend = split(/[\/-]/, $dateofrange);
38
if (C4::Context->preference("dateformat") eq "metric") {
39
    $day1 = $dateend[0];
40
    $month1 = $dateend[1];
41
    $year1 = $dateend[2];
42
}elsif (C4::Context->preference("dateformat") eq "us") {
43
    $month1 = $dateend[0];
44
    $day1 = $dateend[1];
45
    $year1 = $dateend[2];
46
} else {
47
    $year1 = $dateend[0];
48
    $month1 = $dateend[1];
49
    $day1 = $dateend[2];
50
}
51
$title || ($title = '');
52
if ($description) {
53
	$description =~ s/\r/\\r/g;
54
	$description =~ s/\n/\\n/g;
55
} else {
56
	$description = '';
57
}
58
59
# We make an array with holiday's days
60
our @holiday_list;
61
if ($year1 && $month1 && $day1){
62
            my $first_dt = DateTime->new(year => $year, month  => $month,  day => $day);
63
            my $end_dt   = DateTime->new(year => $year1, month  => $month1,  day => $day1);
64
65
            for (my $dt = $first_dt->clone();
66
                $dt <= $end_dt;
67
                $dt->add(days => 1) )
68
                {
69
                push @holiday_list, $dt->clone();
70
                }
71
}
72
73
if($allbranches) {
74
	my $branch;
75
	my @branchcodes = split(/\|/, $input->param('branchCodes')); 
76
	foreach $branch (@branchcodes) {
77
		add_holiday($newoperation, $branch, $weekday, $day, $month, $year, $title, $description);
78
	}
79
} else {
80
	add_holiday($newoperation, $branchcode, $weekday, $day, $month, $year, $title, $description);
81
}
82
83
print $input->redirect("/cgi-bin/koha/tools/holidays.pl?branch=$originalbranchcode&calendardate=$calendardate");
84
85
sub add_holiday {
86
	($newoperation, $branchcode, $weekday, $day, $month, $year, $title, $description) = @_;  
87
	my $calendar = C4::Calendar->new(branchcode => $branchcode);
88
89
	if ($newoperation eq 'weekday') {
90
		unless ( $weekday && ($weekday ne '') ) { 
91
			# was dow calculated by javascript?  original code implies it was supposed to be.
92
			# if not, we need it.
93
			$weekday = &Date::Calc::Day_of_Week($year, $month, $day) % 7 unless($weekday);
94
		}
95
		unless($calendar->isHoliday($day, $month, $year)) {
96
			$calendar->insert_week_day_holiday(weekday => $weekday,
97
							           title => $title,
98
							           description => $description);
99
		}
100
	} elsif ($newoperation eq 'repeatable') {
101
		unless($calendar->isHoliday($day, $month, $year)) {
102
			$calendar->insert_day_month_holiday(day => $day,
103
	                                    month => $month,
104
							            title => $title,
105
							            description => $description);
106
		}
107
	} elsif ($newoperation eq 'holiday') {
108
		unless($calendar->isHoliday($day, $month, $year)) {
109
			$calendar->insert_single_holiday(day => $day,
110
	                                 month => $month,
111
						             year => $year,
112
						             title => $title,
113
						             description => $description);
114
		}
115
116
	} elsif ( $newoperation eq 'holidayrange' ) {
117
        if (@holiday_list){
118
            foreach my $date (@holiday_list){
119
                unless ( $calendar->isHoliday( $date->{local_c}->{day}, $date->{local_c}->{month}, $date->{local_c}->{year} ) ) {
120
                    $calendar->insert_single_holiday(
121
                        day         => $date->{local_c}->{day},
122
                        month       => $date->{local_c}->{month},
123
                        year        => $date->{local_c}->{year},
124
                        title       => $title,
125
                        description => $description
126
                    );
127
                }
128
            }
129
        }
130
    } elsif ( $newoperation eq 'holidayrangerepeat' ) {
131
        if (@holiday_list){
132
            foreach my $date (@holiday_list){
133
                unless ( $calendar->isHoliday( $date->{local_c}->{day}, $date->{local_c}->{month}, $date->{local_c}->{year} ) ) {
134
                    $calendar->insert_day_month_holiday(
135
                        day         => $date->{local_c}->{day},
136
                        month       => $date->{local_c}->{month},
137
                        title       => $title,
138
                        description => $description
139
                    );
140
                }
141
            }
142
        }
143
    }
144
}
145
- 

Return to bug 11211