645 lines
19 KiB
Perl
645 lines
19 KiB
Perl
package C4::Calendar;
|
|
|
|
# This file is part of Koha.
|
|
#
|
|
# Koha is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Koha is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Koha; if not, see <https://www.gnu.org/licenses>.
|
|
|
|
use strict;
|
|
use warnings;
|
|
use vars qw(@EXPORT);
|
|
|
|
use Carp qw( croak );
|
|
use Date::Calc qw( Today );
|
|
use Koha::Library::Calendar;
|
|
|
|
use C4::Context;
|
|
use Koha::Caches;
|
|
|
|
use constant ISO_DATE_FORMAT => "%04d-%02d-%02d";
|
|
|
|
=head1 NAME
|
|
|
|
C4::Calendar::Calendar - Koha module dealing with holidays.
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use C4::Calendar::Calendar;
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This package is used to deal with holidays. Through this package, you can set
|
|
all kind of holidays for the library.
|
|
|
|
=head1 FUNCTIONS
|
|
|
|
=head2 new
|
|
|
|
$calendar = C4::Calendar->new(branchcode => $branchcode);
|
|
|
|
Each library branch has its own Calendar.
|
|
C<$branchcode> specifies which Calendar you want.
|
|
|
|
=cut
|
|
|
|
sub new {
|
|
my $classname = shift @_;
|
|
my %options = @_;
|
|
my $self = bless( {}, $classname );
|
|
foreach my $optionName ( keys %options ) {
|
|
$self->{ lc($optionName) } = $options{$optionName};
|
|
}
|
|
defined( $self->{branchcode} )
|
|
or croak "No branchcode argument to new. Should be C4::Calendar->new(branchcode => \$branchcode)";
|
|
$self->_init( $self->{branchcode} );
|
|
return $self;
|
|
}
|
|
|
|
=head2 _init
|
|
|
|
Loads calendar data from the database for the given branch.
|
|
|
|
=cut
|
|
|
|
sub _init {
|
|
my $self = shift @_;
|
|
my $branch = shift;
|
|
defined($branch) or die "No branchcode sent to _init"; # must test for defined here and above to allow ""
|
|
my $dbh = C4::Context->dbh();
|
|
|
|
my $weekly_sth = $dbh->prepare('SELECT * FROM library_weekly_closures WHERE library_id = ?');
|
|
$weekly_sth->execute($branch);
|
|
my %week_days_holidays;
|
|
while ( my $row = $weekly_sth->fetchrow_hashref ) {
|
|
my $key = $row->{weekday};
|
|
$week_days_holidays{$key}{title} = $row->{title};
|
|
$week_days_holidays{$key}{description} = $row->{description};
|
|
}
|
|
$self->{'week_days_holidays'} = \%week_days_holidays;
|
|
|
|
my $repeating_sth = $dbh->prepare('SELECT * FROM library_repeating_closures WHERE library_id = ?');
|
|
$repeating_sth->execute($branch);
|
|
my %day_month_holidays;
|
|
while ( my $row = $repeating_sth->fetchrow_hashref ) {
|
|
my $key = $row->{month} . "/" . $row->{day};
|
|
$day_month_holidays{$key}{title} = $row->{title};
|
|
$day_month_holidays{$key}{description} = $row->{description};
|
|
$day_month_holidays{$key}{day} = sprintf( "%02d", $row->{day} );
|
|
$day_month_holidays{$key}{month} = sprintf( "%02d", $row->{month} );
|
|
}
|
|
$self->{'day_month_holidays'} = \%day_month_holidays;
|
|
|
|
my $exceptions_sth =
|
|
$dbh->prepare('SELECT date, title, description FROM library_closure_exceptions WHERE library_id = ?');
|
|
$exceptions_sth->execute($branch);
|
|
my %exception_holidays;
|
|
while ( my $row = $exceptions_sth->fetchrow_hashref ) {
|
|
my ( $year, $month, $day ) = map { $_ + 0 } split( /-/, $row->{date} );
|
|
$exception_holidays{"$year/$month/$day"}{title} = $row->{title};
|
|
$exception_holidays{"$year/$month/$day"}{description} = $row->{description};
|
|
$exception_holidays{"$year/$month/$day"}{date} = $row->{date};
|
|
}
|
|
$self->{'exception_holidays'} = \%exception_holidays;
|
|
|
|
my $single_sth = $dbh->prepare('SELECT date, title, description FROM library_single_closures WHERE library_id = ?');
|
|
$single_sth->execute($branch);
|
|
my %single_holidays;
|
|
while ( my $row = $single_sth->fetchrow_hashref ) {
|
|
my ( $year, $month, $day ) = map { $_ + 0 } split( /-/, $row->{date} );
|
|
$single_holidays{"$year/$month/$day"}{title} = $row->{title};
|
|
$single_holidays{"$year/$month/$day"}{description} = $row->{description};
|
|
$single_holidays{"$year/$month/$day"}{date} = $row->{date};
|
|
}
|
|
$self->{'single_holidays'} = \%single_holidays;
|
|
return $self;
|
|
}
|
|
|
|
=head2 get_week_days_holidays
|
|
|
|
$week_days_holidays = $calendar->get_week_days_holidays();
|
|
|
|
Returns a hash reference to week days holidays.
|
|
|
|
=cut
|
|
|
|
sub get_week_days_holidays {
|
|
my $self = shift @_;
|
|
my $week_days_holidays = $self->{'week_days_holidays'};
|
|
return $week_days_holidays;
|
|
}
|
|
|
|
=head2 get_day_month_holidays
|
|
|
|
$day_month_holidays = $calendar->get_day_month_holidays();
|
|
|
|
Returns a hash reference to day month holidays.
|
|
|
|
=cut
|
|
|
|
sub get_day_month_holidays {
|
|
my $self = shift @_;
|
|
my $day_month_holidays = $self->{'day_month_holidays'};
|
|
return $day_month_holidays;
|
|
}
|
|
|
|
=head2 get_exception_holidays
|
|
|
|
$exception_holidays = $calendar->exception_holidays();
|
|
|
|
Returns a hash reference to exception holidays. This kind of days are those
|
|
which stands for a holiday, but you wanted to make an exception for this particular
|
|
date.
|
|
|
|
=cut
|
|
|
|
sub get_exception_holidays {
|
|
my $self = shift @_;
|
|
my $exception_holidays = $self->{'exception_holidays'};
|
|
return $exception_holidays;
|
|
}
|
|
|
|
=head2 get_single_holidays
|
|
|
|
$single_holidays = $calendar->get_single_holidays();
|
|
|
|
Returns a hash reference to single holidays. This kind of holidays are those which
|
|
happened just one time.
|
|
|
|
=cut
|
|
|
|
sub get_single_holidays {
|
|
my $self = shift @_;
|
|
my $single_holidays = $self->{'single_holidays'};
|
|
return $single_holidays;
|
|
}
|
|
|
|
=head2 insert_week_day_holiday
|
|
|
|
insert_week_day_holiday(weekday => $weekday,
|
|
title => $title,
|
|
description => $description);
|
|
|
|
Inserts a new week day for $self->{branchcode}.
|
|
|
|
C<$day> Is the week day to make holiday.
|
|
|
|
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
|
|
|
|
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
|
|
|
|
=cut
|
|
|
|
sub insert_week_day_holiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
Koha::Library::Calendar->new( branchcode => $self->{branchcode} )->add_weekly_closure(
|
|
{
|
|
weekday => $options{weekday}, title => $options{title}, description => $options{description},
|
|
}
|
|
);
|
|
$self->{'week_days_holidays'}->{ $options{weekday} }{title} = $options{title};
|
|
$self->{'week_days_holidays'}->{ $options{weekday} }{description} = $options{description};
|
|
return $self;
|
|
}
|
|
|
|
=head2 insert_day_month_holiday
|
|
|
|
insert_day_month_holiday(day => $day,
|
|
month => $month,
|
|
title => $title,
|
|
description => $description);
|
|
|
|
Inserts a new day month holiday for $self->{branchcode}.
|
|
|
|
C<$day> Is the day month to make the date to insert.
|
|
|
|
C<$month> Is month to make the date to insert.
|
|
|
|
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
|
|
|
|
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
|
|
|
|
=cut
|
|
|
|
sub insert_day_month_holiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
Koha::Library::Calendar->new( branchcode => $self->{branchcode} )->add_repeating_closure(
|
|
{
|
|
day => $options{day}, month => $options{month}, title => $options{title},
|
|
description => $options{description},
|
|
}
|
|
);
|
|
$self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{title} = $options{title};
|
|
$self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{description} = $options{description};
|
|
return $self;
|
|
}
|
|
|
|
=head2 insert_single_holiday
|
|
|
|
insert_single_holiday(day => $day,
|
|
month => $month,
|
|
year => $year,
|
|
title => $title,
|
|
description => $description);
|
|
|
|
Inserts a new single holiday for $self->{branchcode}.
|
|
|
|
C<$day> Is the day month to make the date to insert.
|
|
|
|
C<$month> Is month to make the date to insert.
|
|
|
|
C<$year> Is year to make the date to insert.
|
|
|
|
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
|
|
|
|
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
|
|
|
|
=cut
|
|
|
|
sub insert_single_holiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
my $date = $options{date};
|
|
unless ($date) {
|
|
$date = sprintf( ISO_DATE_FORMAT, $options{year}, $options{month}, $options{day} );
|
|
}
|
|
@options{qw(year month day)} = map { $_ + 0 } ( $date =~ m/(\d+)-(\d+)-(\d+)/ )
|
|
unless $options{day};
|
|
|
|
Koha::Library::Calendar->new( branchcode => $self->{branchcode} )->add_single_closure(
|
|
{
|
|
date => $date, title => $options{title}, description => $options{description},
|
|
}
|
|
);
|
|
|
|
$self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
|
|
$self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
|
|
|
|
return $self;
|
|
}
|
|
|
|
=head2 insert_exception_holiday
|
|
|
|
insert_exception_holiday(day => $day,
|
|
month => $month,
|
|
year => $year,
|
|
title => $title,
|
|
description => $description);
|
|
|
|
Inserts a new exception holiday for $self->{branchcode}.
|
|
|
|
C<$day> Is the day month to make the date to insert.
|
|
|
|
C<$month> Is month to make the date to insert.
|
|
|
|
C<$year> Is year to make the date to insert.
|
|
|
|
C<$title> Is the title to store for the holiday formed by $year/$month/$day.
|
|
|
|
C<$description> Is the description to store for the holiday formed by $year/$month/$day.
|
|
|
|
=cut
|
|
|
|
sub insert_exception_holiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
my $date = $options{date};
|
|
unless ($date) {
|
|
$date = sprintf( ISO_DATE_FORMAT, $options{year}, $options{month}, $options{day} );
|
|
}
|
|
@options{qw(year month day)} = map { $_ + 0 } ( $date =~ m/(\d+)-(\d+)-(\d+)/ )
|
|
unless $options{day};
|
|
|
|
Koha::Library::Calendar->new( branchcode => $self->{branchcode} )->add_exception(
|
|
{
|
|
date => $date, title => $options{title}, description => $options{description},
|
|
}
|
|
);
|
|
|
|
$self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
|
|
$self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} =
|
|
$options{description};
|
|
|
|
return $self;
|
|
}
|
|
|
|
=head2 ModWeekdayholiday
|
|
|
|
ModWeekdayholiday(weekday =>$weekday,
|
|
title => $title,
|
|
description => $description)
|
|
|
|
Modifies the title and description of a weekday for $self->{branchcode}.
|
|
|
|
C<$weekday> Is the title to update for the holiday.
|
|
|
|
C<$description> Is the description to update for the holiday.
|
|
|
|
=cut
|
|
|
|
sub ModWeekdayholiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
my $closure =
|
|
Koha::Library::Calendar::WeeklyClosures->search(
|
|
{ library_id => $self->{branchcode}, weekday => $options{weekday} } )->next;
|
|
$closure->title( $options{title} )->description( $options{description} )->store if $closure;
|
|
return $self;
|
|
}
|
|
|
|
=head2 ModDaymonthholiday
|
|
|
|
ModDaymonthholiday(day => $day,
|
|
month => $month,
|
|
title => $title,
|
|
description => $description);
|
|
|
|
Modifies the title and description for a day/month holiday for $self->{branchcode}.
|
|
|
|
C<$day> The day of the month for the update.
|
|
|
|
C<$month> The month to be used for the update.
|
|
|
|
C<$title> The title to be updated for the holiday.
|
|
|
|
C<$description> The description to be update for the holiday.
|
|
|
|
=cut
|
|
|
|
sub ModDaymonthholiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
my $closure = Koha::Library::Calendar::RepeatingClosures->search(
|
|
{ library_id => $self->{branchcode}, day => $options{day}, month => $options{month} } )->next;
|
|
$closure->title( $options{title} )->description( $options{description} )->store if $closure;
|
|
return $self;
|
|
}
|
|
|
|
=head2 ModSingleholiday
|
|
|
|
ModSingleholiday(day => $day,
|
|
month => $month,
|
|
year => $year,
|
|
title => $title,
|
|
description => $description);
|
|
|
|
Modifies the title and description for a single holiday for $self->{branchcode}.
|
|
|
|
C<$day> Is the day of the month to make the update.
|
|
|
|
C<$month> Is the month to make the update.
|
|
|
|
C<$year> Is the year to make the update.
|
|
|
|
C<$title> Is the title to update for the holiday formed by $year/$month/$day.
|
|
|
|
C<$description> Is the description to update for the holiday formed by $year/$month/$day.
|
|
|
|
=cut
|
|
|
|
sub ModSingleholiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
my $date = $options{date} || sprintf( ISO_DATE_FORMAT, $options{year}, $options{month}, $options{day} );
|
|
my $closure =
|
|
Koha::Library::Calendar::SingleClosures->search( { library_id => $self->{branchcode}, date => $date } )->next;
|
|
if ($closure) {
|
|
$closure->title( $options{title} )->description( $options{description} )->store;
|
|
}
|
|
return $self;
|
|
}
|
|
|
|
=head2 ModExceptionholiday
|
|
|
|
ModExceptionholiday(day => $day,
|
|
month => $month,
|
|
year => $year,
|
|
title => $title,
|
|
description => $description);
|
|
|
|
Modifies the title and description for an exception holiday for $self->{branchcode}.
|
|
|
|
C<$day> Is the day of the month for the holiday.
|
|
|
|
C<$month> Is the month for the holiday.
|
|
|
|
C<$year> Is the year for the holiday.
|
|
|
|
C<$title> Is the title to be modified for the holiday formed by $year/$month/$day.
|
|
|
|
C<$description> Is the description to be modified for the holiday formed by $year/$month/$day.
|
|
|
|
=cut
|
|
|
|
sub ModExceptionholiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
my $date = $options{date} || sprintf( ISO_DATE_FORMAT, $options{year}, $options{month}, $options{day} );
|
|
my $exception =
|
|
Koha::Library::Calendar::Exceptions->search( { library_id => $self->{branchcode}, date => $date } )->next;
|
|
if ($exception) {
|
|
$exception->title( $options{title} )->description( $options{description} )->store;
|
|
}
|
|
return $self;
|
|
}
|
|
|
|
=head2 delete_holiday
|
|
|
|
delete_holiday(weekday => $weekday
|
|
day => $day,
|
|
month => $month,
|
|
year => $year);
|
|
|
|
Delete a holiday for $self->{branchcode}.
|
|
|
|
C<$weekday> Is the week day to delete.
|
|
|
|
C<$day> Is the day month to make the date to delete.
|
|
|
|
C<$month> Is month to make the date to delete.
|
|
|
|
C<$year> Is year to make the date to delete.
|
|
|
|
=cut
|
|
|
|
sub delete_holiday {
|
|
my $self = shift @_;
|
|
my %options = @_;
|
|
my $cal = Koha::Library::Calendar->new( branchcode => $self->{branchcode} );
|
|
|
|
if ( $options{day} && $options{month} && $options{year} ) {
|
|
my $date = sprintf( ISO_DATE_FORMAT, $options{year}, $options{month}, $options{day} );
|
|
|
|
# Try single closure first
|
|
if ( Koha::Library::Calendar::SingleClosures->search( { library_id => $self->{branchcode}, date => $date } )
|
|
->count )
|
|
{
|
|
$cal->delete_single_closure( { date => $date } );
|
|
}
|
|
|
|
# Also remove any exception for this date
|
|
Koha::Library::Calendar::Exceptions->search( { library_id => $self->{branchcode}, date => $date } )->delete;
|
|
}
|
|
|
|
if (
|
|
defined $options{weekday}
|
|
&& Koha::Library::Calendar::WeeklyClosures->search(
|
|
{ library_id => $self->{branchcode}, weekday => $options{weekday} }
|
|
)->count
|
|
)
|
|
{
|
|
$cal->delete_weekly_closure( { weekday => $options{weekday} } );
|
|
} elsif (
|
|
$options{day}
|
|
&& $options{month}
|
|
&& Koha::Library::Calendar::RepeatingClosures->search(
|
|
{ library_id => $self->{branchcode}, day => $options{day}, month => $options{month} }
|
|
)->count
|
|
)
|
|
{
|
|
$cal->delete_repeating_closure( { day => $options{day}, month => $options{month} } );
|
|
}
|
|
|
|
return $self;
|
|
}
|
|
|
|
=head2 delete_holiday_range
|
|
|
|
delete_holiday_range(day => $day,
|
|
month => $month,
|
|
year => $year);
|
|
|
|
Delete a holiday range of dates for $self->{branchcode}.
|
|
|
|
C<$day> Is the day month to make the date to delete.
|
|
|
|
C<$month> Is month to make the date to delete.
|
|
|
|
C<$year> Is year to make the date to delete.
|
|
|
|
=cut
|
|
|
|
sub delete_holiday_range {
|
|
my $self = shift;
|
|
my %options = @_;
|
|
my $date = $options{date} || sprintf( ISO_DATE_FORMAT, $options{year}, $options{month}, $options{day} );
|
|
Koha::Library::Calendar->new( branchcode => $self->{branchcode} )->delete_single_closure( { date => $date } );
|
|
}
|
|
|
|
=head2 delete_holiday_range_repeatable
|
|
|
|
delete_holiday_range_repeatable(day => $day,
|
|
month => $month);
|
|
|
|
Delete a holiday for $self->{branchcode}.
|
|
|
|
C<$day> Is the day month to make the date to delete.
|
|
|
|
C<$month> Is month to make the date to delete.
|
|
|
|
=cut
|
|
|
|
sub delete_holiday_range_repeatable {
|
|
my $self = shift;
|
|
my %options = @_;
|
|
Koha::Library::Calendar->new( branchcode => $self->{branchcode} )
|
|
->delete_repeating_closure( { day => $options{day}, month => $options{month} } );
|
|
}
|
|
|
|
=head2 delete_exception_holiday_range
|
|
|
|
delete_exception_holiday_range(weekday => $weekday
|
|
day => $day,
|
|
month => $month,
|
|
year => $year);
|
|
|
|
Delete a holiday for $self->{branchcode}.
|
|
|
|
C<$day> Is the day month to make the date to delete.
|
|
|
|
C<$month> Is month to make the date to delete.
|
|
|
|
C<$year> Is year to make the date to delete.
|
|
|
|
=cut
|
|
|
|
sub delete_exception_holiday_range {
|
|
my $self = shift;
|
|
my %options = @_;
|
|
my $date = $options{date} || sprintf( ISO_DATE_FORMAT, $options{year}, $options{month}, $options{day} );
|
|
Koha::Library::Calendar->new( branchcode => $self->{branchcode} )->delete_exception( { date => $date } );
|
|
}
|
|
|
|
=head2 isHoliday
|
|
|
|
$isHoliday = isHoliday($day, $month $year);
|
|
|
|
C<$day> Is the day to check whether if is a holiday or not.
|
|
|
|
C<$month> Is the month to check whether if is a holiday or not.
|
|
|
|
C<$year> Is the year to check whether if is a holiday or not.
|
|
|
|
=cut
|
|
|
|
sub isHoliday {
|
|
my ( $self, $day, $month, $year ) = @_;
|
|
|
|
# FIXME - date strings are stored in non-padded metric format. should change to iso.
|
|
$month = $month + 0;
|
|
$year = $year + 0;
|
|
$day = $day + 0;
|
|
my $weekday = &Date::Calc::Day_of_Week( $year, $month, $day ) % 7;
|
|
my $weekDays = $self->get_week_days_holidays();
|
|
my $dayMonths = $self->get_day_month_holidays();
|
|
my $exceptions = $self->get_exception_holidays();
|
|
my $singles = $self->get_single_holidays();
|
|
|
|
if ( defined( $exceptions->{"$year/$month/$day"} ) ) {
|
|
return 0;
|
|
} else {
|
|
if ( ( exists( $weekDays->{$weekday} ) )
|
|
|| ( exists( $dayMonths->{"$month/$day"} ) )
|
|
|| ( exists( $singles->{"$year/$month/$day"} ) ) )
|
|
{
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
=head2 copy_to_branch
|
|
|
|
$calendar->copy_to_branch($target_branch)
|
|
|
|
=cut
|
|
|
|
sub copy_to_branch {
|
|
my ( $self, $target_branch ) = @_;
|
|
return Koha::Library::Calendar->new( branchcode => $self->{branchcode} )->copy_to($target_branch);
|
|
}
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
=head1 AUTHOR
|
|
|
|
Koha Physics Library UNLP <matias_veleda@hotmail.com>
|
|
|
|
=cut
|
|
|