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

(-)a/C4/Calendar.pm (-617 / +156 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 Koha::Database;
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
}
26
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
45
  $calendar = C4::Calendar->new(branchcode => $branchcode);
46
47
Each library branch has its own Calendar.  
48
C<$branchcode> specifies which Calendar you want.
49
50
=cut
51
52
sub new {
53
    my $classname = shift @_;
54
    my %options = @_;
55
    my $self = bless({}, $classname);
56
    foreach my $optionName (keys %options) {
57
        $self->{lc($optionName)} = $options{$optionName};
58
    }
59
    defined($self->{branchcode}) or croak "No branchcode argument to new.  Should be C4::Calendar->new(branchcode => \$branchcode)";
60
    $self->_init($self->{branchcode});
61
    return $self;
62
}
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
}
118
119
=head2 get_week_days_holidays
120
121
   $week_days_holidays = $calendar->get_week_days_holidays();
122
123
Returns a hash reference to week days holidays.
124
125
=cut
126
127
sub get_week_days_holidays {
128
    my $self = shift @_;
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
141
sub get_day_month_holidays {
142
    my $self = shift @_;
143
    my $day_month_holidays = $self->{'day_month_holidays'};
144
    return $day_month_holidays;
145
}
146
147
=head2 get_exception_holidays
148
149
    $exception_holidays = $calendar->exception_holidays();
150
151
Returns a hash reference to exception holidays. This kind of days are those
152
which stands for a holiday, but you wanted to make an exception for this particular
153
date.
154
155
=cut
156
157
sub get_exception_holidays {
158
    my $self = shift @_;
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
167
Returns a hash reference to single holidays. This kind of holidays are those which
168
happend just one time.
169
57
170
=cut
58
  \@events = GetSingleEvents( $branchcode )
171
172
sub get_single_holidays {
173
    my $self = shift @_;
174
    my $single_holidays = $self->{'single_holidays'};
175
    return $single_holidays;
176
}
177
178
=head2 insert_week_day_holiday
179
180
    insert_week_day_holiday(weekday => $weekday,
181
                            title => $title,
182
                            description => $description);
183
59
184
Inserts a new week day for $self->{branchcode}.
60
Get the non-repeating events for the given library.
185
186
C<$day> Is the week day to make holiday.
187
188
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
189
190
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
191
61
192
=cut
62
=cut
193
63
194
sub insert_week_day_holiday {
64
sub GetSingleEvents {
195
    my $self = shift @_;
65
    my ( $branchcode ) = @_;
196
    my %options = @_;
66
197
67
    return C4::Context->dbh->selectall_arrayref( q{
198
    my $weekday = $options{weekday};
68
        SELECT
199
    croak "Invalid weekday $weekday" unless $weekday =~ m/^[0-6]$/;
69
            CONCAT(LPAD(year, 4, '0'), '-', LPAD(month, 2, '0'), '-', LPAD(day, 2, '0')) as event_date,
200
70
            0 as open_hour, 0 as open_minute, IF(isexception, 24, 0) as close_hour,
201
    my $dbh = C4::Context->dbh();
71
            0 as close_minute, title, description, IF(isexception, 0, 1) as closed
202
    my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ( '',?,?,NULL,NULL,?,? )"); 
72
        FROM special_holidays
203
	$insertHoliday->execute( $self->{branchcode}, $weekday, $options{title}, $options{description});
73
        WHERE branchcode = ?
204
    $self->{'week_days_holidays'}->{$weekday}{title} = $options{title};
74
    }, { Slice => {} }, $branchcode );
205
    $self->{'week_days_holidays'}->{$weekday}{description} = $options{description};
206
    return $self;
207
}
75
}
208
76
209
=head2 insert_day_month_holiday
77
=head2 GetWeeklyEvents
210
78
211
    insert_day_month_holiday(day => $day,
79
  \@events = GetWeeklyEvents( $branchcode )
212
                             month => $month,
213
                             title => $title,
214
                             description => $description);
215
80
216
Inserts a new day month holiday for $self->{branchcode}.
81
Get the weekly-repeating events for the given library.
217
218
C<$day> Is the day month to make the date to insert.
219
220
C<$month> Is month to make the date to insert.
221
222
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
223
224
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
225
82
226
=cut
83
=cut
227
84
228
sub insert_day_month_holiday {
85
sub GetWeeklyEvents {
229
    my $self = shift @_;
86
    my ( $branchcode ) = @_;
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
}
239
240
=head2 insert_single_holiday
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
87
250
C<$day> Is the day month to make the date to insert.
88
    return C4::Context->dbh->selectall_arrayref( q{
251
89
        SELECT
252
C<$month> Is month to make the date to insert.
90
            weekday, 0 as open_hour, 0 as open_minute, 0 as close_hour,
253
91
            0 as close_minute, title, description, 1 as closed
254
C<$year> Is year to make the date to insert.
92
        FROM repeatable_holidays
255
93
        WHERE branchcode = ? AND weekday IS NOT NULL
256
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
94
    }, { Slice => {} }, $branchcode );
257
258
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
259
260
=cut
261
262
sub insert_single_holiday {
263
    my $self = shift @_;
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
}
95
}
277
96
278
=head2 insert_exception_holiday
97
=head2 GetYearlyEvents
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
98
290
C<$month> Is month to make the date to insert.
99
  \@events = GetYearlyEvents( $branchcode )
291
100
292
C<$year> Is year to make the date to insert.
101
Get the yearly-repeating events for the given library.
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
102
298
=cut
103
=cut
299
104
300
sub insert_exception_holiday {
105
sub GetYearlyEvents {
301
    my $self = shift @_;
106
    my ( $branchcode ) = @_;
302
    my %options = @_;
303
304
    @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o )
305
      if $options{date} && !$options{day};
306
107
307
    my $dbh = C4::Context->dbh();
108
    return C4::Context->dbh->selectall_arrayref( q{
308
    my $isexception = 1;
109
        SELECT
309
    my $insertException = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)");
110
            month, day, 0 as open_hour, 0 as open_minute, 0 as close_hour,
310
	$insertException->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $options{description});
111
            0 as close_minute, title, description, 1 as closed
311
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
112
        FROM repeatable_holidays
312
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
113
        WHERE branchcode = ? AND weekday IS NULL
313
    return $self;
114
    }, { Slice => {} }, $branchcode );
314
}
115
}
315
116
316
=head2 ModWeekdayholiday
117
=head2 ModSingleEvent
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
118
324
C<$weekday> Is the title to update for the holiday.
119
  ModSingleEvent( $branchcode, \%info )
325
120
326
C<$description> Is the description to update for the holiday.
121
Creates or updates an event for a single date. $info->{date} should be an
122
ISO-formatted date string, and \%info should also contain the following keys:
123
open_hour, open_minute, close_hour, close_minute, title and description.
327
124
328
=cut
125
=cut
329
126
330
sub ModWeekdayholiday {
127
sub ModSingleEvent {
331
    my $self = shift @_;
128
    my ( $branchcode, $info ) = @_;
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
}
341
342
=head2 ModDaymonthholiday
343
344
    ModDaymonthholiday(day => $day,
345
                       month => $month,
346
                       title => $title,
347
                       description => $description);
348
129
349
Modifies the title and description for a day/month holiday for $self->{branchcode}.
130
    my ( $year, $month, $day ) = ( $info->{date} =~ /(\d+)-(\d+)-(\d+)/ );
131
    return unless ( $year && $month && $day );
350
132
351
C<$day> The day of the month for the update.
133
    my $dbh = C4::Context->dbh;
134
    my @args = ( ( map { $info->{$_} } qw(title description) ), $info->{close_hour} != 0, $branchcode, $year, $month, $day );
352
135
353
C<$month> The month to be used for the update.
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 );
354
143
355
C<$title> The title to be updated for the holiday.
144
    $dbh->do( q{
356
145
        INSERT
357
C<$description> The description to be update for the holiday.
146
        INTO special_holidays(title, description, isexception, branchcode, year, month, day)
358
147
        VALUES (?, ?, ?, ?, ?, ?, ?)
359
=cut
148
    }, {}, @args ) unless ( $affected > 0 );
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
}
149
}
372
150
373
=head2 ModSingleholiday
151
=head2 ModRepeatingEvent
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
385
C<$month> Is the month to make the update.
386
387
C<$year> Is the year to make the update.
388
152
389
C<$title> Is the title to update for the holiday formed by $year/$month/$day.
153
  ModRepeatingEvent( $branchcode, \%info )
390
154
391
C<$description> Is the description to update for the holiday formed by $year/$month/$day.
155
Creates or updates a weekly- or yearly-repeating event. Either $info->{weekday},
156
or $info->{month} and $info->{day} should be set, for a weekly or yearly event,
157
respectively.
392
158
393
=cut
159
=cut
394
160
395
sub ModSingleholiday {
161
sub _get_compare {
396
    my $self = shift @_;
162
    my ( $colname, $value ) = @_;
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
163
428
=cut
164
    return ' AND ' . $colname . ' ' . ( defined( $value ) ? '=' : 'IS' ) . ' ?';
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
}
165
}
442
166
443
=head2 delete_holiday
167
sub ModRepeatingEvent {
444
168
    my ( $branchcode, $info ) = @_;
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
169
454
C<$day> Is the day month to make the date to delete.
170
    my $dbh = C4::Context->dbh;
171
    my $open = ( $info->{close_hour} != 0 );
455
172
456
C<$month> Is month to make the date to delete.
173
    if ($open) {
457
174
        $dbh->do( q{
458
C<$year> Is year to make the date to delete.
175
            DELETE FROM repeatable_holidays
459
176
            WHERE branchcode = ?
460
=cut
177
        } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, $branchcode, $info->{weekday}, $info->{month}, $info->{day} );
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 {
178
    } else {
482
        $isSingleHoliday->finish; # Close the last query
179
        my @args = ( ( map { $info->{$_} } qw(title description) ), $branchcode, $info->{weekday}, $info->{month}, $info->{day} );
483
180
484
        my $isWeekdayHoliday = $dbh->prepare("SELECT id FROM repeatable_holidays WHERE branchcode = ? AND weekday = ?");
181
        # The code below relies on $dbh->do returning 0 when the update affects no rows
485
        $isWeekdayHoliday->execute($self->{branchcode}, $options{weekday});
182
        my $affected = $dbh->do( q{
486
        if ($isWeekdayHoliday->rows) {
183
            UPDATE repeatable_holidays
487
            my $id = $isWeekdayHoliday->fetchrow;
184
            SET
488
            $isWeekdayHoliday->finish; # Close the last query
185
                title = ?, description = ?
489
186
            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 = ?)");
187
        } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, @args );
491
            $updateExceptions->execute($options{weekday}, $self->{branchcode});
188
492
            $updateExceptions->finish; # Close the last query
189
        $dbh->do( q{
493
190
            INSERT
494
            my $deleteHoliday = $dbh->prepare("DELETE FROM repeatable_holidays WHERE id = ?");
191
            INTO repeatable_holidays(title, description, branchcode, weekday, month, day)
495
            $deleteHoliday->execute($id);
192
            VALUES (?, ?, ?, ?, ?, ?)
496
            delete($self->{'week_days_holidays'}->{$options{weekday}});
193
        }, {}, @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
    }
194
    }
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
}
195
}
541
196
542
=head2 delete_holiday_range_repeatable
197
=head2 DelSingleEvent
543
198
544
    delete_holiday_range_repeatable(day => $day,
199
  DelSingleEvent( $branchcode, \%info )
545
                   month => $month);
546
200
547
Delete a holiday for $self->{branchcode}.
201
Deletes an event for a single date. $info->{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
202
553
=cut
203
=cut
554
204
555
sub delete_holiday_range_repeatable {
205
sub DelSingleEvent {
556
    my $self = shift;
206
    my ( $branchcode, $info ) = @_;
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
207
566
    delete_exception_holiday_range(weekday => $weekday
208
    my ( $year, $month, $day ) = ( $info->{date} =~ /(\d+)-(\d+)-(\d+)/ );
567
                   day => $day,
209
    return unless ( $year && $month && $day );
568
                   month => $month,
569
                   year => $year);
570
210
571
Delete a holiday for $self->{branchcode}.
211
    C4::Context->dbh->do( q{
572
212
        DELETE FROM special_holidays
573
C<$day> Is the day month to make the date to delete.
213
        WHERE branchcode = ? AND year = ? AND month = ? AND day = ?
574
214
    }, {}, $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
}
215
}
589
216
590
=head2 isHoliday
217
=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
218
626
}
219
  DelRepeatingEvent( $branchcode, \%info )
627
220
628
=head2 copy_to_branch
221
Deletes a weekly- or yearly-repeating event. Either $info->{weekday}, or
629
222
$info->{month} and $info->{day} should be set, for a weekly or yearly event,
630
    $calendar->copy_to_branch($target_branch)
223
respectively.
631
224
632
=cut
225
=cut
633
226
634
sub copy_to_branch {
227
sub DelRepeatingEvent {
635
    my ($self, $target_branch) = @_;
228
    my ( $branchcode, $info ) = @_;
636
637
    croak "No target_branch" unless $target_branch;
638
229
639
    my $target_calendar = C4::Calendar->new(branchcode => $target_branch);
230
    C4::Context->dbh->do( q{
640
231
        DELETE FROM repeatable_holidays
641
    my ($y, $m, $d) = Today();
232
        WHERE branchcode = ?
642
    my $today = sprintf ISO_DATE_FORMAT, $y,$m,$d;
233
    } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, $branchcode, $info->{weekday}, $info->{month}, $info->{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
}
234
}
656
235
657
=head2 addDate
236
=head2 CopyAllEvents
658
237
659
    my ($day, $month, $year) = $calendar->addDate($date, $offset)
238
  CopyAllEvents( $from_branchcode, $to_branchcode )
660
239
661
C<$date> is a C4::Dates object representing the starting date of the interval.
240
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
241
665
=cut
242
=cut
666
243
667
sub addDate {
244
sub CopyAllEvents {
668
    my ($self, $startdate, $offset) = @_;
245
    my ( $from_branchcode, $to_branchcode ) = @_;
669
    my ($year,$month,$day) = split("-",$startdate->output('iso'));
246
670
	my $daystep = 1;
247
    C4::Context->dbh->do( q{
671
	if ($offset < 0) { # In case $offset is negative
248
        INSERT IGNORE INTO special_holidays(branchcode, year, month, day, isexception, title, description)
672
       # $offset = $offset*(-1);
249
        SELECT ?, year, month, day, isexception, title, description
673
		$daystep = -1;
250
        FROM special_holidays
674
    }
251
        WHERE branchcode = ?
675
	my $daysMode = C4::Context->preference('useDaysMode');
252
    }, {}, $to_branchcode, $from_branchcode );
676
    if ($daysMode eq 'Datedue') {
253
677
        ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset );
254
    C4::Context->dbh->do( q{
678
	 	while ($self->isHoliday($day, $month, $year)) {
255
        INSERT IGNORE INTO repeatable_holidays(branchcode, weekday, month, day, title, description)
679
            ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep);
256
        SELECT ?, weekday, month, day, title, description
680
        }
257
        FROM repeatable_holidays
681
    } elsif($daysMode eq 'Calendar') {
258
        WHERE branchcode = ?
682
        while ($offset !=  0) {
259
    }, {}, $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
}
260
}
693
261
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
262
725
1;
263
1;
726
264
Lines 729-733 __END__ Link Here
729
=head1 AUTHOR
267
=head1 AUTHOR
730
268
731
Koha Physics Library UNLP <matias_veleda@hotmail.com>
269
Koha Physics Library UNLP <matias_veleda@hotmail.com>
270
Jesse Weaver <jweaver@bywatersolutions.com>
732
271
733
=cut
272
=cut
(-)a/C4/Circulation.pm (-87 lines)
Lines 3342-3434 sub CalcDateDue { Link Here
3342
    return $datedue;
3342
    return $datedue;
3343
}
3343
}
3344
3344
3345
3346
=head2 CheckRepeatableHolidays
3347
3348
  $countrepeatable = CheckRepeatableHoliday($itemnumber,$week_day,$branchcode);
3349
3350
This function checks if the date due is a repeatable holiday
3351
3352
C<$date_due>   = returndate calculate with no day check
3353
C<$itemnumber>  = itemnumber
3354
C<$branchcode>  = localisation of issue 
3355
3356
=cut
3357
3358
sub CheckRepeatableHolidays{
3359
my($itemnumber,$week_day,$branchcode)=@_;
3360
my $dbh = C4::Context->dbh;
3361
my $query = qq|SELECT count(*)  
3362
	FROM repeatable_holidays 
3363
	WHERE branchcode=?
3364
	AND weekday=?|;
3365
my $sth = $dbh->prepare($query);
3366
$sth->execute($branchcode,$week_day);
3367
my $result=$sth->fetchrow;
3368
return $result;
3369
}
3370
3371
3372
=head2 CheckSpecialHolidays
3373
3374
  $countspecial = CheckSpecialHolidays($years,$month,$day,$itemnumber,$branchcode);
3375
3376
This function check if the date is a special holiday
3377
3378
C<$years>   = the years of datedue
3379
C<$month>   = the month of datedue
3380
C<$day>     = the day of datedue
3381
C<$itemnumber>  = itemnumber
3382
C<$branchcode>  = localisation of issue 
3383
3384
=cut
3385
3386
sub CheckSpecialHolidays{
3387
my ($years,$month,$day,$itemnumber,$branchcode) = @_;
3388
my $dbh = C4::Context->dbh;
3389
my $query=qq|SELECT count(*) 
3390
	     FROM `special_holidays`
3391
	     WHERE year=?
3392
	     AND month=?
3393
	     AND day=?
3394
             AND branchcode=?
3395
	    |;
3396
my $sth = $dbh->prepare($query);
3397
$sth->execute($years,$month,$day,$branchcode);
3398
my $countspecial=$sth->fetchrow ;
3399
return $countspecial;
3400
}
3401
3402
=head2 CheckRepeatableSpecialHolidays
3403
3404
  $countspecial = CheckRepeatableSpecialHolidays($month,$day,$itemnumber,$branchcode);
3405
3406
This function check if the date is a repeatble special holidays
3407
3408
C<$month>   = the month of datedue
3409
C<$day>     = the day of datedue
3410
C<$itemnumber>  = itemnumber
3411
C<$branchcode>  = localisation of issue 
3412
3413
=cut
3414
3415
sub CheckRepeatableSpecialHolidays{
3416
my ($month,$day,$itemnumber,$branchcode) = @_;
3417
my $dbh = C4::Context->dbh;
3418
my $query=qq|SELECT count(*) 
3419
	     FROM `repeatable_holidays`
3420
	     WHERE month=?
3421
	     AND day=?
3422
             AND branchcode=?
3423
	    |;
3424
my $sth = $dbh->prepare($query);
3425
$sth->execute($month,$day,$branchcode);
3426
my $countspecial=$sth->fetchrow ;
3427
return $countspecial;
3428
}
3429
3430
3431
3432
sub CheckValidBarcode{
3345
sub CheckValidBarcode{
3433
my ($barcode) = @_;
3346
my ($barcode) = @_;
3434
my $dbh = C4::Context->dbh;
3347
my $dbh = C4::Context->dbh;
(-)a/C4/Installer/PerlDependencies.pm (+5 lines)
Lines 712-717 our $PERL_DEPS = { Link Here
712
        'required' => '1',
712
        'required' => '1',
713
        'min_ver'  => '0.03',
713
        'min_ver'  => '0.03',
714
    },
714
    },
715
    'Template::Plugin::JavaScript' => {
716
        'usage'    => 'Core',
717
        'required' => '1',
718
        'min_ver'  => '0.02',
719
    },
715
};
720
};
716
721
717
1;
722
1;
(-)a/C4/Overdues.pm (-124 lines)
Lines 313-442 sub _get_chargeable_units { Link Here
313
}
313
}
314
314
315
315
316
=head2 GetSpecialHolidays
317
318
    &GetSpecialHolidays($date_dues,$itemnumber);
319
320
return number of special days  between date of the day and date due
321
322
C<$date_dues> is the envisaged date of book return.
323
324
C<$itemnumber> is the book's item number.
325
326
=cut
327
328
sub GetSpecialHolidays {
329
    my ( $date_dues, $itemnumber ) = @_;
330
331
    # calcul the today date
332
    my $today = join "-", &Today();
333
334
    # return the holdingbranch
335
    my $iteminfo = GetIssuesIteminfo($itemnumber);
336
337
    # use sql request to find all date between date_due and today
338
    my $dbh = C4::Context->dbh;
339
    my $query =
340
      qq|SELECT DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') as date
341
FROM `special_holidays`
342
WHERE DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') >= ?
343
AND   DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') <= ?
344
AND branchcode=?
345
|;
346
    my @result = GetWdayFromItemnumber($itemnumber);
347
    my @result_date;
348
    my $wday;
349
    my $dateinsec;
350
    my $sth = $dbh->prepare($query);
351
    $sth->execute( $date_dues, $today, $iteminfo->{'branchcode'} )
352
      ;    # FIXME: just use NOW() in SQL instead of passing in $today
353
354
    while ( my $special_date = $sth->fetchrow_hashref ) {
355
        push( @result_date, $special_date );
356
    }
357
358
    my $specialdaycount = scalar(@result_date);
359
360
    for ( my $i = 0 ; $i < scalar(@result_date) ; $i++ ) {
361
        $dateinsec = UnixDate( $result_date[$i]->{'date'}, "%o" );
362
        ( undef, undef, undef, undef, undef, undef, $wday, undef, undef ) =
363
          localtime($dateinsec);
364
        for ( my $j = 0 ; $j < scalar(@result) ; $j++ ) {
365
            if ( $wday == ( $result[$j]->{'weekday'} ) ) {
366
                $specialdaycount--;
367
            }
368
        }
369
    }
370
371
    return $specialdaycount;
372
}
373
374
=head2 GetRepeatableHolidays
375
376
    &GetRepeatableHolidays($date_dues, $itemnumber, $difference,);
377
378
return number of day closed between date of the day and date due
379
380
C<$date_dues> is the envisaged date of book return.
381
382
C<$itemnumber> is item number.
383
384
C<$difference> numbers of between day date of the day and date due
385
386
=cut
387
388
sub GetRepeatableHolidays {
389
    my ( $date_dues, $itemnumber, $difference ) = @_;
390
    my $dateinsec = UnixDate( $date_dues, "%o" );
391
    my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
392
      localtime($dateinsec);
393
    my @result = GetWdayFromItemnumber($itemnumber);
394
    my @dayclosedcount;
395
    my $j;
396
397
    for ( my $i = 0 ; $i < scalar(@result) ; $i++ ) {
398
        my $k = $wday;
399
400
        for ( $j = 0 ; $j < $difference ; $j++ ) {
401
            if ( $result[$i]->{'weekday'} == $k ) {
402
                push( @dayclosedcount, $k );
403
            }
404
            $k++;
405
            ( $k = 0 ) if ( $k eq 7 );
406
        }
407
    }
408
    return scalar(@dayclosedcount);
409
}
410
411
412
=head2 GetWayFromItemnumber
413
414
    &Getwdayfromitemnumber($itemnumber);
415
416
return the different week day from repeatable_holidays table
417
418
C<$itemnumber> is  item number.
419
420
=cut
421
422
sub GetWdayFromItemnumber {
423
    my ($itemnumber) = @_;
424
    my $iteminfo = GetIssuesIteminfo($itemnumber);
425
    my @result;
426
    my $query = qq|SELECT weekday
427
    FROM repeatable_holidays
428
    WHERE branchcode=?
429
|;
430
    my $sth = C4::Context->dbh->prepare($query);
431
432
    $sth->execute( $iteminfo->{'branchcode'} );
433
    while ( my $weekday = $sth->fetchrow_hashref ) {
434
        push( @result, $weekday );
435
    }
436
    return @result;
437
}
438
439
440
=head2 GetIssuesIteminfo
316
=head2 GetIssuesIteminfo
441
317
442
    &GetIssuesIteminfo($itemnumber);
318
    &GetIssuesIteminfo($itemnumber);
(-)a/Koha/Calendar.pm (-23 / +4 lines)
Lines 60-66 sub _init { Link Here
60
# 3.16, bug 8089 will be fixed and we can switch the caching over
60
# 3.16, bug 8089 will be fixed and we can switch the caching over
61
# to Koha::Cache.
61
# to Koha::Cache.
62
our ( $exception_holidays, $single_holidays );
62
our ( $exception_holidays, $single_holidays );
63
sub exception_holidays {
63
sub _exception_holidays {
64
    my ( $self ) = @_;
64
    my ( $self ) = @_;
65
    my $dbh = C4::Context->dbh;
65
    my $dbh = C4::Context->dbh;
66
    my $branch = $self->{branchcode};
66
    my $branch = $self->{branchcode};
Lines 88-94 sub exception_holidays { Link Here
88
    return $exception_holidays;
88
    return $exception_holidays;
89
}
89
}
90
90
91
sub single_holidays {
91
sub _single_holidays {
92
    my ( $self ) = @_;
92
    my ( $self ) = @_;
93
    my $dbh = C4::Context->dbh;
93
    my $dbh = C4::Context->dbh;
94
    my $branchcode = $self->{branchcode};
94
    my $branchcode = $self->{branchcode};
Lines 213-219 sub is_holiday { Link Here
213
213
214
    $localdt->truncate( to => 'day' );
214
    $localdt->truncate( to => 'day' );
215
215
216
    if ( $self->exception_holidays->contains($localdt) ) {
216
    if ( $self->_exception_holidays->contains($localdt) ) {
217
        # exceptions are not holidays
217
        # exceptions are not holidays
218
        return 0;
218
        return 0;
219
    }
219
    }
Lines 233-239 sub is_holiday { Link Here
233
        return 1;
233
        return 1;
234
    }
234
    }
235
235
236
    if ( $self->single_holidays->contains($localdt) ) {
236
    if ( $self->_single_holidays->contains($localdt) ) {
237
        return 1;
237
        return 1;
238
    }
238
    }
239
239
Lines 339-357 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
    my $branchcode = $self->{branchcode};
348
    $self->{single_holidays}{$branchcode} =
349
      DateTime::Set->from_datetimes( dates => \@dt );
350
    $single_holidays->{$branchcode} = $self->{single_holidays}{$branchcode};
351
352
    return;
353
}
354
355
1;
342
1;
356
__END__
343
__END__
357
344
Lines 469-480 In test mode changes the testing set of closed days to a new set with Link Here
469
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
470
allow testing of more configurations
457
allow testing of more configurations
471
458
472
=head2 add_holiday
473
474
Passed a datetime object this will add it to the calendar's list of
475
closed days. This is for testing so that we can alter the Calenfar object's
476
list of specified dates
477
478
=head1 DIAGNOSTICS
459
=head1 DIAGNOSTICS
479
460
480
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 (-536 lines)
Lines 1-536 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 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 different 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: %s").format(exception_holidays[dateString].title)];
120
        } else if ( week_days[weekDay] != null ){
121
            return [true, "repeatableweekly", _("Weekly holiday: %s").format(week_days[weekDay].title)];
122
        } else if ( day_month_holidays[dayMonth] != null ) {
123
            return [true, "repeatableyearly", _("Yearly holiday: %s").format(day_month_holidays[dayMonth].title)];
124
        } else if (holidays[dateString] != null) {
125
            return [true, "holiday", _("Single holiday: %s").format(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:  #FFFF99 none; color :  Black;  border : 1px solid #BCBCBC; }
208
td.repeatableyearly a.ui-state-default {  background:  #FFCC66 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
            <li>
274
                <label for="showDescription">Description:</label>
275
                <textarea rows="2" cols="40" id="showDescription" name="showDescription"></textarea>
276
            </li>
277
            <li class="radio"><div id="exceptionPosibility" style="position:static">
278
                <input type="radio" name="showOperation" id="showOperationExc" value="exception" /> <label for="showOperationExc">Generate an exception for this repeated holiday.</label>
279
                <a href="#" class="helptext">[?]</a>
280
                <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>
281
            </div></li>
282
            <li class="radio"><input type="radio" name="showOperation" id="showOperationExcRange" value="exceptionrange" />
283
                <label for="showOperationExcRange">Generate exceptions on a range of dates.</label>
284
                <a href="#" class="helptext">[?]</a>
285
                <div class="hint">You can make an exception on a range of dates repeated yearly.</div>
286
            </li>
287
            <li class="radio"><input type="radio" name="showOperation" id="showOperationDel" value="delete" /> <label for="showOperationDel" id="showOperationDelLabel">Delete this holiday</label>
288
                <a href="#" class="helptext">[?]</a>
289
                <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>
290
            <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>.
291
                <a href="#" class="helptext">[?]</a>
292
                <div class="hint">This will delete the single holidays rules only. The repeatable holidays and exceptions will not be deleted.</div>
293
            </li>
294
            <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>.
295
                <a href="#" class="helptext">[?]</a>
296
                <div class="hint">This will delete the repeated holidays rules only. The repeatable holidays will be deleted but not the exceptions.</div>
297
            </li>
298
            <li class="radio"><input type="radio" name="showOperation" id="showOperationDelRangeRepeatExcept" value="deleterangerepeatexcept" /> <label for="showOperationDelRangeRepeatExcept" id="showOperationDelLabelRangeRepeatExcept">Delete the exceptions on a range</label>.
299
                <a href="#" class="helptext">[?]</a>
300
                <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>
301
            </li>
302
            <li class="radio"><input type="radio" name="showOperation" id="showOperationEdit" value="edit" checked="checked" /> <label for="showOperationEdit">Edit this holiday</label>
303
                <a href="#" class="helptext">[?]</a>
304
                <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>
305
            </ol>
306
            <fieldset class="action">
307
                <input type="submit" name="submit" value="Save" />
308
                <a href="#" class="cancel" onclick=" hidePanel('showHoliday');">Cancel</a>
309
            </fieldset>
310
            </fieldset>
311
        </form>
312
    </div>
313
314
    <!-- ***************************** Panel to deal with new holidays **********************  -->
315
    <div class="panel" id="newHoliday">
316
         <form action="/cgi-bin/koha/tools/newHolidays.pl" method="post">
317
                <input type="hidden" name="branchCodes" id="branchCodes" value="[% branchcodes %]" /> 
318
            <fieldset class="brief">
319
            <h3>Add new holiday</h3>
320
            <ol>
321
            <li>
322
                <strong>Library:</strong>
323
                <span id="newBranchNameOutput"></span>
324
                <input type="hidden" id="newBranchName" name="newBranchName" />
325
            </li>
326
            <li>
327
                <strong>From date:</strong>
328
                <span id="newDaynameOutput"></span>, 
329
330
                         [% 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 %]
331
332
                <input type="hidden" id="newDayname" name="showDayname" />
333
                <input type="hidden" id="newWeekday" name="newWeekday" />
334
                <input type="hidden" id="newDay" name="newDay" />
335
                <input type="hidden" id="newMonth" name="newMonth" />
336
                <input type="hidden" id="newYear" name="newYear" />
337
            </li>
338
            <li class="dateinsert">
339
                <b>To date: </b>
340
                <input type="text" id="dateofrange" name="dateofrange" size="20" value="[% dateofrange %]" class="datepicker" />
341
            </li>
342
            <li><label for="title">Title: </label><input type="text" name="newTitle" id="title" size="35" /></li>
343
            <li><label for="newDescription">Description:</label>
344
                <textarea rows="2" cols="40" id="newDescription" name="newDescription"></textarea>
345
            </li>
346
            <li class="radio"><input type="radio" name="newOperation" id="newOperationOnce" value="holiday" checked="checked" />
347
            <label for="newOperationOnce">Holiday only on this day</label>.
348
            <a href="#" class="helptext">[?]</a>
349
            <div class="hint">Make a single holiday. For example, selecting August 1, 2012 will make it a holiday, but will not affect August 1 in other years.</div>
350
            </li>
351
            <li class="radio"><input type="radio" name="newOperation" id="newOperationDay" value="weekday" />
352
                            <label for="newOperationDay">Holiday repeated every same day of the week</label>.
353
                            <a href="#" class="helptext">[?]</a>
354
                            <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>
355
                            </li>
356
            <li class="radio"><input type="radio" name="newOperation" id="newOperationYear" value="repeatable" />
357
                            <label for="newOperationYear">Holiday repeated yearly on the same date</label>.
358
                            <a href="#" class="helptext">[?]</a>
359
                            <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 1 will make August 1 a holiday every year.</div>
360
                            </li>
361
            <li class="radio"><input type="radio" name="newOperation" id="newOperationField" value="holidayrange" />
362
                            <label for="newOperationField">Holidays on a range</label>.
363
                            <a href="#" class="helptext">[?]</a>
364
                            <div class="hint">Make a single holiday on a range. For example, selecting August 1, 2012  and August 10, 2012 will make all days between August 1 and 10 a holiday, but will not affect August 1-10 in other years.</div>
365
                            </li>
366
            <li class="radio"><input type="radio" name="newOperation" id="newOperationFieldyear" value="holidayrangerepeat" />
367
                            <label for="newOperationFieldyear">Holidays repeated yearly on a range</label>.
368
                            <a href="#" class="helptext">[?]</a>
369
                            <div class="hint">Make a single holiday on a range repeated yearly. For example, selecting August 1, 2012  and August 10, 2012 will make all days between August 1 and 10 a holiday, and will affect August 1-10 in other years.</div>
370
                            </li>
371
                <li class="radio">
372
                <input type="checkbox" name="allBranches" id="allBranches" />
373
                <label for="allBranches">Copy to all libraries</label>.
374
                <a href="#" class="helptext">[?]</a>
375
                <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>
376
                </li></ol>
377
                <fieldset class="action">
378
                    <input type="submit" name="submit" value="Save" />
379
                    <a href="#" class="cancel" onclick=" hidePanel('newHoliday');">Cancel</a>
380
                </fieldset>
381
                </fieldset>
382
         </form>
383
    </div>
384
385
    <!-- *************************************************************************************** -->
386
    <!-- ******                          END OF FLAT PANELS                               ****** -->
387
    <!-- *************************************************************************************** -->
388
389
<!-- ************************************************************************************** -->
390
<!-- ******                              MAIN SCREEN CODE                            ****** -->
391
<!-- ************************************************************************************** -->
392
<h3>Calendar information</h3>
393
<div id="jcalendar-container"></div>
394
395
<div style="margin-top: 2em;">
396
<form action="copy-holidays.pl" method="post">
397
    <input type="hidden" name="from_branchcode" value="[% branch %]" />
398
  <label for="branchcode">Copy holidays to:</label>
399
  <select id="branchcode" name="branchcode">
400
    <option value=""></option>
401
    [% FOREACH branchloo IN branchloop %]
402
    <option value="[% branchloo.value %]">[% branchloo.branchname %]</option>
403
    [% END %]
404
  </select>
405
    <input type="submit" value="Copy" />
406
</form>
407
</div>
408
409
</div>
410
<div class="yui-u">
411
<div class="help">
412
<h4>Hints</h4>
413
    <ul>
414
        <li>Search in the calendar the day you want to set as holiday.</li>
415
        <li>Click the date to add or edit a holiday.</li>
416
        <li>Enter a title and description for the holiday.</li>
417
        <li>Specify how the holiday should repeat.</li>
418
        <li>Click Save to finish.</li>
419
    </ul>
420
<h4>Key</h4>
421
    <p>
422
        <span class="key normalday">Working day</span>
423
        <span class="key holiday">Unique holiday</span>
424
        <span class="key repeatableweekly">Holiday repeating weekly</span>
425
        <span class="key repeatableyearly">Holiday repeating yearly</span>
426
        <span class="key exception">Holiday exception</span>
427
    </p>
428
</div>
429
<div id="holiday-list">
430
<!-- Exceptions First -->
431
<!--   this will probably always have the least amount of data -->
432
[% IF ( EXCEPTION_HOLIDAYS_LOOP ) %]
433
<h3>Exceptions</h3>
434
  <table id="holidayexceptions">
435
<thead><tr>
436
  <th class="exception">Date</th>
437
  <th class="exception">Title</th>
438
  <th class="exception">Description</th>
439
</tr>
440
</thead>
441
<tbody>
442
  [% FOREACH EXCEPTION_HOLIDAYS_LOO IN EXCEPTION_HOLIDAYS_LOOP %]
443
  <tr>
444
  <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>
445
  <td>[% EXCEPTION_HOLIDAYS_LOO.TITLE %]</td>
446
  <td>[% EXCEPTION_HOLIDAYS_LOO.DESCRIPTION %]</td> 
447
  </tr>
448
  [% END %] 
449
</tbody>
450
</table>
451
[% END %]
452
453
[% IF ( WEEK_DAYS_LOOP ) %]
454
<h3>Weekly - Repeatable holidays</h3>
455
<table id="holidayweeklyrepeatable">
456
<thead>
457
<tr>
458
  <th class="repeatableweekly">Day of week</th>
459
  <th class="repeatableweekly">Title</th>
460
  <th class="repeatableweekly">Description</th>
461
</tr>
462
</thead>
463
<tbody>
464
  [% FOREACH WEEK_DAYS_LOO IN WEEK_DAYS_LOOP %]
465
  <tr>
466
  <td>
467
<script type="text/javascript">
468
  document.write(weekdays[ [% WEEK_DAYS_LOO.KEY %]]);
469
</script>
470
  </td> 
471
  <td>[% WEEK_DAYS_LOO.TITLE %]</td> 
472
  <td>[% WEEK_DAYS_LOO.DESCRIPTION %]</td> 
473
  </tr>
474
  [% END %] 
475
</tbody>
476
</table>
477
[% END %]
478
479
[% IF ( DAY_MONTH_HOLIDAYS_LOOP ) %]
480
<h3>Yearly - Repeatable holidays</h3>
481
<table id="holidaysyearlyrepeatable">
482
<thead>
483
<tr>
484
  [% IF ( dateformat == "metric" ) %]
485
  <th class="repeatableyearly">Day/month</th>
486
  [% ELSE %]
487
  <th class="repeatableyearly">Month/day</th>
488
  [% END %]
489
  <th class="repeatableyearly">Title</th>
490
  <th class="repeatableyearly">Description</th>
491
</tr>
492
</thead>
493
<tbody>
494
  [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN DAY_MONTH_HOLIDAYS_LOOP %]
495
  <tr>
496
  <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT %]">[% DAY_MONTH_HOLIDAYS_LOO.DATE %]</span></td>
497
  <td>[% DAY_MONTH_HOLIDAYS_LOO.TITLE %]</td> 
498
  <td>[% DAY_MONTH_HOLIDAYS_LOO.DESCRIPTION %]</td> 
499
  </tr>
500
  [% END %] 
501
</tbody>
502
</table>
503
[% END %]
504
505
[% IF ( HOLIDAYS_LOOP ) %]
506
<h3>Unique holidays</h3>
507
<table id="holidaysunique">
508
<thead>
509
<tr>
510
  <th class="holiday">Date</th>
511
  <th class="holiday">Title</th>
512
  <th class="holiday">Description</th>
513
</tr>
514
</thead>
515
<tbody>
516
    [% FOREACH HOLIDAYS_LOO IN HOLIDAYS_LOOP %]
517
<tr>
518
  <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>
519
  <td>[% HOLIDAYS_LOO.TITLE %]</td>
520
  <td>[% HOLIDAYS_LOO.DESCRIPTION %]</td>
521
</tr>
522
  [% END %] 
523
</tbody>
524
</table>
525
[% END %]
526
</div>
527
</div>
528
</div>
529
</div>
530
</div>
531
532
<div class="yui-b noprint">
533
[% INCLUDE 'tools-menu.inc' %]
534
</div>
535
</div>
536
[% 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 312-334 sub GetWaitingHolds { Link Here
312
          sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] );
312
          sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] );
313
        $issue->{'level'} = 1;   # only one level for Hold Waiting notifications
313
        $issue->{'level'} = 1;   # only one level for Hold Waiting notifications
314
314
315
        my $days_to_subtract = 0;
315
        my $calendar = Koha::Calendar->new( branchcode => $issue->{'site'} );
316
        my $calendar = C4::Calendar->new( branchcode => $issue->{'site'} );
316
        $issue->{'days_since_waiting'} = $calendar->days_between(
317
        while (
317
            DateTime->new(
318
            $calendar->isHoliday(
318
                year => $waitingdate[0],
319
                reverse(
319
                month => $waitingdate[1],
320
                    Add_Delta_Days(
320
                day => $waitingdate[2],
321
                        $waitingdate[0], $waitingdate[1],
321
                time_zone => C4::Context->tz,
322
                        $waitingdate[2], $days_to_subtract
322
            ),
323
                    )
323
            DateTime->now(
324
                )
324
                time_zone => C4::Context->tz,
325
            )
325
            ),
326
          )
326
        );
327
        {
328
            $days_to_subtract++;
329
        }
330
        $issue->{'days_since_waiting'} =
331
          $issue->{'days_since_waiting'} - $days_to_subtract;
332
327
333
        if (
328
        if (
334
            (
329
            (
(-)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 (+86 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
use Test::More tests => 14;
4
5
use C4::Calendar;
6
use C4::Context;
7
8
my $dbh = C4::Context->dbh;
9
10
# Start transaction
11
$dbh->{AutoCommit} = 0;
12
$dbh->{RaiseError} = 1;
13
14
my %new_holiday = ( open_hour    => 0,
15
                    open_minute  => 0,
16
                    close_hour   => 0,
17
                    close_minute => 0,
18
                    title        => 'example week_day_holiday',
19
                    description  => 'This is an example week_day_holiday used for testing' );
20
21
# Weekly events
22
ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } );
23
24
my $weekly_events = GetWeeklyEvents( 'UPL' );
25
is( $weekly_events->[0]->{'title'}, $new_holiday{'title'}, 'weekly title' );
26
is( $weekly_events->[0]->{'description'}, $new_holiday{'description'}, 'weekly description' );
27
28
$new_holiday{close_hour} = 24;
29
30
ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } );
31
$weekly_events = GetWeeklyEvents( 'UPL' );
32
is( scalar @$weekly_events, 0, 'weekly modification, not insertion' );
33
34
$new_holiday{close_hour} = 0;
35
ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } );
36
37
# Yearly events
38
39
ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } );
40
41
my $yearly_events = GetYearlyEvents( 'UPL' );
42
is( $yearly_events->[0]->{'title'}, $new_holiday{'title'}, 'yearly title' );
43
is( $yearly_events->[0]->{'description'}, $new_holiday{'description'}, 'yearly description' );
44
45
$new_holiday{close_hour} = 24;
46
47
ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } );
48
$yearly_events = GetYearlyEvents( 'UPL' );
49
is( scalar @$yearly_events, 0, 'yearly modification, not insertion' );
50
51
$new_holiday{close_hour} = 0;
52
ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } );
53
54
# Single events
55
56
ModSingleEvent( 'UPL', { date => '2013-03-17', %new_holiday } );
57
58
my $single_events = GetSingleEvents( 'UPL' );
59
is( $single_events->[0]->{'title'}, $new_holiday{'title'}, 'single title' );
60
is( $single_events->[0]->{'description'}, $new_holiday{'description'}, 'single description' );
61
is( $single_events->[0]->{'closed'}, 1, 'single closed' );
62
63
$new_holiday{close_hour} = 24;
64
65
ModSingleEvent( 'UPL', { date => '2013-03-17', %new_holiday } );
66
$single_events = GetSingleEvents( 'UPL' );
67
is( scalar @$single_events, 1, 'single modification, not insertion' );
68
is( $single_events->[0]->{'closed'}, 0, 'single closed' );
69
70
71
# delete
72
73
DelRepeatingEvent( 'UPL', { weekday => 1 } );
74
$weekly_events = GetWeeklyEvents( 'UPL' );
75
is( scalar @$weekly_events, 0, 'weekly deleted' );
76
77
DelRepeatingEvent( 'UPL', { month => 6, day => 26 } );
78
$yearly_events = GetYearlyEvents( 'UPL' );
79
is( scalar @$yearly_events, 0, 'yearly deleted' );
80
81
DelSingleEvent( 'UPL', { date => '2013-03-17' } );
82
83
$single_events = GetSingleEvents( 'UPL' );
84
is( scalar @$single_events, 0, 'single deleted' );
85
86
$dbh->rollback;
(-)a/t/db_dependent/Holidays.t (-28 / +1 lines)
Lines 5-15 use DateTime; Link Here
5
use DateTime::TimeZone;
5
use DateTime::TimeZone;
6
6
7
use C4::Context;
7
use C4::Context;
8
use Koha::DateUtils;
8
use Test::More tests => 6;
9
use Test::More tests => 12;
10
9
11
BEGIN { use_ok('Koha::Calendar'); }
10
BEGIN { use_ok('Koha::Calendar'); }
12
BEGIN { use_ok('C4::Calendar'); }
13
11
14
my $dbh = C4::Context->dbh();
12
my $dbh = C4::Context->dbh();
15
# Start transaction
13
# Start transaction
Lines 19-28 $dbh->{RaiseError} = 1; Link Here
19
my $branchcode = 'MPL';
17
my $branchcode = 'MPL';
20
18
21
my $koha_calendar = Koha::Calendar->new( branchcode => $branchcode );
19
my $koha_calendar = Koha::Calendar->new( branchcode => $branchcode );
22
my $c4_calendar = C4::Calendar->new( branchcode => $branchcode );
23
20
24
isa_ok( $koha_calendar, 'Koha::Calendar', 'Koha::Calendar class returned' );
21
isa_ok( $koha_calendar, 'Koha::Calendar', 'Koha::Calendar class returned' );
25
isa_ok( $c4_calendar,   'C4::Calendar',   'C4::Calendar class returned' );
26
22
27
my $sunday = DateTime->new(
23
my $sunday = DateTime->new(
28
    year  => 2011,
24
    year  => 2011,
Lines 49-74 is( $koha_calendar->is_holiday($sunday), 1, 'Sunday is a closed day' ); Link Here
49
is( $koha_calendar->is_holiday($monday),    0, 'Monday is not a closed day' );
45
is( $koha_calendar->is_holiday($monday),    0, 'Monday is not a closed day' );
50
is( $koha_calendar->is_holiday($christmas), 1, 'Christmas is a closed day' );
46
is( $koha_calendar->is_holiday($christmas), 1, 'Christmas is a closed day' );
51
is( $koha_calendar->is_holiday($newyear), 1, 'New Years day is a closed day' );
47
is( $koha_calendar->is_holiday($newyear), 1, 'New Years day is a closed day' );
52
53
$dbh->do("DELETE FROM repeatable_holidays");
54
$dbh->do("DELETE FROM special_holidays");
55
56
my $custom_holiday = DateTime->new(
57
    year  => 2013,
58
    month => 11,
59
    day   => 12,
60
);
61
is( $koha_calendar->is_holiday($custom_holiday), 0, '2013-11-10 does not start off as a holiday' );
62
$koha_calendar->add_holiday($custom_holiday);
63
is( $koha_calendar->is_holiday($custom_holiday), 1, 'able to add holiday for testing' );
64
65
my $today = dt_from_string();
66
C4::Calendar->new( branchcode => 'CPL' )->insert_single_holiday(
67
    day         => $today->day(),
68
    month       => $today->month(),
69
    year        => $today->year(),
70
    title       => "$today",
71
    description => "$today",
72
);
73
is( Koha::Calendar->new( branchcode => 'CPL' )->is_holiday( $today ), 1, "Today is a holiday for CPL" );
74
is( Koha::Calendar->new( branchcode => 'MPL' )->is_holiday( $today ), 0, "Today is not a holiday for MPL");
(-)a/tools/calendar.pl (+268 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
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
#####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.tt",
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 my $branchcode ( @branches ) {
127
        my %event_types = (
128
            'single' => sub {
129
                ModSingleEvent( $branchcode, {
130
                    date => $date,
131
                    title => $input->param( 'title' ),
132
                    description => $input->param( 'description' ),
133
                    open_hour => $open_hour,
134
                    open_minute => $open_minute,
135
                    close_hour => $close_hour,
136
                    close_minute => $close_minute
137
                } );
138
            },
139
140
            'weekly' => sub {
141
                ModRepeatingEvent( $branchcode, {
142
                    weekday => $input->param( 'weekday' ),
143
                    title => $input->param( 'title' ),
144
                    description => $input->param( 'description' ),
145
                    open_hour => $open_hour,
146
                    open_minute => $open_minute,
147
                    close_hour => $close_hour,
148
                    close_minute => $close_minute
149
                } );
150
            },
151
152
            'yearly' => sub {
153
                ModRepeatingEvent( $branchcode, {
154
                    month => $input->param( 'month' ),
155
                    day => $input->param( 'day' ),
156
                    title => $input->param( 'title' ),
157
                    description => $input->param( 'description' ),
158
                    open_hour => $open_hour,
159
                    open_minute => $open_minute,
160
                    close_hour => $close_hour,
161
                    close_minute => $close_minute
162
                } );
163
            },
164
165
            'singlerange' => sub {
166
                foreach my $dt ( @ranged_dates ) {
167
                    ModSingleEvent( $branchcode, {
168
                        date => $dt->ymd,
169
                        title => $input->param( 'title' ),
170
                        description => $input->param( 'description' ),
171
                        open_hour => $open_hour,
172
                        open_minute => $open_minute,
173
                        close_hour => $close_hour,
174
                        close_minute => $close_minute
175
                    } );
176
                }
177
            },
178
179
            'yearlyrange' => sub {
180
                foreach my $dt ( @ranged_dates ) {
181
                    ModRepeatingEvent( $branchcode, {
182
                        month => $dt->month,
183
                        day => $dt->day,
184
                        title => $input->param( 'title' ),
185
                        description => $input->param( 'description' ),
186
                        open_hour => $open_hour,
187
                        open_minute => $open_minute,
188
                        close_hour => $close_hour,
189
                        close_minute => $close_minute
190
                    } );
191
                }
192
            },
193
        );
194
195
        # Choose from the above options
196
        $event_types{ $input->param( 'eventType' ) }->();
197
    }
198
} elsif ( $op eq 'delete' ) {
199
    my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' );
200
201
    foreach my $branchcode ( @branches ) {
202
        my %event_types = (
203
            'single' => sub {
204
                DelSingleEvent( $branchcode, { date => $date } );
205
            },
206
207
            'weekly' => sub {
208
                DelRepeatingEvent( $branchcode, { weekday => $input->param( 'weekday' ) } );
209
            },
210
211
            'yearly' => sub {
212
                DelRepeatingEvent( $branchcode, { month => $input->param( 'month' ), day => $input->param( 'day' ) } );
213
            },
214
        );
215
216
        # Choose from the above options
217
        $event_types{ $input->param( 'eventType' ) }->();
218
    }
219
} elsif ( $op eq 'deleterange' ) {
220
    foreach my $branchcode ( @branches ) {
221
        foreach my $dt ( @ranged_dates ) {
222
            DelSingleEvent( $branchcode, { date => $dt->ymd } );
223
        }
224
    }
225
} elsif ( $op eq 'deleterangerepeat' ) {
226
    foreach my $branchcode ( @branches ) {
227
        foreach my $dt ( @ranged_dates ) {
228
            DelRepeatingEvent( $branchcode, { month => $dt->month, day => $dt->day } );
229
        }
230
    }
231
} elsif ( $op eq 'copyall' ) {
232
    CopyAllEvents( $input->param( 'from_branchcode' ), $input->param( 'branchcode' ) );
233
}
234
235
my $yearly_events = GetYearlyEvents($branch);
236
foreach my $event ( @$yearly_events ) {
237
    # Determine date format on month and day.
238
    my $day_monthdate;
239
    my $day_monthdate_sort;
240
    if (C4::Context->preference("dateformat") eq "metric") {
241
      $day_monthdate_sort = "$event->{month}-$event->{day}";
242
      $day_monthdate = "$event->{day}/$event->{month}";
243
    } elsif (C4::Context->preference("dateformat") eq "us") {
244
      $day_monthdate = "$event->{month}/$event->{day}";
245
      $day_monthdate_sort = $day_monthdate;
246
    } else {
247
      $day_monthdate = "$event->{month}-$event->{day}";
248
      $day_monthdate_sort = $day_monthdate;
249
    }
250
251
    $event->{month_day_display} = $day_monthdate;
252
    $event->{month_day_sort} = $day_monthdate_sort;
253
}
254
255
$template->param(
256
    weekly_events            => GetWeeklyEvents($branch),
257
    yearly_events            => $yearly_events,
258
    single_events            => GetSingleEvents($branch),
259
    branchloop               => \@branchloop,
260
    calendardate             => $calendardate,
261
    keydate                  => $keydate,
262
    branchcodes              => $branchcodes,
263
    branch                   => $branch,
264
    branchname               => $branchname,
265
);
266
267
# Shows the template with the real values replaced
268
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.tt",
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