From b7f8d53b35ab17253a9a2691e71554226648a3d9 Mon Sep 17 00:00:00 2001 From: Jesse Weaver Date: Tue, 28 Jan 2014 18:32:04 -0700 Subject: [PATCH] Bug 11211 - Move calculation code out of C4::Calendar This patch moves the calculation code out of C4::Calendar, replacing any references to it with Koha::Calendar. Additionally, it moves the administration interface to a single script, tools/calendar.pl. NOTE: This is intended as a bridge to bug 8133, so the UI is a bit awkward, and C4::Calendar has an API designed for adding hours to the calendar. All features should still work, and 8133 will make things better. Test plan: 1) Install the new dependency, Template::Plugin::JavaScript. 2) prove t/db_dependent/Calendar.t t/db_dependent/Holidays.t to verify that the new C4::Calendar API works correctly. 3) prove t/Calendar.t 4) Add, remove and modify events of each type using the administrative interface. In this version, changing a repeating event to "Open" deletes it. 5) Check out items to verify that the calculation code is using the events you just created. 6) If possible, verify that the two affected cronjobs still function correctly. --- C4/Calendar.pm | 773 +++++---------------- C4/Circulation.pm | 87 --- C4/Installer/PerlDependencies.pm | 5 + C4/Overdues.pm | 124 ---- Koha/Calendar.pm | 26 +- .../intranet-tmpl/prog/en/includes/tools-menu.inc | 2 +- .../prog/en/modules/tools/calendar.tt | 594 ++++++++++++++++ .../prog/en/modules/tools/holidays.tt | 536 -------------- .../prog/en/modules/tools/tools-home.tt | 2 +- misc/cronjobs/staticfines.pl | 11 +- .../thirdparty/TalkingTech_itiva_outbound.pl | 31 +- t/Calendar.t | 6 +- t/db_dependent/Calendar.t | 86 +++ t/db_dependent/Holidays.t | 15 +- tools/calendar.pl | 268 +++++++ tools/copy-holidays.pl | 39 -- tools/exceptionHolidays.pl | 145 ---- tools/holidays.pl | 164 ----- tools/newHolidays.pl | 144 ---- 19 files changed, 1138 insertions(+), 1920 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt create mode 100644 t/db_dependent/Calendar.t create mode 100755 tools/calendar.pl delete mode 100755 tools/copy-holidays.pl delete mode 100755 tools/exceptionHolidays.pl delete mode 100755 tools/holidays.pl delete mode 100755 tools/newHolidays.pl diff --git a/C4/Calendar.pm b/C4/Calendar.pm index 1e687db..dee183d 100644 --- a/C4/Calendar.pm +++ b/C4/Calendar.pm @@ -15,712 +15,250 @@ package C4::Calendar; # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, # Suite 330, Boston, MA 02111-1307 USA -use strict; -use warnings; +use Modern::Perl; use vars qw($VERSION @EXPORT); use Carp; -use Date::Calc qw( Date_to_Days Today); -use C4::Context; +use Koha::Database; + +our ( @ISA, @EXPORT ); + +BEGIN { + @ISA = qw( Exporter ); + @EXPORT = qw( + GetSingleEvents + GetWeeklyEvents + GetYearlyEvents + ModSingleEvent + ModRepeatingEvent + DelSingleEvent + DelRepeatingEvent + CopyAllEvents + ); +} use constant ISO_DATE_FORMAT => "%04d-%02d-%02d"; =head1 NAME -C4::Calendar::Calendar - Koha module dealing with holidays. +C4::Calendar - Koha module dealing with holidays. =head1 SYNOPSIS - use C4::Calendar::Calendar; + use C4::Calendar; =head1 DESCRIPTION -This package is used to deal with holidays. Through this package, you can set -all kind of holidays for the library. +This package is used to deal with hours and holidays; =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; -} - -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 $repeatable = $dbh->prepare( 'SELECT * - FROM repeatable_holidays - WHERE ( branchcode = ? ) - AND (ISNULL(weekday) = ?)' ); - $repeatable->execute($branch,0); - my %week_days_holidays; - while (my $row = $repeatable->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; - - $repeatable->execute($branch,1); - my %day_month_holidays; - while (my $row = $repeatable->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 $special = $dbh->prepare( 'SELECT day, month, year, title, description - FROM special_holidays - WHERE ( branchcode = ? ) - AND (isexception = ?)' ); - $special->execute($branch,1); - my %exception_holidays; - while (my ($day, $month, $year, $title, $description) = $special->fetchrow) { - $exception_holidays{"$year/$month/$day"}{title} = $title; - $exception_holidays{"$year/$month/$day"}{description} = $description; - $exception_holidays{"$year/$month/$day"}{date} = - sprintf(ISO_DATE_FORMAT, $year, $month, $day); - } - $self->{'exception_holidays'} = \%exception_holidays; - - $special->execute($branch,0); - my %single_holidays; - while (my ($day, $month, $year, $title, $description) = $special->fetchrow) { - $single_holidays{"$year/$month/$day"}{title} = $title; - $single_holidays{"$year/$month/$day"}{description} = $description; - $single_holidays{"$year/$month/$day"}{date} = - sprintf(ISO_DATE_FORMAT, $year, $month, $day); - } - $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 -happend just one time. +=head2 GetSingleEvents -=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); + \@events = GetSingleEvents( $branchcode ) -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. +Get the non-repeating events for the given library. =cut -sub insert_week_day_holiday { - my $self = shift @_; - my %options = @_; - - my $weekday = $options{weekday}; - croak "Invalid weekday $weekday" unless $weekday =~ m/^[0-6]$/; - - my $dbh = C4::Context->dbh(); - my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ( '',?,?,NULL,NULL,?,? )"); - $insertHoliday->execute( $self->{branchcode}, $weekday, $options{title}, $options{description}); - $self->{'week_days_holidays'}->{$weekday}{title} = $options{title}; - $self->{'week_days_holidays'}->{$weekday}{description} = $options{description}; - return $self; +sub GetSingleEvents { + my ( $branchcode ) = @_; + + return C4::Context->dbh->selectall_arrayref( q{ + SELECT + CONCAT(LPAD(year, 4, '0'), '-', LPAD(month, 2, '0'), '-', LPAD(day, 2, '0')) as event_date, + 0 as open_hour, 0 as open_minute, IF(isexception, 24, 0) as close_hour, + 0 as close_minute, title, description, IF(isexception, 0, 1) as closed + FROM special_holidays + WHERE branchcode = ? + }, { Slice => {} }, $branchcode ); } -=head2 insert_day_month_holiday +=head2 GetWeeklyEvents - insert_day_month_holiday(day => $day, - month => $month, - title => $title, - description => $description); + \@events = GetWeeklyEvents( $branchcode ) -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. +Get the weekly-repeating events for the given library. =cut -sub insert_day_month_holiday { - my $self = shift @_; - my %options = @_; - - my $dbh = C4::Context->dbh(); - my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ('', ?, NULL, ?, ?, ?,? )"); - $insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{title}, $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}. +sub GetWeeklyEvents { + my ( $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 = @_; - - @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o ) - if $options{date} && !$options{day}; - - my $dbh = C4::Context->dbh(); - my $isexception = 0; - my $insertHoliday = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)"); - $insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $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; + return C4::Context->dbh->selectall_arrayref( q{ + SELECT + weekday, 0 as open_hour, 0 as open_minute, 0 as close_hour, + 0 as close_minute, title, description, 1 as closed + FROM repeatable_holidays + WHERE branchcode = ? AND weekday IS NOT NULL + }, { Slice => {} }, $branchcode ); } -=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. +=head2 GetYearlyEvents -C<$month> Is month to make the date to insert. + \@events = GetYearlyEvents( $branchcode ) -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. +Get the yearly-repeating events for the given library. =cut -sub insert_exception_holiday { - my $self = shift @_; - my %options = @_; - - @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o ) - if $options{date} && !$options{day}; +sub GetYearlyEvents { + my ( $branchcode ) = @_; - my $dbh = C4::Context->dbh(); - my $isexception = 1; - my $insertException = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)"); - $insertException->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $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; + return C4::Context->dbh->selectall_arrayref( q{ + SELECT + month, day, 0 as open_hour, 0 as open_minute, 0 as close_hour, + 0 as close_minute, title, description, 1 as closed + FROM repeatable_holidays + WHERE branchcode = ? AND weekday IS NULL + }, { Slice => {} }, $branchcode ); } -=head2 ModWeekdayholiday - - ModWeekdayholiday(weekday =>$weekday, - title => $title, - description => $description) - -Modifies the title and description of a weekday for $self->{branchcode}. +=head2 ModSingleEvent -C<$weekday> Is the title to update for the holiday. + ModSingleEvent( $branchcode, \%info ) -C<$description> Is the description to update for the holiday. +Creates or updates an event for a single date. $info->{date} should be an +ISO-formatted date string, and \%info should also contain the following keys: +open_hour, open_minute, close_hour, close_minute, title and description. =cut -sub ModWeekdayholiday { - my $self = shift @_; - my %options = @_; - - my $dbh = C4::Context->dbh(); - my $updateHoliday = $dbh->prepare("UPDATE repeatable_holidays SET title = ?, description = ? WHERE branchcode = ? AND weekday = ?"); - $updateHoliday->execute( $options{title},$options{description},$self->{branchcode},$options{weekday}); - $self->{'week_days_holidays'}->{$options{weekday}}{title} = $options{title}; - $self->{'week_days_holidays'}->{$options{weekday}}{description} = $options{description}; - return $self; -} - -=head2 ModDaymonthholiday - - ModDaymonthholiday(day => $day, - month => $month, - title => $title, - description => $description); +sub ModSingleEvent { + my ( $branchcode, $info ) = @_; -Modifies the title and description for a day/month holiday for $self->{branchcode}. + my ( $year, $month, $day ) = ( $info->{date} =~ /(\d+)-(\d+)-(\d+)/ ); + return unless ( $year && $month && $day ); -C<$day> The day of the month for the update. + my $dbh = C4::Context->dbh; + my @args = ( ( map { $info->{$_} } qw(title description) ), $info->{close_hour} != 0, $branchcode, $year, $month, $day ); -C<$month> The month to be used for the update. + # The code below relies on $dbh->do returning 0 when the update affects no rows + my $affected = $dbh->do( q{ + UPDATE special_holidays + SET + title = ?, description = ?, isexception = ? + WHERE branchcode = ? AND year = ? AND month = ? AND day = ? + }, {}, @args ); -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 $dbh = C4::Context->dbh(); - my $updateHoliday = $dbh->prepare("UPDATE repeatable_holidays SET title = ?, description = ? WHERE month = ? AND day = ? AND branchcode = ?"); - $updateHoliday->execute( $options{title},$options{description},$options{month},$options{day},$self->{branchcode}); - $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{title} = $options{title}; - $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{description} = $options{description}; - return $self; + $dbh->do( q{ + INSERT + INTO special_holidays(title, description, isexception, branchcode, year, month, day) + VALUES (?, ?, ?, ?, ?, ?, ?) + }, {}, @args ) unless ( $affected > 0 ); } -=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. +=head2 ModRepeatingEvent -C<$title> Is the title to update for the holiday formed by $year/$month/$day. + ModRepeatingEvent( $branchcode, \%info ) -C<$description> Is the description to update for the holiday formed by $year/$month/$day. +Creates or updates a weekly- or yearly-repeating event. Either $info->{weekday}, +or $info->{month} and $info->{day} should be set, for a weekly or yearly event, +respectively. =cut -sub ModSingleholiday { - my $self = shift @_; - my %options = @_; - - my $dbh = C4::Context->dbh(); - my $isexception = 0; - my $updateHoliday = $dbh->prepare("UPDATE special_holidays SET title = ?, description = ? WHERE day = ? AND month = ? AND year = ? AND branchcode = ? AND isexception = ?"); - $updateHoliday->execute($options{title},$options{description},$options{day},$options{month},$options{year},$self->{branchcode},$isexception); - $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 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. +sub _get_compare { + my ( $colname, $value ) = @_; -=cut - -sub ModExceptionholiday { - my $self = shift @_; - my %options = @_; - - my $dbh = C4::Context->dbh(); - my $isexception = 1; - my $updateHoliday = $dbh->prepare("UPDATE special_holidays SET title = ?, description = ? WHERE day = ? AND month = ? AND year = ? AND branchcode = ? AND isexception = ?"); - $updateHoliday->execute($options{title},$options{description},$options{day},$options{month},$options{year},$self->{branchcode},$isexception); - $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; + return ' AND ' . $colname . ' ' . ( defined( $value ) ? '=' : 'IS' ) . ' ?'; } -=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. +sub ModRepeatingEvent { + my ( $branchcode, $info ) = @_; -C<$day> Is the day month to make the date to delete. + my $dbh = C4::Context->dbh; + my $open = ( $info->{close_hour} != 0 ); -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 = @_; - - # Verify what kind of holiday that day is. For example, if it is - # a repeatable holiday, this should check if there are some exception - # for that holiday rule. Otherwise, if it is a regular holiday, it´s - # ok just deleting it. - - my $dbh = C4::Context->dbh(); - my $isSingleHoliday = $dbh->prepare("SELECT id FROM special_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?) AND (year = ?)"); - $isSingleHoliday->execute($self->{branchcode}, $options{day}, $options{month}, $options{year}); - if ($isSingleHoliday->rows) { - my $id = $isSingleHoliday->fetchrow; - $isSingleHoliday->finish; # Close the last query - - my $deleteHoliday = $dbh->prepare("DELETE FROM special_holidays WHERE id = ?"); - $deleteHoliday->execute($id); - delete($self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}); + if ($open) { + $dbh->do( q{ + DELETE FROM repeatable_holidays + WHERE branchcode = ? + } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, $branchcode, $info->{weekday}, $info->{month}, $info->{day} ); } else { - $isSingleHoliday->finish; # Close the last query - - my $isWeekdayHoliday = $dbh->prepare("SELECT id FROM repeatable_holidays WHERE branchcode = ? AND weekday = ?"); - $isWeekdayHoliday->execute($self->{branchcode}, $options{weekday}); - if ($isWeekdayHoliday->rows) { - my $id = $isWeekdayHoliday->fetchrow; - $isWeekdayHoliday->finish; # Close the last query - - my $updateExceptions = $dbh->prepare("UPDATE special_holidays SET isexception = 0 WHERE (WEEKDAY(CONCAT(special_holidays.year,'-',special_holidays.month,'-',special_holidays.day)) = ?) AND (branchcode = ?)"); - $updateExceptions->execute($options{weekday}, $self->{branchcode}); - $updateExceptions->finish; # Close the last query - - my $deleteHoliday = $dbh->prepare("DELETE FROM repeatable_holidays WHERE id = ?"); - $deleteHoliday->execute($id); - delete($self->{'week_days_holidays'}->{$options{weekday}}); - } else { - $isWeekdayHoliday->finish; # Close the last query - - my $isDayMonthHoliday = $dbh->prepare("SELECT id FROM repeatable_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?)"); - $isDayMonthHoliday->execute($self->{branchcode}, $options{day}, $options{month}); - if ($isDayMonthHoliday->rows) { - my $id = $isDayMonthHoliday->fetchrow; - $isDayMonthHoliday->finish; - my $updateExceptions = $dbh->prepare("UPDATE special_holidays SET isexception = 0 WHERE (special_holidays.branchcode = ?) AND (special_holidays.day = ?) and (special_holidays.month = ?)"); - $updateExceptions->execute($self->{branchcode}, $options{day}, $options{month}); - $updateExceptions->finish; # Close the last query - - my $deleteHoliday = $dbh->prepare("DELETE FROM repeatable_holidays WHERE (id = ?)"); - $deleteHoliday->execute($id); - delete($self->{'day_month_holidays'}->{"$options{month}/$options{day}"}); - } - } + my @args = ( ( map { $info->{$_} } qw(title description) ), $branchcode, $info->{weekday}, $info->{month}, $info->{day} ); + + # The code below relies on $dbh->do returning 0 when the update affects no rows + my $affected = $dbh->do( q{ + UPDATE repeatable_holidays + SET + title = ?, description = ? + WHERE branchcode = ? + } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, @args ); + + $dbh->do( q{ + INSERT + INTO repeatable_holidays(title, description, branchcode, weekday, month, day) + VALUES (?, ?, ?, ?, ?, ?) + }, {}, @args ) unless ( $affected > 0 ); } - 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 $dbh = C4::Context->dbh(); - my $sth = $dbh->prepare("DELETE FROM special_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?) AND (year = ?)"); - $sth->execute($self->{branchcode}, $options{day}, $options{month}, $options{year}); } -=head2 delete_holiday_range_repeatable +=head2 DelSingleEvent - delete_holiday_range_repeatable(day => $day, - month => $month); + DelSingleEvent( $branchcode, \%info ) -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. +Deletes an event for a single date. $info->{date} should be an ISO-formatted date string. =cut -sub delete_holiday_range_repeatable { - my $self = shift; - my %options = @_; - - my $dbh = C4::Context->dbh(); - my $sth = $dbh->prepare("DELETE FROM repeatable_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?)"); - $sth->execute($self->{branchcode}, $options{day}, $options{month}); -} - -=head2 delete_exception_holiday_range +sub DelSingleEvent { + my ( $branchcode, $info ) = @_; - delete_exception_holiday_range(weekday => $weekday - day => $day, - month => $month, - year => $year); + my ( $year, $month, $day ) = ( $info->{date} =~ /(\d+)-(\d+)-(\d+)/ ); + return unless ( $year && $month && $day ); -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 $dbh = C4::Context->dbh(); - my $sth = $dbh->prepare("DELETE FROM special_holidays WHERE (branchcode = ?) AND (isexception = 1) AND (day = ?) AND (month = ?) AND (year = ?)"); - $sth->execute($self->{branchcode}, $options{day}, $options{month}, $options{year}); + C4::Context->dbh->do( q{ + DELETE FROM special_holidays + WHERE branchcode = ? AND year = ? AND month = ? AND day = ? + }, {}, $branchcode, $year, $month, $day ); } -=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. - # FIXME - should change arguments to accept C4::Dates object - $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 DelRepeatingEvent -} + DelRepeatingEvent( $branchcode, \%info ) -=head2 copy_to_branch - - $calendar->copy_to_branch($target_branch) +Deletes a weekly- or yearly-repeating event. Either $info->{weekday}, or +$info->{month} and $info->{day} should be set, for a weekly or yearly event, +respectively. =cut -sub copy_to_branch { - my ($self, $target_branch) = @_; - - croak "No target_branch" unless $target_branch; +sub DelRepeatingEvent { + my ( $branchcode, $info ) = @_; - my $target_calendar = C4::Calendar->new(branchcode => $target_branch); - - my ($y, $m, $d) = Today(); - my $today = sprintf ISO_DATE_FORMAT, $y,$m,$d; - - my $wdh = $self->get_week_days_holidays; - $target_calendar->insert_week_day_holiday( weekday => $_, %{ $wdh->{$_} } ) - foreach keys %$wdh; - $target_calendar->insert_day_month_holiday(%$_) - foreach values %{ $self->get_day_month_holidays }; - $target_calendar->insert_exception_holiday(%$_) - foreach grep { $_->{date} gt $today } values %{ $self->get_exception_holidays }; - $target_calendar->insert_single_holiday(%$_) - foreach grep { $_->{date} gt $today } values %{ $self->get_single_holidays }; - - return 1; + C4::Context->dbh->do( q{ + DELETE FROM repeatable_holidays + WHERE branchcode = ? + } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, $branchcode, $info->{weekday}, $info->{month}, $info->{day} ); } -=head2 addDate +=head2 CopyAllEvents - my ($day, $month, $year) = $calendar->addDate($date, $offset) + CopyAllEvents( $from_branchcode, $to_branchcode ) -C<$date> is a C4::Dates object representing the starting date of the interval. - -C<$offset> Is the number of days that this function has to count from $date. +Copies all events from one branch to another. =cut -sub addDate { - my ($self, $startdate, $offset) = @_; - my ($year,$month,$day) = split("-",$startdate->output('iso')); - my $daystep = 1; - if ($offset < 0) { # In case $offset is negative - # $offset = $offset*(-1); - $daystep = -1; - } - my $daysMode = C4::Context->preference('useDaysMode'); - if ($daysMode eq 'Datedue') { - ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset ); - while ($self->isHoliday($day, $month, $year)) { - ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep); - } - } elsif($daysMode eq 'Calendar') { - while ($offset != 0) { - ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep); - if (!($self->isHoliday($day, $month, $year))) { - $offset = $offset - $daystep; - } - } - } else { ## ($daysMode eq 'Days') - ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset ); - } - return(C4::Dates->new( sprintf(ISO_DATE_FORMAT,$year,$month,$day),'iso')); +sub CopyAllEvents { + my ( $from_branchcode, $to_branchcode ) = @_; + + C4::Context->dbh->do( q{ + INSERT IGNORE INTO special_holidays(branchcode, year, month, day, isexception, title, description) + SELECT ?, year, month, day, isexception, title, description + FROM special_holidays + WHERE branchcode = ? + }, {}, $to_branchcode, $from_branchcode ); + + C4::Context->dbh->do( q{ + INSERT IGNORE INTO repeatable_holidays(branchcode, weekday, month, day, title, description) + SELECT ?, weekday, month, day, title, description + FROM repeatable_holidays + WHERE branchcode = ? + }, {}, $to_branchcode, $from_branchcode ); } -=head2 daysBetween - - my $daysBetween = $calendar->daysBetween($startdate, $enddate) - -C<$startdate> and C<$enddate> are C4::Dates objects that define the interval. - -Returns the number of non-holiday days in the interval. -useDaysMode syspref has no effect here. -=cut - -sub daysBetween { - my $self = shift or return; - my $startdate = shift or return; - my $enddate = shift or return; - my ($yearFrom,$monthFrom,$dayFrom) = split("-",$startdate->output('iso')); - my ($yearTo, $monthTo, $dayTo ) = split("-", $enddate->output('iso')); - if (Date_to_Days($yearFrom,$monthFrom,$dayFrom) > Date_to_Days($yearTo,$monthTo,$dayTo)) { - return 0; - # we don't go backwards ( FIXME - handle this error better ) - } - my $count = 0; - while (1) { - ($yearFrom != $yearTo or $monthFrom != $monthTo or $dayFrom != $dayTo) or last; # if they all match, it's the last day - unless ($self->isHoliday($dayFrom, $monthFrom, $yearFrom)) { - $count++; - } - ($yearFrom, $monthFrom, $dayFrom) = &Date::Calc::Add_Delta_Days($yearFrom, $monthFrom, $dayFrom, 1); - } - return($count); -} 1; @@ -729,5 +267,6 @@ __END__ =head1 AUTHOR Koha Physics Library UNLP +Jesse Weaver =cut diff --git a/C4/Circulation.pm b/C4/Circulation.pm index dc7334a..3ace11c 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -3334,93 +3334,6 @@ sub CalcDateDue { return $datedue; } - -=head2 CheckRepeatableHolidays - - $countrepeatable = CheckRepeatableHoliday($itemnumber,$week_day,$branchcode); - -This function checks if the date due is a repeatable holiday - -C<$date_due> = returndate calculate with no day check -C<$itemnumber> = itemnumber -C<$branchcode> = localisation of issue - -=cut - -sub CheckRepeatableHolidays{ -my($itemnumber,$week_day,$branchcode)=@_; -my $dbh = C4::Context->dbh; -my $query = qq|SELECT count(*) - FROM repeatable_holidays - WHERE branchcode=? - AND weekday=?|; -my $sth = $dbh->prepare($query); -$sth->execute($branchcode,$week_day); -my $result=$sth->fetchrow; -return $result; -} - - -=head2 CheckSpecialHolidays - - $countspecial = CheckSpecialHolidays($years,$month,$day,$itemnumber,$branchcode); - -This function check if the date is a special holiday - -C<$years> = the years of datedue -C<$month> = the month of datedue -C<$day> = the day of datedue -C<$itemnumber> = itemnumber -C<$branchcode> = localisation of issue - -=cut - -sub CheckSpecialHolidays{ -my ($years,$month,$day,$itemnumber,$branchcode) = @_; -my $dbh = C4::Context->dbh; -my $query=qq|SELECT count(*) - FROM `special_holidays` - WHERE year=? - AND month=? - AND day=? - AND branchcode=? - |; -my $sth = $dbh->prepare($query); -$sth->execute($years,$month,$day,$branchcode); -my $countspecial=$sth->fetchrow ; -return $countspecial; -} - -=head2 CheckRepeatableSpecialHolidays - - $countspecial = CheckRepeatableSpecialHolidays($month,$day,$itemnumber,$branchcode); - -This function check if the date is a repeatble special holidays - -C<$month> = the month of datedue -C<$day> = the day of datedue -C<$itemnumber> = itemnumber -C<$branchcode> = localisation of issue - -=cut - -sub CheckRepeatableSpecialHolidays{ -my ($month,$day,$itemnumber,$branchcode) = @_; -my $dbh = C4::Context->dbh; -my $query=qq|SELECT count(*) - FROM `repeatable_holidays` - WHERE month=? - AND day=? - AND branchcode=? - |; -my $sth = $dbh->prepare($query); -$sth->execute($month,$day,$branchcode); -my $countspecial=$sth->fetchrow ; -return $countspecial; -} - - - sub CheckValidBarcode{ my ($barcode) = @_; my $dbh = C4::Context->dbh; diff --git a/C4/Installer/PerlDependencies.pm b/C4/Installer/PerlDependencies.pm index ad1f5a6..fe39565 100644 --- a/C4/Installer/PerlDependencies.pm +++ b/C4/Installer/PerlDependencies.pm @@ -742,6 +742,11 @@ our $PERL_DEPS = { 'required' => '0', 'min_ver' => '5.836', }, + 'Template::Plugin::JavaScript' => { + 'usage' => 'Core', + 'required' => '1', + 'min_ver' => '0.02', + }, }; 1; diff --git a/C4/Overdues.pm b/C4/Overdues.pm index b3ec066..10e740b 100644 --- a/C4/Overdues.pm +++ b/C4/Overdues.pm @@ -313,130 +313,6 @@ sub _get_chargeable_units { } -=head2 GetSpecialHolidays - - &GetSpecialHolidays($date_dues,$itemnumber); - -return number of special days between date of the day and date due - -C<$date_dues> is the envisaged date of book return. - -C<$itemnumber> is the book's item number. - -=cut - -sub GetSpecialHolidays { - my ( $date_dues, $itemnumber ) = @_; - - # calcul the today date - my $today = join "-", &Today(); - - # return the holdingbranch - my $iteminfo = GetIssuesIteminfo($itemnumber); - - # use sql request to find all date between date_due and today - my $dbh = C4::Context->dbh; - my $query = - qq|SELECT DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') as date -FROM `special_holidays` -WHERE DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') >= ? -AND DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') <= ? -AND branchcode=? -|; - my @result = GetWdayFromItemnumber($itemnumber); - my @result_date; - my $wday; - my $dateinsec; - my $sth = $dbh->prepare($query); - $sth->execute( $date_dues, $today, $iteminfo->{'branchcode'} ) - ; # FIXME: just use NOW() in SQL instead of passing in $today - - while ( my $special_date = $sth->fetchrow_hashref ) { - push( @result_date, $special_date ); - } - - my $specialdaycount = scalar(@result_date); - - for ( my $i = 0 ; $i < scalar(@result_date) ; $i++ ) { - $dateinsec = UnixDate( $result_date[$i]->{'date'}, "%o" ); - ( undef, undef, undef, undef, undef, undef, $wday, undef, undef ) = - localtime($dateinsec); - for ( my $j = 0 ; $j < scalar(@result) ; $j++ ) { - if ( $wday == ( $result[$j]->{'weekday'} ) ) { - $specialdaycount--; - } - } - } - - return $specialdaycount; -} - -=head2 GetRepeatableHolidays - - &GetRepeatableHolidays($date_dues, $itemnumber, $difference,); - -return number of day closed between date of the day and date due - -C<$date_dues> is the envisaged date of book return. - -C<$itemnumber> is item number. - -C<$difference> numbers of between day date of the day and date due - -=cut - -sub GetRepeatableHolidays { - my ( $date_dues, $itemnumber, $difference ) = @_; - my $dateinsec = UnixDate( $date_dues, "%o" ); - my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = - localtime($dateinsec); - my @result = GetWdayFromItemnumber($itemnumber); - my @dayclosedcount; - my $j; - - for ( my $i = 0 ; $i < scalar(@result) ; $i++ ) { - my $k = $wday; - - for ( $j = 0 ; $j < $difference ; $j++ ) { - if ( $result[$i]->{'weekday'} == $k ) { - push( @dayclosedcount, $k ); - } - $k++; - ( $k = 0 ) if ( $k eq 7 ); - } - } - return scalar(@dayclosedcount); -} - - -=head2 GetWayFromItemnumber - - &Getwdayfromitemnumber($itemnumber); - -return the different week day from repeatable_holidays table - -C<$itemnumber> is item number. - -=cut - -sub GetWdayFromItemnumber { - my ($itemnumber) = @_; - my $iteminfo = GetIssuesIteminfo($itemnumber); - my @result; - my $query = qq|SELECT weekday - FROM repeatable_holidays - WHERE branchcode=? -|; - my $sth = C4::Context->dbh->prepare($query); - - $sth->execute( $iteminfo->{'branchcode'} ); - while ( my $weekday = $sth->fetchrow_hashref ) { - push( @result, $weekday ); - } - return @result; -} - - =head2 GetIssuesIteminfo &GetIssuesIteminfo($itemnumber); diff --git a/Koha/Calendar.pm b/Koha/Calendar.pm index 276c7ce..7f4b9a5 100644 --- a/Koha/Calendar.pm +++ b/Koha/Calendar.pm @@ -60,7 +60,7 @@ sub _init { # 3.16, bug 8089 will be fixed and we can switch the caching over # to Koha::Cache. our ( $exception_holidays, $single_holidays ); -sub exception_holidays { +sub _exception_holidays { my ( $self ) = @_; my $dbh = C4::Context->dbh; my $branch = $self->{branchcode}; @@ -88,7 +88,7 @@ sub exception_holidays { return $exception_holidays; } -sub single_holidays { +sub _single_holidays { my ( $self ) = @_; my $dbh = C4::Context->dbh; my $branch = $self->{branchcode}; @@ -213,7 +213,7 @@ sub is_holiday { $localdt->truncate( to => 'day' ); - if ( $self->exception_holidays->contains($localdt) ) { + if ( $self->_exception_holidays->contains($localdt) ) { # exceptions are not holidays return 0; } @@ -233,7 +233,7 @@ sub is_holiday { return 1; } - if ( $self->single_holidays->contains($localdt) ) { + if ( $self->_single_holidays->contains($localdt) ) { return 1; } @@ -339,18 +339,6 @@ sub clear_weekly_closed_days { return; } -sub add_holiday { - my $self = shift; - my $new_dt = shift; - my @dt = $self->single_holidays->as_list; - push @dt, $new_dt; - $self->{single_holidays} = - DateTime::Set->from_datetimes( dates => \@dt ); - $single_holidays = $self->{single_holidays}; - - return; -} - 1; __END__ @@ -468,12 +456,6 @@ In test mode changes the testing set of closed days to a new set with no closed days. TODO passing an array of closed days to this would allow testing of more configurations -=head2 add_holiday - -Passed a datetime object this will add it to the calendar's list of -closed days. This is for testing so that we can alter the Calenfar object's -list of specified dates - =head1 DIAGNOSTICS Will croak if not passed a branchcode in new diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc index 45d9b4e..13dd061 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc @@ -87,7 +87,7 @@
Additional tools
    [% IF ( CAN_user_tools_edit_calendar ) %] -
  • Calendar
  • +
  • Calendar
  • [% END %] [% IF ( CAN_user_tools_manage_csv_profiles ) %]
  • CSV profiles
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt new file mode 100644 index 0000000..b952253 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt @@ -0,0 +1,594 @@ +[% USE 'JavaScript' %] +[% USE 'KohaDates' %] +[% INCLUDE 'doc-head-open.inc' %] +Koha › Tools › [% branchname %] Calendar +[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'calendar.inc' %] + +[% INCLUDE 'datatables.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'cat-search.inc' %] + + + +
    + +
    +
    +
    +

    [% branchname %] Calendar

    +
    +
    + + + + + + + + +
    +
    + +
    +

    Edit this event

    + +
      +
    1. + Library: + +
    2. +
    3. + From Date: + , + + [% IF ( dateformat == "us" ) %]//[% ELSIF ( dateformat == "metric" ) %]//[% ELSE %]//[% END %] + + + + + +
    4. +
    5. + To Date : + +
    6. +
    7. + + +
    8. + +
    9. + + + + +
    10. + [?] +
      This will delete this event rule. +
    11. . + [?] +
      This will delete the single events only. The repeatable events will not be deleted.
      +
    12. +
    13. . + [?] +
      This will delete the yearly repeated events only.
      +
    14. +
    15. + [?] +
      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.
    16. +
    +
    + + Cancel +
    +
    +
    +
    + + +
    +
    + + +
    +

    Add new event

    + +
      +
    1. + Library: + + +
    2. +
    3. + From date: + , + + [% IF ( dateformat == "us" ) %]//[% ELSIF ( dateformat == "metric" ) %]//[% ELSE %]//[% END %] + + + + + +
    4. +
    5. + To date : + +
    6. +
    7. + + +
    8. + +
    9. +
    10. + +
    11. +
    12. + . + [?] +
      Make a single event. For example, selecting August 1st, 2012 will not affect August 1st in other years.
      +
    13. +
    14. + . + [?] +
      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.
      +
    15. +
    16. + . + [?] +
      Make this day of the year an event, every year. For example, selecting August 1st will set the hours for August 1st every year.
      +
    17. +
    18. + . + [?] +
      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.
      +
    19. +
    20. + . + [?] +
      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.
      +
    21. +
    22. + + . + [?] +
      If checked, this event will be copied to all libraries. If the event already exists for a library, no change is made.
      +
    +
    + + Cancel +
    +
    +
    +
    + + + + + + + + +

    Calendar information

    +
    + +
    +
    + + + + + +
    +
    + +
    +
    +
    +

    Hints

    +
      +
    • Search in the calendar the day you want to set as event.
    • +
    • Click the date to add or edit a event.
    • +
    • Enter a title and description for the event.
    • +
    • Specify how the event should repeat.
    • +
    • Click Save to finish.
    • +
    +

    Key

    +

    + Working day + Unique event + Event repeating weekly + Event repeating yearly +

    +
    +
    +[% IF ( weekly_events ) %] +

    Weekly - Repeatable Events

    + + + + + + + + + + + [% FOREACH event IN weekly_events %] + + + + + + + [% END %] + +
    Day of weekTitleDescriptionHours
    + + [% event.title %][% event.description %] + [% IF event.closed %] + Closed + [% ELSIF event.close_hour == 24 %] + Open + [% ELSE %] + [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - + [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %] + [% END %] +
    +[% END %] + +[% IF ( yearly_events ) %] +

    Yearly - Repeatable Events

    + + + + [% IF ( dateformat == "metric" ) %] + + [% ELSE %] + + [% END %] + + + + + + + [% FOREACH event IN yearly_events %] + + + + + + + [% END %] + +
    Day/MonthMonth/DayTitleDescriptionHours
    [% event.month_day_sort %][% event.title %][% event.description %] + [% IF event.closed %] + Closed + [% ELSIF event.close_hour == 24 %] + Open + [% ELSE %] + [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - + [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %] + [% END %] +
    +[% END %] + +[% IF ( single_events ) %] +

    Single Events

    + + + + + + + + + + + [% FOREACH event IN single_events %] + + + + + + + [% END %] + +
    DateTitleDescriptionHours
    [% event.event_date | $KohaDates %][% event.title %][% event.description %] + [% IF event.closed %] + Closed + [% ELSIF event.close_hour == 24 %] + Open + [% ELSE %] + [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - + [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %] + [% END %] +
    +[% END %] +
    +
    +
    +
    +
    + +
    +[% INCLUDE 'tools-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt deleted file mode 100644 index 57193a5..0000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt +++ /dev/null @@ -1,536 +0,0 @@ -[% INCLUDE 'doc-head-open.inc' %] -Koha › Tools › [% branchname %] calendar -[% INCLUDE 'doc-head-close.inc' %] -[% INCLUDE 'calendar.inc' %] - -[% INCLUDE 'datatables.inc' %] - - - - -[% INCLUDE 'header.inc' %] -[% INCLUDE 'cat-search.inc' %] - - - -
    - -
    -
    -
    -

    [% branchname %] calendar

    -
    -
    - - - - - - - - -
    -
    - -
    -

    Edit this holiday

    - -
      -
    1. - Library: - -
    2. -
    3. - From date: - , - - [% IF ( dateformat == "us" ) %]//[% ELSIF ( dateformat == "metric" ) %]//[% ELSE %]//[% END %] - - - - - - -
    4. -
    5. - To Date : - -
    6. -
    7. - -
    8. - - -
    9. -
    10. - - [?] -
      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.
      -
    11. -
    12. - - [?] -
      You can make an exception on a range of dates repeated yearly.
      -
    13. -
    14. - [?] -
      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.
    15. -
    16. . - [?] -
      This will delete the single holidays rules only. The repeatable holidays and exceptions will not be deleted.
      -
    17. -
    18. . - [?] -
      This will delete the repeated holidays rules only. The repeatable holidays will be deleted but not the exceptions.
      -
    19. -
    20. . - [?] -
      This will delete the exceptions inside a given range. Be careful about your scope range if it is oversized you could slow down Koha.
      -
    21. -
    22. - [?] -
      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.
    23. -
    -
    - - Cancel -
    -
    -
    -
    - - -
    -
    - -
    -

    Add new holiday

    -
      -
    1. - Library: - - -
    2. -
    3. - From date: - , - - [% IF ( dateformat == "us" ) %]//[% ELSIF ( dateformat == "metric" ) %]//[% ELSE %]//[% END %] - - - - - - -
    4. -
    5. - To date: - -
    6. -
    7. -
    8. - -
    9. -
    10. - . - [?] -
      Make a single holiday. For example, selecting August 1, 2012 will make it a holiday, but will not affect August 1 in other years.
      -
    11. -
    12. - . - [?] -
      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.
      -
    13. -
    14. - . - [?] -
      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.
      -
    15. -
    16. - . - [?] -
      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.
      -
    17. -
    18. - . - [?] -
      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.
      -
    19. -
    20. - - . - [?] -
      If checked, this holiday will be copied to all libraries. If the holiday already exists for a library, no change is made.
      -
    -
    - - Cancel -
    -
    -
    -
    - - - - - - - - -

    Calendar information

    -
    - -
    -
    - - - - -
    -
    - -
    -
    -
    -

    Hints

    -
      -
    • Search in the calendar the day you want to set as holiday.
    • -
    • Click the date to add or edit a holiday.
    • -
    • Enter a title and description for the holiday.
    • -
    • Specify how the holiday should repeat.
    • -
    • Click Save to finish.
    • -
    -

    Key

    -

    - Working day - Unique holiday - Holiday repeating weekly - Holiday repeating yearly - Holiday exception -

    -
    -
    - - -[% IF ( EXCEPTION_HOLIDAYS_LOOP ) %] -

    Exceptions

    - - - - - - - - - [% FOREACH EXCEPTION_HOLIDAYS_LOO IN EXCEPTION_HOLIDAYS_LOOP %] - - - - - - [% END %] - -
    DateTitleDescription
    [% EXCEPTION_HOLIDAYS_LOO.DATE %][% EXCEPTION_HOLIDAYS_LOO.TITLE %][% EXCEPTION_HOLIDAYS_LOO.DESCRIPTION %]
    -[% END %] - -[% IF ( WEEK_DAYS_LOOP ) %] -

    Weekly - Repeatable holidays

    - - - - - - - - - - [% FOREACH WEEK_DAYS_LOO IN WEEK_DAYS_LOOP %] - - - - - - [% END %] - -
    Day of weekTitleDescription
    - - [% WEEK_DAYS_LOO.TITLE %][% WEEK_DAYS_LOO.DESCRIPTION %]
    -[% END %] - -[% IF ( DAY_MONTH_HOLIDAYS_LOOP ) %] -

    Yearly - Repeatable holidays

    - - - - [% IF ( dateformat == "metric" ) %] - - [% ELSE %] - - [% END %] - - - - - - [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN DAY_MONTH_HOLIDAYS_LOOP %] - - - - - - [% END %] - -
    Day/monthMonth/dayTitleDescription
    [% DAY_MONTH_HOLIDAYS_LOO.DATE %][% DAY_MONTH_HOLIDAYS_LOO.TITLE %][% DAY_MONTH_HOLIDAYS_LOO.DESCRIPTION %]
    -[% END %] - -[% IF ( HOLIDAYS_LOOP ) %] -

    Unique holidays

    - - - - - - - - - - [% FOREACH HOLIDAYS_LOO IN HOLIDAYS_LOOP %] - - - - - - [% END %] - -
    DateTitleDescription
    [% HOLIDAYS_LOO.DATE %][% HOLIDAYS_LOO.TITLE %][% HOLIDAYS_LOO.DESCRIPTION %]
    -[% END %] -
    -
    -
    -
    -
    - -
    -[% INCLUDE 'tools-menu.inc' %] -
    -
    -[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt index 4ab38c9..dce635a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt @@ -73,7 +73,7 @@

    Additional tools

    [% IF ( CAN_user_tools_edit_calendar ) %] -
    Calendar
    +
    Calendar
    Define days when the library is closed
    [% END %] diff --git a/misc/cronjobs/staticfines.pl b/misc/cronjobs/staticfines.pl index 0d819a5..2f3d86c 100755 --- a/misc/cronjobs/staticfines.pl +++ b/misc/cronjobs/staticfines.pl @@ -40,9 +40,10 @@ use Date::Calc qw/Date_to_Days/; use C4::Context; use C4::Circulation; use C4::Overdues; -use C4::Calendar qw(); # don't need any exports from Calendar use C4::Biblio; use C4::Debug; # supplying $debug and $cgi_debug +use Koha::Calendar; + use Getopt::Long; use List::MoreUtils qw/none/; use Koha::DateUtils; @@ -172,10 +173,14 @@ for ( my $i = 0 ; $i < scalar(@$data) ; $i++ ) { my $calendar; unless ( defined( $calendars{$branchcode} ) ) { - $calendars{$branchcode} = C4::Calendar->new( branchcode => $branchcode ); + $calendars{$branchcode} = Koha::Calendar->new( branchcode => $branchcode ); } $calendar = $calendars{$branchcode}; - my $isHoliday = $calendar->isHoliday( $tday, $tmonth, $tyear ); + my $isHoliday = $calendar->is_holiday( DateTime->new( + year => $tyear, + month => $tmonth, + day => $tday + ) ); # Reassing datedue_days if -delay specified in commandline $bigdebug and warn "Using commandline supplied delay : $delay" if ($delay); diff --git a/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl b/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl index d7054c2..3b256a0 100755 --- a/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl +++ b/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl @@ -37,7 +37,7 @@ use C4::Items; use C4::Letters; use C4::Overdues; use C4::Dates; -use C4::Calendar; +use Koha::Calendar; sub usage { pod2usage( -verbose => 2 ); @@ -312,23 +312,18 @@ sub GetWaitingHolds { sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] ); $issue->{'level'} = 1; # only one level for Hold Waiting notifications - my $days_to_subtract = 0; - my $calendar = C4::Calendar->new( branchcode => $issue->{'site'} ); - while ( - $calendar->isHoliday( - reverse( - Add_Delta_Days( - $waitingdate[0], $waitingdate[1], - $waitingdate[2], $days_to_subtract - ) - ) - ) - ) - { - $days_to_subtract++; - } - $issue->{'days_since_waiting'} = - $issue->{'days_since_waiting'} - $days_to_subtract; + my $calendar = Koha::Calendar->new( branchcode => $issue->{'site'} ); + $issue->{'days_since_waiting'} = $calendar->days_between( + DateTime->new( + year => $waitingdate[0], + month => $waitingdate[1], + day => $waitingdate[2], + time_zone => C4::Context->tz, + ), + DateTime->now( + time_zone => C4::Context->tz, + ), + ); if ( ( diff --git a/t/Calendar.t b/t/Calendar.t index 8648968..8c30c77 100755 --- a/t/Calendar.t +++ b/t/Calendar.t @@ -4,17 +4,13 @@ use strict; use warnings; use DateTime; use DateTime::Duration; -use Test::More tests => 35; +use Test::More tests => 34; use Test::MockModule; use DBD::Mock; use Koha::DateUtils; BEGIN { use_ok('Koha::Calendar'); - - # This was the only test C4 had - # Remove when no longer used - use_ok('C4::Calendar'); } my $module_context = new Test::MockModule('C4::Context'); diff --git a/t/db_dependent/Calendar.t b/t/db_dependent/Calendar.t new file mode 100644 index 0000000..162e09b --- /dev/null +++ b/t/db_dependent/Calendar.t @@ -0,0 +1,86 @@ +use Modern::Perl; + +use Test::More tests => 14; + +use C4::Calendar; +use C4::Context; + +my $dbh = C4::Context->dbh; + +# Start transaction +$dbh->{AutoCommit} = 0; +$dbh->{RaiseError} = 1; + +my %new_holiday = ( open_hour => 0, + open_minute => 0, + close_hour => 0, + close_minute => 0, + title => 'example week_day_holiday', + description => 'This is an example week_day_holiday used for testing' ); + +# Weekly events +ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } ); + +my $weekly_events = GetWeeklyEvents( 'UPL' ); +is( $weekly_events->[0]->{'title'}, $new_holiday{'title'}, 'weekly title' ); +is( $weekly_events->[0]->{'description'}, $new_holiday{'description'}, 'weekly description' ); + +$new_holiday{close_hour} = 24; + +ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } ); +$weekly_events = GetWeeklyEvents( 'UPL' ); +is( scalar @$weekly_events, 0, 'weekly modification, not insertion' ); + +$new_holiday{close_hour} = 0; +ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } ); + +# Yearly events + +ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } ); + +my $yearly_events = GetYearlyEvents( 'UPL' ); +is( $yearly_events->[0]->{'title'}, $new_holiday{'title'}, 'yearly title' ); +is( $yearly_events->[0]->{'description'}, $new_holiday{'description'}, 'yearly description' ); + +$new_holiday{close_hour} = 24; + +ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } ); +$yearly_events = GetYearlyEvents( 'UPL' ); +is( scalar @$yearly_events, 0, 'yearly modification, not insertion' ); + +$new_holiday{close_hour} = 0; +ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } ); + +# Single events + +ModSingleEvent( 'UPL', { date => '2013-03-17', %new_holiday } ); + +my $single_events = GetSingleEvents( 'UPL' ); +is( $single_events->[0]->{'title'}, $new_holiday{'title'}, 'single title' ); +is( $single_events->[0]->{'description'}, $new_holiday{'description'}, 'single description' ); +is( $single_events->[0]->{'closed'}, 1, 'single closed' ); + +$new_holiday{close_hour} = 24; + +ModSingleEvent( 'UPL', { date => '2013-03-17', %new_holiday } ); +$single_events = GetSingleEvents( 'UPL' ); +is( scalar @$single_events, 1, 'single modification, not insertion' ); +is( $single_events->[0]->{'closed'}, 0, 'single closed' ); + + +# delete + +DelRepeatingEvent( 'UPL', { weekday => 1 } ); +$weekly_events = GetWeeklyEvents( 'UPL' ); +is( scalar @$weekly_events, 0, 'weekly deleted' ); + +DelRepeatingEvent( 'UPL', { month => 6, day => 26 } ); +$yearly_events = GetYearlyEvents( 'UPL' ); +is( scalar @$yearly_events, 0, 'yearly deleted' ); + +DelSingleEvent( 'UPL', { date => '2013-03-17' } ); + +$single_events = GetSingleEvents( 'UPL' ); +is( scalar @$single_events, 0, 'single deleted' ); + +$dbh->rollback; diff --git a/t/db_dependent/Holidays.t b/t/db_dependent/Holidays.t index 9d41105..0d61036 100755 --- a/t/db_dependent/Holidays.t +++ b/t/db_dependent/Holidays.t @@ -5,18 +5,15 @@ use DateTime; use DateTime::TimeZone; use C4::Context; -use Test::More tests => 10; +use Test::More tests => 6; BEGIN { use_ok('Koha::Calendar'); } -BEGIN { use_ok('C4::Calendar'); } my $branchcode = 'MPL'; my $koha_calendar = Koha::Calendar->new( branchcode => $branchcode ); -my $c4_calendar = C4::Calendar->new( branchcode => $branchcode ); isa_ok( $koha_calendar, 'Koha::Calendar', 'Koha::Calendar class returned' ); -isa_ok( $c4_calendar, 'C4::Calendar', 'C4::Calendar class returned' ); my $sunday = DateTime->new( year => 2011, @@ -43,13 +40,3 @@ is( $koha_calendar->is_holiday($sunday), 1, 'Sunday is a closed day' ); is( $koha_calendar->is_holiday($monday), 0, 'Monday is not a closed day' ); is( $koha_calendar->is_holiday($christmas), 1, 'Christmas is a closed day' ); is( $koha_calendar->is_holiday($newyear), 1, 'New Years day is a closed day' ); - -my $custom_holiday = DateTime->new( - year => 2013, - month => 11, - day => 12, -); -is( $koha_calendar->is_holiday($custom_holiday), 0, '2013-11-10 does not start off as a holiday' ); -$koha_calendar->add_holiday($custom_holiday); -is( $koha_calendar->is_holiday($custom_holiday), 1, 'able to add holiday for testing' ); - diff --git a/tools/calendar.pl b/tools/calendar.pl new file mode 100755 index 0000000..0ba8f92 --- /dev/null +++ b/tools/calendar.pl @@ -0,0 +1,268 @@ +#!/usr/bin/perl + +# 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 . + +#####Sets holiday periods for each branch. Datedues will be extended if branch is closed -TG + +use Modern::Perl; + +use CGI; + +use C4::Auth; +use C4::Output; + +use C4::Branch; # GetBranches +use C4::Calendar; + +my $input = new CGI; + +my $dbh = C4::Context->dbh(); +# Get the template to use +my ($template, $loggedinuser, $cookie) + = get_template_and_user({template_name => "tools/calendar.tmpl", + type => "intranet", + query => $input, + authnotrequired => 0, + flagsrequired => {tools => 'edit_calendar'}, + debug => 1, + }); + +# keydate - date passed to calendar.js. calendar.js does not process dashes within a date. +my $keydate; +# calendardate - date passed in url for human readability (syspref) +my $calendardate; +my $today = C4::Dates->new(); +my $calendarinput = C4::Dates->new($input->param('calendardate')) || $today; +# if the url has an invalid date default to 'now.' +unless($calendardate = $calendarinput->output('syspref')) { + $calendardate = $today->output('syspref'); +} +unless($keydate = $calendarinput->output('iso')) { + $keydate = $today->output('iso'); +} +$keydate =~ s/-/\//g; + +my $branch= $input->param('branchName') || $input->param('branch') || C4::Context->userenv->{'branch'}; +# Set all the branches. +my $onlymine=(C4::Context->preference('IndependentBranches') && + C4::Context->userenv && + C4::Context->userenv->{flags} % 2 !=1 && + C4::Context->userenv->{branch}?1:0); +if ( $onlymine ) { + $branch = C4::Context->userenv->{'branch'}; +} +my $branchname = GetBranchName($branch); +my $branches = GetBranches($onlymine); +my @branchloop; +for my $thisbranch ( + sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} } + keys %{$branches} ) { + push @branchloop, + { value => $thisbranch, + selected => $thisbranch eq $branch, + branchname => $branches->{$thisbranch}->{'branchname'}, + }; +} + +# branches calculated - put branch codes in a single string so they can be passed in a form +my $branchcodes = join '|', keys %{$branches}; + +my $op = $input->param( 'op' ) // ''; + +my @ranged_dates; + +if ( my $dateofrange = $input->param( 'dateofrange' ) ) { + my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' ); + + my ( $start_year, $start_month, $start_day ) = split( /-/, $date ); + my ( $end_year, $end_month, $end_day ) = split( /-/, C4::Dates->new( $dateofrange )->output( 'iso' ) ); + + if ( $end_year && $end_month && $end_day ){ + my $first_dt = DateTime->new(year => $start_year, month => $start_month, day => $start_day); + my $end_dt = DateTime->new(year => $end_year, month => $end_month, day => $end_day); + + for ( my $dt = $first_dt->clone(); $dt <= $end_dt; $dt->add(days => 1) ) { + push @ranged_dates, $dt->clone(); + } + } +} + +my @branches; +if ( $input->param( 'allBranches' ) || !$input->param( 'branchName' ) ) { + @branches = split /\|/, $input->param( 'branchcodes' ); +} else { + @branches = ( $input->param( 'branchName' ) ); +} + +if ( $op eq 'save' ) { + my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' ); + + local our ( $open_hour, $open_minute, $close_hour, $close_minute ); + + if ( $input->param( 'hoursType' ) eq 'open' ) { + ( $open_hour, $open_minute ) = ( 0, 0 ); + ( $close_hour, $close_minute ) = ( 24, 0 ); + } elsif ( $input->param( 'hoursType' ) eq 'closed' ) { + ( $open_hour, $open_minute ) = ( 0, 0 ); + ( $close_hour, $close_minute ) = ( 0, 0 ); + } else { + ( $open_hour, $open_minute ) = ( $input->param( 'openTime' ) =~ /(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])/ ); + ( $close_hour, $close_minute ) = ( $input->param( 'closeTime' ) =~ /(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])/ ); + } + + foreach my $branchcode ( @branches ) { + my %event_types = ( + 'single' => sub { + ModSingleEvent( $branchcode, { + date => $date, + title => $input->param( 'title' ), + description => $input->param( 'description' ), + open_hour => $open_hour, + open_minute => $open_minute, + close_hour => $close_hour, + close_minute => $close_minute + } ); + }, + + 'weekly' => sub { + ModRepeatingEvent( $branchcode, { + weekday => $input->param( 'weekday' ), + title => $input->param( 'title' ), + description => $input->param( 'description' ), + open_hour => $open_hour, + open_minute => $open_minute, + close_hour => $close_hour, + close_minute => $close_minute + } ); + }, + + 'yearly' => sub { + ModRepeatingEvent( $branchcode, { + month => $input->param( 'month' ), + day => $input->param( 'day' ), + title => $input->param( 'title' ), + description => $input->param( 'description' ), + open_hour => $open_hour, + open_minute => $open_minute, + close_hour => $close_hour, + close_minute => $close_minute + } ); + }, + + 'singlerange' => sub { + foreach my $dt ( @ranged_dates ) { + ModSingleEvent( $branchcode, { + date => $dt->ymd, + title => $input->param( 'title' ), + description => $input->param( 'description' ), + open_hour => $open_hour, + open_minute => $open_minute, + close_hour => $close_hour, + close_minute => $close_minute + } ); + } + }, + + 'yearlyrange' => sub { + foreach my $dt ( @ranged_dates ) { + ModRepeatingEvent( $branchcode, { + month => $dt->month, + day => $dt->day, + title => $input->param( 'title' ), + description => $input->param( 'description' ), + open_hour => $open_hour, + open_minute => $open_minute, + close_hour => $close_hour, + close_minute => $close_minute + } ); + } + }, + ); + + # Choose from the above options + $event_types{ $input->param( 'eventType' ) }->(); + } +} elsif ( $op eq 'delete' ) { + my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' ); + + foreach my $branchcode ( @branches ) { + my %event_types = ( + 'single' => sub { + DelSingleEvent( $branchcode, { date => $date } ); + }, + + 'weekly' => sub { + DelRepeatingEvent( $branchcode, { weekday => $input->param( 'weekday' ) } ); + }, + + 'yearly' => sub { + DelRepeatingEvent( $branchcode, { month => $input->param( 'month' ), day => $input->param( 'day' ) } ); + }, + ); + + # Choose from the above options + $event_types{ $input->param( 'eventType' ) }->(); + } +} elsif ( $op eq 'deleterange' ) { + foreach my $branchcode ( @branches ) { + foreach my $dt ( @ranged_dates ) { + DelSingleEvent( $branchcode, { date => $dt->ymd } ); + } + } +} elsif ( $op eq 'deleterangerepeat' ) { + foreach my $branchcode ( @branches ) { + foreach my $dt ( @ranged_dates ) { + DelRepeatingEvent( $branchcode, { month => $dt->month, day => $dt->day } ); + } + } +} elsif ( $op eq 'copyall' ) { + CopyAllEvents( $input->param( 'from_branchcode' ), $input->param( 'branchcode' ) ); +} + +my $yearly_events = GetYearlyEvents($branch); +foreach my $event ( @$yearly_events ) { + # Determine date format on month and day. + my $day_monthdate; + my $day_monthdate_sort; + if (C4::Context->preference("dateformat") eq "metric") { + $day_monthdate_sort = "$event->{month}-$event->{day}"; + $day_monthdate = "$event->{day}/$event->{month}"; + } elsif (C4::Context->preference("dateformat") eq "us") { + $day_monthdate = "$event->{month}/$event->{day}"; + $day_monthdate_sort = $day_monthdate; + } else { + $day_monthdate = "$event->{month}-$event->{day}"; + $day_monthdate_sort = $day_monthdate; + } + + $event->{month_day_display} = $day_monthdate; + $event->{month_day_sort} = $day_monthdate_sort; +} + +$template->param( + weekly_events => GetWeeklyEvents($branch), + yearly_events => $yearly_events, + single_events => GetSingleEvents($branch), + branchloop => \@branchloop, + calendardate => $calendardate, + keydate => $keydate, + branchcodes => $branchcodes, + branch => $branch, + branchname => $branchname, +); + +# Shows the template with the real values replaced +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/tools/copy-holidays.pl b/tools/copy-holidays.pl deleted file mode 100755 index 83c9761..0000000 --- a/tools/copy-holidays.pl +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/perl - -# Copyright 2012 Catalyst IT -# -# 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 2 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -use strict; -use warnings; - -use CGI; - -use C4::Auth; -use C4::Output; - - -use C4::Calendar; - -my $input = new CGI; -my $dbh = C4::Context->dbh(); - -my $branchcode = $input->param('branchcode'); -my $from_branchcode = $input->param('from_branchcode'); - -C4::Calendar->new(branchcode => $from_branchcode)->copy_to_branch($branchcode) if $from_branchcode && $branchcode; - -print $input->redirect("/cgi-bin/koha/tools/holidays.pl?branch=".($branchcode || $from_branchcode)); diff --git a/tools/exceptionHolidays.pl b/tools/exceptionHolidays.pl deleted file mode 100755 index 0a36a20..0000000 --- a/tools/exceptionHolidays.pl +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -use CGI; - -use C4::Auth; -use C4::Output; -use DateTime; - -use C4::Calendar; - -my $input = new CGI; -my $dbh = C4::Context->dbh(); - -my $branchcode = $input->param('showBranchName'); -my $weekday = $input->param('showWeekday'); -my $day = $input->param('showDay'); -my $month = $input->param('showMonth'); -my $year = $input->param('showYear'); -my $day1; -my $month1; -my $year1; -my $title = $input->param('showTitle'); -my $description = $input->param('showDescription'); -my $holidaytype = $input->param('showHolidayType'); -my $datecancelrange = $input->param('datecancelrange'); -my $calendardate = sprintf("%04d-%02d-%02d", $year, $month, $day); -my $isodate = C4::Dates->new($calendardate, 'iso'); -$calendardate = $isodate->output('syspref'); - -my $calendar = C4::Calendar->new(branchcode => $branchcode); - -$title || ($title = ''); -if ($description) { - $description =~ s/\r/\\r/g; - $description =~ s/\n/\\n/g; -} else { - $description = ''; -} - -# We format the date -my @dateend = split(/[\/-]/, $datecancelrange); -if (C4::Context->preference("dateformat") eq "metric") { - $day1 = $dateend[0]; - $month1 = $dateend[1]; - $year1 = $dateend[2]; -}elsif (C4::Context->preference("dateformat") eq "us") { - $month1 = $dateend[0]; - $day1 = $dateend[1]; - $year1 = $dateend[2]; -} else { - $year1 = $dateend[0]; - $month1 = $dateend[1]; - $day1 = $dateend[2]; -} - -# We make an array with holiday's days -my @holiday_list; -if ($year1 && $month1 && $day1){ - my $first_dt = DateTime->new(year => $year, month => $month, day => $day); - my $end_dt = DateTime->new(year => $year1, month => $month1, day => $day1); - - for (my $dt = $first_dt->clone(); - $dt <= $end_dt; - $dt->add(days => 1) ) - { - push @holiday_list, $dt->clone(); - } -} -if ($input->param('showOperation') eq 'exception') { - $calendar->insert_exception_holiday(day => $day, - month => $month, - year => $year, - title => $title, - description => $description); -} elsif ($input->param('showOperation') eq 'exceptionrange' ) { - if (@holiday_list){ - foreach my $date (@holiday_list){ - $calendar->insert_exception_holiday( - day => $date->{local_c}->{day}, - month => $date->{local_c}->{month}, - year => $date->{local_c}->{year}, - title => $title, - description => $description - ); - } - } -} elsif ($input->param('showOperation') eq 'edit') { - if($holidaytype eq 'weekday') { - $calendar->ModWeekdayholiday(weekday => $weekday, - title => $title, - description => $description); - } elsif ($holidaytype eq 'daymonth') { - $calendar->ModDaymonthholiday(day => $day, - month => $month, - title => $title, - description => $description); - } elsif ($holidaytype eq 'ymd') { - $calendar->ModSingleholiday(day => $day, - month => $month, - year => $year, - title => $title, - description => $description); - } elsif ($holidaytype eq 'exception') { - $calendar->ModExceptionholiday(day => $day, - month => $month, - year => $year, - title => $title, - description => $description); - } -} elsif ($input->param('showOperation') eq 'delete') { - $calendar->delete_holiday(weekday => $weekday, - day => $day, - month => $month, - year => $year); -}elsif ($input->param('showOperation') eq 'deleterange') { - if (@holiday_list){ - foreach my $date (@holiday_list){ - $calendar->delete_holiday_range(weekday => $weekday, - day => $date->{local_c}->{day}, - month => $date->{local_c}->{month}, - year => $date->{local_c}->{year}); - } - } -}elsif ($input->param('showOperation') eq 'deleterangerepeat') { - if (@holiday_list){ - foreach my $date (@holiday_list){ - $calendar->delete_holiday_range_repeatable(weekday => $weekday, - day => $date->{local_c}->{day}, - month => $date->{local_c}->{month}); - } - } -}elsif ($input->param('showOperation') eq 'deleterangerepeatexcept') { - if (@holiday_list){ - foreach my $date (@holiday_list){ - $calendar->delete_exception_holiday_range(weekday => $weekday, - day => $date->{local_c}->{day}, - month => $date->{local_c}->{month}, - year => $date->{local_c}->{year}); - } - } -} -print $input->redirect("/cgi-bin/koha/tools/holidays.pl?branch=$branchcode&calendardate=$calendardate"); diff --git a/tools/holidays.pl b/tools/holidays.pl deleted file mode 100755 index 23468d1..0000000 --- a/tools/holidays.pl +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/perl - -# 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, -# Suite 330, Boston, MA 02111-1307 USA - -#####Sets holiday periods for each branch. Datedues will be extended if branch is closed -TG -use strict; -use warnings; - -use CGI; - -use C4::Auth; -use C4::Output; - -use C4::Branch; # GetBranches -use C4::Calendar; - -my $input = new CGI; - -my $dbh = C4::Context->dbh(); -# Get the template to use -my ($template, $loggedinuser, $cookie) - = get_template_and_user({template_name => "tools/holidays.tt", - type => "intranet", - query => $input, - authnotrequired => 0, - flagsrequired => {tools => 'edit_calendar'}, - debug => 1, - }); - -# keydate - date passed to calendar.js. calendar.js does not process dashes within a date. -my $keydate; -# calendardate - date passed in url for human readability (syspref) -my $calendardate; -my $today = C4::Dates->new(); -my $calendarinput = C4::Dates->new($input->param('calendardate')) || $today; -# if the url has an invalid date default to 'now.' -unless($calendardate = $calendarinput->output('syspref')) { - $calendardate = $today->output('syspref'); -} -unless($keydate = $calendarinput->output('iso')) { - $keydate = $today->output('iso'); -} -$keydate =~ s/-/\//g; - -my $branch= $input->param('branch') || C4::Context->userenv->{'branch'}; -# Set all the branches. -my $onlymine = - ( C4::Context->preference('IndependentBranches') - && C4::Context->userenv - && !C4::Context->IsSuperLibrarian() - && C4::Context->userenv->{branch} ? 1 : 0 ); -if ( $onlymine ) { - $branch = C4::Context->userenv->{'branch'}; -} -my $branchname = GetBranchName($branch); -my $branches = GetBranches($onlymine); -my @branchloop; -for my $thisbranch ( - sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} } - keys %{$branches} ) { - push @branchloop, - { value => $thisbranch, - selected => $thisbranch eq $branch, - branchname => $branches->{$thisbranch}->{'branchname'}, - }; -} - -# branches calculated - put branch codes in a single string so they can be passed in a form -my $branchcodes = join '|', keys %{$branches}; - -# Get all the holidays - -my $calendar = C4::Calendar->new(branchcode => $branch); -my $week_days_holidays = $calendar->get_week_days_holidays(); -my @week_days; -foreach my $weekday (keys %$week_days_holidays) { -# warn "WEEK DAY : $weekday"; - my %week_day; - %week_day = (KEY => $weekday, - TITLE => $week_days_holidays->{$weekday}{title}, - DESCRIPTION => $week_days_holidays->{$weekday}{description}); - push @week_days, \%week_day; -} - -my $day_month_holidays = $calendar->get_day_month_holidays(); -my @day_month_holidays; -foreach my $monthDay (keys %$day_month_holidays) { - # Determine date format on month and day. - my $day_monthdate; - my $day_monthdate_sort; - if (C4::Context->preference("dateformat") eq "metric") { - $day_monthdate_sort = "$day_month_holidays->{$monthDay}{month}-$day_month_holidays->{$monthDay}{day}"; - $day_monthdate = "$day_month_holidays->{$monthDay}{day}/$day_month_holidays->{$monthDay}{month}"; - } elsif (C4::Context->preference("dateformat") eq "us") { - $day_monthdate = "$day_month_holidays->{$monthDay}{month}/$day_month_holidays->{$monthDay}{day}"; - $day_monthdate_sort = $day_monthdate; - } else { - $day_monthdate = "$day_month_holidays->{$monthDay}{month}-$day_month_holidays->{$monthDay}{day}"; - $day_monthdate_sort = $day_monthdate; - } - my %day_month; - %day_month = (KEY => $monthDay, - DATE_SORT => $day_monthdate_sort, - DATE => $day_monthdate, - TITLE => $day_month_holidays->{$monthDay}{title}, - DESCRIPTION => $day_month_holidays->{$monthDay}{description}); - push @day_month_holidays, \%day_month; -} - -my $exception_holidays = $calendar->get_exception_holidays(); -my @exception_holidays; -foreach my $yearMonthDay (keys %$exception_holidays) { - my $exceptiondate = C4::Dates->new($exception_holidays->{$yearMonthDay}{date}, "iso"); - my %exception_holiday; - %exception_holiday = (KEY => $yearMonthDay, - DATE_SORT => $exception_holidays->{$yearMonthDay}{date}, - DATE => $exceptiondate->output("syspref"), - TITLE => $exception_holidays->{$yearMonthDay}{title}, - DESCRIPTION => $exception_holidays->{$yearMonthDay}{description}); - push @exception_holidays, \%exception_holiday; -} - -my $single_holidays = $calendar->get_single_holidays(); -my @holidays; -foreach my $yearMonthDay (keys %$single_holidays) { - my $holidaydate = C4::Dates->new($single_holidays->{$yearMonthDay}{date}, "iso"); - my %holiday; - %holiday = (KEY => $yearMonthDay, - DATE_SORT => $single_holidays->{$yearMonthDay}{date}, - DATE => $holidaydate->output("syspref"), - TITLE => $single_holidays->{$yearMonthDay}{title}, - DESCRIPTION => $single_holidays->{$yearMonthDay}{description}); - push @holidays, \%holiday; -} - -$template->param( - WEEK_DAYS_LOOP => \@week_days, - branchloop => \@branchloop, - HOLIDAYS_LOOP => \@holidays, - EXCEPTION_HOLIDAYS_LOOP => \@exception_holidays, - DAY_MONTH_HOLIDAYS_LOOP => \@day_month_holidays, - calendardate => $calendardate, - keydate => $keydate, - branchcodes => $branchcodes, - branch => $branch, - branchname => $branchname, - branch => $branch, -); - -# Shows the template with the real values replaced -output_html_with_http_headers $input, $cookie, $template->output; diff --git a/tools/newHolidays.pl b/tools/newHolidays.pl deleted file mode 100755 index 646276c..0000000 --- a/tools/newHolidays.pl +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -use CGI; - -use C4::Auth; -use C4::Output; - - -use C4::Calendar; -use DateTime; - -my $input = new CGI; -my $dbh = C4::Context->dbh(); - -our $branchcode = $input->param('newBranchName'); -my $originalbranchcode = $branchcode; -our $weekday = $input->param('newWeekday'); -our $day = $input->param('newDay'); -our $month = $input->param('newMonth'); -our $year = $input->param('newYear'); -my $day1; -my $month1; -my $year1; -my $dateofrange = $input->param('dateofrange'); -our $title = $input->param('newTitle'); -our $description = $input->param('newDescription'); -our $newoperation = $input->param('newOperation'); -my $allbranches = $input->param('allBranches'); - -my $calendardate = sprintf("%04d-%02d-%02d", $year, $month, $day); -my $isodate = C4::Dates->new($calendardate, 'iso'); -$calendardate = $isodate->output('syspref'); - -my @dateend = split(/[\/-]/, $dateofrange); -if (C4::Context->preference("dateformat") eq "metric") { - $day1 = $dateend[0]; - $month1 = $dateend[1]; - $year1 = $dateend[2]; -}elsif (C4::Context->preference("dateformat") eq "us") { - $month1 = $dateend[0]; - $day1 = $dateend[1]; - $year1 = $dateend[2]; -} else { - $year1 = $dateend[0]; - $month1 = $dateend[1]; - $day1 = $dateend[2]; -} -$title || ($title = ''); -if ($description) { - $description =~ s/\r/\\r/g; - $description =~ s/\n/\\n/g; -} else { - $description = ''; -} - -# We make an array with holiday's days -our @holiday_list; -if ($year1 && $month1 && $day1){ - my $first_dt = DateTime->new(year => $year, month => $month, day => $day); - my $end_dt = DateTime->new(year => $year1, month => $month1, day => $day1); - - for (my $dt = $first_dt->clone(); - $dt <= $end_dt; - $dt->add(days => 1) ) - { - push @holiday_list, $dt->clone(); - } -} - -if($allbranches) { - my $branch; - my @branchcodes = split(/\|/, $input->param('branchCodes')); - foreach $branch (@branchcodes) { - add_holiday($newoperation, $branch, $weekday, $day, $month, $year, $title, $description); - } -} else { - add_holiday($newoperation, $branchcode, $weekday, $day, $month, $year, $title, $description); -} - -print $input->redirect("/cgi-bin/koha/tools/holidays.pl?branch=$originalbranchcode&calendardate=$calendardate"); - -sub add_holiday { - ($newoperation, $branchcode, $weekday, $day, $month, $year, $title, $description) = @_; - my $calendar = C4::Calendar->new(branchcode => $branchcode); - - if ($newoperation eq 'weekday') { - unless ( $weekday && ($weekday ne '') ) { - # was dow calculated by javascript? original code implies it was supposed to be. - # if not, we need it. - $weekday = &Date::Calc::Day_of_Week($year, $month, $day) % 7 unless($weekday); - } - unless($calendar->isHoliday($day, $month, $year)) { - $calendar->insert_week_day_holiday(weekday => $weekday, - title => $title, - description => $description); - } - } elsif ($newoperation eq 'repeatable') { - unless($calendar->isHoliday($day, $month, $year)) { - $calendar->insert_day_month_holiday(day => $day, - month => $month, - title => $title, - description => $description); - } - } elsif ($newoperation eq 'holiday') { - unless($calendar->isHoliday($day, $month, $year)) { - $calendar->insert_single_holiday(day => $day, - month => $month, - year => $year, - title => $title, - description => $description); - } - - } elsif ( $newoperation eq 'holidayrange' ) { - if (@holiday_list){ - foreach my $date (@holiday_list){ - unless ( $calendar->isHoliday( $date->{local_c}->{day}, $date->{local_c}->{month}, $date->{local_c}->{year} ) ) { - $calendar->insert_single_holiday( - day => $date->{local_c}->{day}, - month => $date->{local_c}->{month}, - year => $date->{local_c}->{year}, - title => $title, - description => $description - ); - } - } - } - } elsif ( $newoperation eq 'holidayrangerepeat' ) { - if (@holiday_list){ - foreach my $date (@holiday_list){ - unless ( $calendar->isHoliday( $date->{local_c}->{day}, $date->{local_c}->{month}, $date->{local_c}->{year} ) ) { - $calendar->insert_day_month_holiday( - day => $date->{local_c}->{day}, - month => $date->{local_c}->{month}, - title => $title, - description => $description - ); - } - } - } - } -} -- 2.0.1