Bugzilla – Attachment 74864 Details for
Bug 17015
New Koha Calendar
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 17015: Code quality fixes on QA feedback
Bug-17015-Code-quality-fixes-on-QA-feedback.patch (text/plain), 110.66 KB, created by
David Bourgault
on 2018-04-25 20:26:32 UTC
(
hide
)
Description:
Bug 17015: Code quality fixes on QA feedback
Filename:
MIME Type:
Creator:
David Bourgault
Created:
2018-04-25 20:26:32 UTC
Size:
110.66 KB
patch
obsolete
>From c7e89b92d1d023a65f501d757f0585c02ebeec60 Mon Sep 17 00:00:00 2001 >From: David Bourgault <david.bourgault@inlibro.com> >Date: Wed, 28 Feb 2018 17:42:09 -0500 >Subject: [PATCH] Bug 17015: Code quality fixes on QA feedback > >Changes: > >* Koha::DiscreteCalendar->new uses a hashref instead of a hash >This meant changing every call to the Calendar and explains why this patch is so >big. Most changes are simply adding braces to the new() call. > >+ Added table encoding to atomic update >+ Added table definition to kohastructure.sql > >- Removed `repeatable_holidays`, `special_holidays` from kohastructure.sql >Also added relevant DROP TABLEs to a new atomicupdate (part3) > >+ Added 'override' param to Koha::DiscreteCalendar >Without this param (off by default), edit_holiday will not modify past dates. >This caused issues with some tests that required this functionality to work >properly. Adding 'override => 1' to the function call will allow past dates to >happen, but should only be called for testing. > >* Holds.t, Hold.t, CalcDateDue.t have been corrected. >Prior to his patch, theses tests used hardcoded dates to test calendar >functionalities, however, DiscreteCalendar is only usable one year into the past >by default. They have been modified to be centered around '$today' > >* 'use strict; use warnings;' changed to 'use Modern::Perl;' in modified files. >* Atomic update no longer takes params >* Javascript moved to the bottom of discrete_calendar.tt >* Calendar css moved out of tt file and into new discrete_calendar.css >* All references to C4::Calendar and Koha::Calendar should now be removed >* Some comments corrected > >All relevant tests passed for me on a fresh database. QA tool green. >Test plan has not changed. >--- > C4/Calendar.pm | 713 ---------------- > C4/Circulation.pm | 13 +- > C4/HoldsQueue.pm | 4 +- > C4/Overdues.pm | 4 +- > C4/Reserves.pm | 2 +- > Koha/DiscreteCalendar.pm | 64 +- > Koha/Hold.pm | 4 +- > circ/returns.pl | 2 +- > .../bug_17015_part1_create_discrete_calendar.sql | 2 +- > .../bug_17015_part2_fill_discrete_calendar.perl | 20 +- > .../atomicupdate/bug_17015_part3_drop_calendar.sql | 5 + > installer/data/mysql/kohastructure.sql | 49 +- > installer/data/mysql/updatedatabase.pl | 2 +- > .../intranet-tmpl/prog/css/discretecalendar.css | 206 +++++ > .../prog/en/modules/tools/discrete_calendar.tt | 898 +++++++++------------ > misc/cronjobs/add_days_discrete_calendar.pl | 3 +- > misc/cronjobs/fines.pl | 2 +- > misc/cronjobs/overdue_notices.pl | 6 +- > misc/cronjobs/staticfines.pl | 2 +- > .../thirdparty/TalkingTech_itiva_outbound.pl | 2 +- > t/db_dependent/Circulation/CalcDateDue.t | 47 +- > t/db_dependent/DiscreteCalendar.t | 44 +- > t/db_dependent/Hold.t | 20 +- > t/db_dependent/Holds.t | 1 - > t/db_dependent/HoldsQueue.t | 12 +- > tools/discrete_calendar.pl | 7 +- > 26 files changed, 762 insertions(+), 1372 deletions(-) > delete mode 100644 C4/Calendar.pm > create mode 100644 installer/data/mysql/atomicupdate/bug_17015_part3_drop_calendar.sql > create mode 100644 koha-tmpl/intranet-tmpl/prog/css/discretecalendar.css > >diff --git a/C4/Calendar.pm b/C4/Calendar.pm >deleted file mode 100644 >index 321aad7..0000000 >--- a/C4/Calendar.pm >+++ /dev/null >@@ -1,713 +0,0 @@ >-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 <http://www.gnu.org/licenses>. >- >-use strict; >-use warnings; >-use vars qw(@EXPORT); >- >-use Carp; >-use Date::Calc qw( Date_to_Days Today); >- >-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; >-} >- >-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 >-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 = @_; >- >- 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 (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; >-} >- >-=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 = @_; >- >- my $dbh = C4::Context->dbh(); >- my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (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}. >- >-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 (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}; >- >- >- # changed the 'single_holidays' table, lets force/reset its cache >- my $cache = Koha::Caches->get_instance(); >- $cache->clear_from_cache( 'single_holidays') ; >- $cache->clear_from_cache( 'exception_holidays') ; >- >- 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 = @_; >- >- @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o ) >- if $options{date} && !$options{day}; >- >- my $dbh = C4::Context->dbh(); >- my $isexception = 1; >- my $insertException = $dbh->prepare("insert into special_holidays (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}; >- >- # changed the 'single_holidays' table, lets force/reset its cache >- my $cache = Koha::Caches->get_instance(); >- $cache->clear_from_cache( 'single_holidays') ; >- $cache->clear_from_cache( 'exception_holidays') ; >- >- 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 $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); >- >-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 $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; >-} >- >-=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 $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}; >- >- # changed the 'single_holidays' table, lets force/reset its cache >- my $cache = Koha::Caches->get_instance(); >- $cache->clear_from_cache( 'single_holidays') ; >- $cache->clear_from_cache( 'exception_holidays') ; >- >- 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 $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}; >- >- # changed the 'single_holidays' table, lets force/reset its cache >- my $cache = Koha::Caches->get_instance(); >- $cache->clear_from_cache( 'single_holidays') ; >- $cache->clear_from_cache( 'exception_holidays') ; >- >- 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 = @_; >- >- # 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}"}); >- } 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}"}); >- } >- } >- } >- >- # changed the 'single_holidays' table, lets force/reset its cache >- my $cache = Koha::Caches->get_instance(); >- $cache->clear_from_cache( 'single_holidays') ; >- $cache->clear_from_cache( 'exception_holidays') ; >- >- 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}); >- >- # changed the 'single_holidays' table, lets force/reset its cache >- my $cache = Koha::Caches->get_instance(); >- $cache->clear_from_cache( 'single_holidays') ; >- $cache->clear_from_cache( 'exception_holidays') ; >- >-} >- >-=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 = @_; >- >- 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 >- >- 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 $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}); >- >- # changed the 'single_holidays' table, lets force/reset its cache >- my $cache = Koha::Caches->get_instance(); >- $cache->clear_from_cache( 'single_holidays') ; >- $cache->clear_from_cache( 'exception_holidays') ; >-} >- >-=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) = @_; >- >- croak "No target_branch" unless $target_branch; >- >- 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; >-} >- >-1; >- >-__END__ >- >-=head1 AUTHOR >- >-Koha Physics Library UNLP <matias_veleda@hotmail.com> >- >-=cut >diff --git a/C4/Circulation.pm b/C4/Circulation.pm >index 3049130..191c2f1 100644 >--- a/C4/Circulation.pm >+++ b/C4/Circulation.pm >@@ -1195,7 +1195,7 @@ sub checkHighHolds { > > my $issuedate = DateTime->now( time_zone => C4::Context->tz() ); > >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branch ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branch }); > > my $itype = $item_object->effective_itemtype; > my $orig_due = C4::Circulation::CalcDateDue( $issuedate, $itype, $branch, $borrower ); >@@ -1722,7 +1722,7 @@ Returns a book. > removed. Optional. > > =item C<$dropbox> indicates that the check-in date is assumed to be >-yesterday, or the last non-holiday as defined in C4::Calendar . If >+yesterday, or the last non-holiday as defined in Koha::DiscreteCalendar. If > overdue charges are applied and C<$dropbox> is true, the last charge > will be removed. This assumes that the fines accrual script has run > for _today_. Optional. >@@ -2126,7 +2126,7 @@ sub MarkIssueReturned { > my $query = 'UPDATE issues SET returndate='; > my @bind; > if ($dropbox_branch) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $dropbox_branch ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $dropbox_branch }); > my $dropboxdate = $calendar->addDate( DateTime->now( time_zone => C4::Context->tz), -1 ); > $query .= ' ? '; > push @bind, $dropboxdate->strftime('%Y-%m-%d %H:%M'); >@@ -3480,7 +3480,7 @@ sub CalcDateDue { > else { # days > $dur = DateTime::Duration->new( days => $loanlength->{$length_key}); > } >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branch ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branch }); > $datedue = $calendar->addDate( $datedue, $dur, $loanlength->{lengthunit} ); > if ($loanlength->{lengthunit} eq 'days') { > $datedue->set_hour(23); >@@ -3519,14 +3519,13 @@ sub CalcDateDue { > } > } > if ( C4::Context->preference('useDaysMode') ne 'Days' ) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branch ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branch }); > if ( $calendar->is_holiday($datedue) ) { > # Don't return on a closed day >- $datedue = $calendar->prev_open_day( $datedue ); >+ $datedue = $calendar->prev_open_day( $datedue )->set(hour => 23, minute => 59); > } > } > } >- > return $datedue; > } > >diff --git a/C4/HoldsQueue.pm b/C4/HoldsQueue.pm >index 8765308..eb0cc02 100755 >--- a/C4/HoldsQueue.pm >+++ b/C4/HoldsQueue.pm >@@ -77,7 +77,7 @@ sub TransportCostMatrix { > }; > > if ( C4::Context->preference("HoldsQueueSkipClosed") ) { >- $calendars->{$from} ||= Koha::DiscreteCalendar->new( branchcode => $from ); >+ $calendars->{$from} ||= Koha::DiscreteCalendar->new({ branchcode => $from }); > $transport_cost_matrix{$to}{$from}{disable_transfer} ||= > $calendars->{$from}->is_holiday( $today ); > } >@@ -742,7 +742,7 @@ sub load_branches_to_pull_from { > my $today = dt_from_string(); > if ( C4::Context->preference('HoldsQueueSkipClosed') ) { > @branches_to_use = grep { >- !Koha::DiscreteCalendar->new( branchcode => $_ ) >+ !Koha::DiscreteCalendar->new({ branchcode => $_ }) > ->is_holiday( $today ) > } @branches_to_use; > } >diff --git a/C4/Overdues.pm b/C4/Overdues.pm >index 721e832..3f1436a 100644 >--- a/C4/Overdues.pm >+++ b/C4/Overdues.pm >@@ -294,7 +294,7 @@ sub get_chargeable_units { > my $charge_duration; > if ($unit eq 'hours') { > if(C4::Context->preference('finesCalendar') eq 'noFinesWhenClosed') { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branchcode }); > $charge_duration = $calendar->hours_between( $date_due, $date_returned ); > } else { > $charge_duration = $date_returned->delta_ms( $date_due ); >@@ -306,7 +306,7 @@ sub get_chargeable_units { > } > else { # days > if(C4::Context->preference('finesCalendar') eq 'noFinesWhenClosed') { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branchcode }); > $charge_duration = $calendar->days_between( $date_due, $date_returned ); > } else { > $charge_duration = $date_returned->delta_days( $date_due ); >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index 012cb7b..0e937b6 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -770,7 +770,7 @@ sub CancelExpiredReserves { > my $holds = Koha::Holds->search( $params ); > > while ( my $hold = $holds->next ) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $hold->branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $hold->branchcode }); > > next if !$cancel_on_holidays && $calendar->is_holiday( $today ); > >diff --git a/Koha/DiscreteCalendar.pm b/Koha/DiscreteCalendar.pm >index 8830396..8dee776 100644 >--- a/Koha/DiscreteCalendar.pm >+++ b/Koha/DiscreteCalendar.pm >@@ -16,13 +16,13 @@ package Koha::DiscreteCalendar; > # along with Koha; if not, see <http://www.gnu.org/licenses>. > > #####Sets holiday periods for each branch. Datedues will be extended if branch is closed -TG >-use strict; >-use warnings; >+use Modern::Perl; > > use CGI qw ( -utf8 ); > use Carp; > use DateTime; > use DateTime::Format::Strptime; >+use Data::Dumper; > > use C4::Context; > use C4::Output; >@@ -48,7 +48,7 @@ Koha::DiscreteCalendar - Object containing a branches calendar, working with the > > use Koha::DiscreteCalendar > >- my $c = Koha::DiscreteCalendar->new( branchcode => 'MAIN' ); >+ my $c = Koha::DiscreteCalendar->new({ branchcode => 'MAIN' }); > my $dt = DateTime->now(); > > # are we open >@@ -66,19 +66,19 @@ Koha::DiscreteCalendar - Object containing a branches calendar, working with the > > =head2 new : Create a (discrete) calendar object > >-my $calendar = Koha::DiscreteCalendar->new( branchcode => 'MAIN' ); >+my $calendar = Koha::DiscreteCalendar->new({ branchcode => 'MAIN' }); > > The option branchcode is required > > =cut > > sub new { >- my ( $classname, %options ) = @_; >+ my ( $classname, $options ) = @_; > my $self = {}; > bless $self, $classname; >- for my $o_name ( keys %options ) { >+ for my $o_name ( keys %{ $options } ) { > my $o = lc $o_name; >- $self->{$o} = $options{$o_name}; >+ $self->{$o} = $options->{$o_name}; > } > if ( !defined $self->{branchcode} ) { > croak 'No branchcode argument passed to Koha::DiscreteCalendar->new'; >@@ -157,7 +157,7 @@ sub get_dates_info { > > Koha::DiscreteCalendar->add_new_branch($copyBranch, $newBranch) > >-This methode will copy everything from a given branch to a new branch >+This method will copy everything from a given branch to a new branch > C<$copyBranch> is the branch to copy from > C<$newBranch> is the branch to be created, and copy into > >@@ -240,7 +240,7 @@ Returns the furthest date available in the databse of current branch. > > sub get_max_date { > my $self = shift; >- my $branchcode = $self->{branchcode}; >+ my $branchcode = $self->{branchcode}; > my $schema = Koha::Database->new->schema; > > my $rs = $schema->resultset('DiscreteCalendar')->search( >@@ -505,23 +505,26 @@ sub edit_holiday { > my $close_hour = $params->{close_hour} || ''; > > my $delete_type = $params->{delete_type} || undef; >- my $today = $params->{today} || DateTime->today; >+ my $today = $params->{today} || dt_from_string()->truncate( to => 'day' ); > > my $branchcode = $self->{branchcode}; > >+ # When override param is set, this function will allow past dates to be set as holidays, >+ # otherwise it will not. This is meant to only be used for testing. >+ my $override = $params->{override} || 0; >+ > my $schema = Koha::Database->new->schema; > $schema->{AutoCommit} = 0; > $schema->storage->txn_begin; >- my $dtf = $schema->storage->datetime_parser; >+ my $dtf = DateTime::Format::Strptime->new(pattern => "%F %T"); > > #String dates for Database usage >- my $start_date_string = $dtf->format_datetime($start_date); >- my $end_date_string = $dtf->format_datetime($end_date); >- $today = $dtf->format_datetime($today); >- >+ my $start_date_string = $dtf->format_datetime($start_date->clone->truncate(to => 'day')); >+ my $end_date_string = $dtf->format_datetime($end_date->clone->truncate(to => 'day')); >+ $today = $dtf->format_datetime($today->clone->truncate(to => 'day')); > my %updateValues = ( > is_opened => 0, >- note => $title, >+ note => $title, > holiday_type => $holiday_type, > ); > $updateValues{open_hour} = $open_hour if $open_hour ne ''; >@@ -537,7 +540,7 @@ sub edit_holiday { > branchcode => $branchcode, > }, > { >- where => \[ 'DAYOFWEEK(date) = ? AND date >= ? AND date <= DATE(?)', $weekday, $start_date_string, $end_date_string], >+ where => \[ 'DAYOFWEEK(date) = ? AND date >= DATE(?) AND date <= DATE(?)', $weekday, $start_date_string, $end_date_string], > } > ); > >@@ -546,10 +549,12 @@ sub edit_holiday { > } > }elsif ($holiday_type eq $HOLIDAYS->{EXCEPTION} || $holiday_type eq $HOLIDAYS->{FLOAT} || $holiday_type eq $HOLIDAYS->{NEED_VALIDATION}) { > #Update Exception Float and Needs Validation holidays >- my $where = { date => { -between => [$start_date_string, $end_date_string], '>=' => $today}}; >+ my $where = { date => { -between => [$start_date_string, $end_date_string]}}; > if($start_date_string ne $end_date_string && $weekday && $weekday ne 'everyday'){ >- $where = {-and => [ \["DAYOFWEEK(date) = ?", $weekday], date => { -between => [$start_date_string, $end_date_string], '>=' => $today}]}; >+ $where = {-and => [ \["DAYOFWEEK(date) = ?", $weekday], date => { -between => [$start_date_string, $end_date_string]}]}; > } >+ $where->{date}{'>='} = $today unless $override; >+ > my $rs = $schema->resultset('DiscreteCalendar')->search( > { > branchcode => $branchcode, >@@ -585,10 +590,12 @@ sub edit_holiday { > > }else { > #Update date(s)/Remove holidays >- my $where = { date => { -between => [$start_date_string, $end_date_string], '>=' => $today}}; >+ my $where = { date => { -between => [$start_date_string, $end_date_string]}}; > if($start_date_string ne $end_date_string && $weekday && $weekday ne 'everyday'){ >- $where = {-and => [ \["DAYOFWEEK(date) = ?", $weekday], date => { -between => [$start_date_string, $end_date_string], '>=' => $today}]}; >+ $where = {-and => [ \["DAYOFWEEK(date) = ?", $weekday], date => { -between => [$start_date_string, $end_date_string]}]}; > } >+ $where->{date}{'>='} = $today unless $override; >+ > my $rs = $schema->resultset('DiscreteCalendar')->search( > { > branchcode => $branchcode, >@@ -794,9 +801,8 @@ sub is_holiday { > } > ); > >- if($rs->count() != 0){ >- $isHoliday = 0 if $rs->first()->is_opened(); >- $isHoliday = 1 if !$rs->first()->is_opened(); >+ if ($rs->count() != 0) { >+ $isHoliday = ($rs->first()->is_opened() ? 0 : 1); > } > > return $isHoliday; >@@ -955,15 +961,13 @@ sub days_between { > > if ( $start_date->compare($end_date) > 0 ) { > # swap dates >- my $int_dt = $end_date; >- $end_date = $start_date; >- $start_date = $int_dt; >+ ($start_date, $end_date) = ($end_date, $start_date); > } > > my $schema = Koha::Database->new->schema; > my $dtf = $schema->storage->datetime_parser; >- $start_date = $dtf->format_datetime($start_date); >- $end_date = $dtf->format_datetime($end_date); >+ $start_date = $dtf->format_datetime($start_date->clone->truncate(to => 'day')); >+ $end_date = $dtf->format_datetime($end_date->clone->truncate(to => 'day')); > > my $days_between = $schema->resultset('DiscreteCalendar')->search( > { >@@ -1118,7 +1122,7 @@ sub open_hours_between { > my ($self, $start_date, $end_date) = @_; > my $branchcode = $self->{branchcode}; > my $schema = Koha::Database->new->schema; >- my $dtf = $schema->storage->datetime_parser; >+ my $dtf = DateTime::Format::Strptime->new(pattern => "%F %T"); > $start_date = $dtf->format_datetime($start_date); > $end_date = $dtf->format_datetime($end_date); > >diff --git a/Koha/Hold.pm b/Koha/Hold.pm >index a6dfab4..7198448 100644 >--- a/Koha/Hold.pm >+++ b/Koha/Hold.pm >@@ -62,7 +62,7 @@ sub age { > my $age; > > if ( $use_calendar ) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $self->branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $self->branchcode }); > $age = $calendar->days_between( dt_from_string( $self->reservedate ), $today ); > } > else { >@@ -164,7 +164,7 @@ sub set_waiting { > > my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay"); > my $cancel_on_holidays = C4::Context->preference('ExpireReservesOnHolidays'); >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $self->branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $self->branchcode }); > > my $expirationdate = $today->clone; > $expirationdate->add(days => $max_pickup_delay); >diff --git a/circ/returns.pl b/circ/returns.pl >index 5759de4..f0d410f 100755 >--- a/circ/returns.pl >+++ b/circ/returns.pl >@@ -203,7 +203,7 @@ my $dropboxmode = $query->param('dropboxmode'); > my $dotransfer = $query->param('dotransfer'); > my $canceltransfer = $query->param('canceltransfer'); > my $dest = $query->param('dest'); >-my $calendar = Koha::DiscreteCalendar->new( branchcode => $userenv_branch ); >+my $calendar = Koha::DiscreteCalendar->new({ branchcode => $userenv_branch }); > #dropbox: get last open day (today - 1) > my $today = DateTime->now( time_zone => C4::Context->tz()); > my $dropboxdate = $calendar->addDate($today, -1); >diff --git a/installer/data/mysql/atomicupdate/bug_17015_part1_create_discrete_calendar.sql b/installer/data/mysql/atomicupdate/bug_17015_part1_create_discrete_calendar.sql >index cd299c6..9956b4d 100644 >--- a/installer/data/mysql/atomicupdate/bug_17015_part1_create_discrete_calendar.sql >+++ b/installer/data/mysql/atomicupdate/bug_17015_part1_create_discrete_calendar.sql >@@ -11,4 +11,4 @@ CREATE TABLE `discrete_calendar` ( > `open_hour` time NOT NULL, > `close_hour` time NOT NULL, > PRIMARY KEY (`branchcode`,`date`) >-); >+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; >diff --git a/installer/data/mysql/atomicupdate/bug_17015_part2_fill_discrete_calendar.perl b/installer/data/mysql/atomicupdate/bug_17015_part2_fill_discrete_calendar.perl >index c7f823c..8a2485f 100755 >--- a/installer/data/mysql/atomicupdate/bug_17015_part2_fill_discrete_calendar.perl >+++ b/installer/data/mysql/atomicupdate/bug_17015_part2_fill_discrete_calendar.perl >@@ -3,8 +3,7 @@ > # > # Script that fills the discrete_calendar table with dates, using the other date-related tables > # >-use strict; >-use warnings; >+use Modern::Perl; > use DateTime; > use DateTime::Format::Strptime; > use Data::Dumper; >@@ -12,25 +11,8 @@ use Getopt::Long; > use C4::Context; > > # Options >-my $help = 0; > my $daysInFuture = 365; >-GetOptions ( >- 'days|?|d=i' => \$daysInFuture, >- 'help|?|h' => \$help); >-my $usage = << 'ENDUSAGE'; > >-Script that manages the discrete_calendar table. >- >-This script has the following parameters : >- --days --d : how many days in the future will be created, by default it's 365 >- -h --help: this message >- >-ENDUSAGE >- >-if ($help) { >- print $usage; >- exit; >-} > my $dbh = C4::Context->dbh; > $dbh->{AutoCommit} = 0; > $dbh->{RaiseError} = 1; >diff --git a/installer/data/mysql/atomicupdate/bug_17015_part3_drop_calendar.sql b/installer/data/mysql/atomicupdate/bug_17015_part3_drop_calendar.sql >new file mode 100644 >index 0000000..68da78b >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug_17015_part3_drop_calendar.sql >@@ -0,0 +1,5 @@ >+-- Bugzilla 17015 >+-- New koha calendar >+-- Drop deprecated calendar-related tables after creating and filling discrete_calendar >+DROP TABLE IF EXISTS `repeatable_holidays`; >+DROP TABLE IF EXISTS `special_holidays`; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 4b770d0..3ea11e1 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -680,6 +680,22 @@ CREATE TABLE `deleteditems` ( > ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; > > -- >+-- Table structure for table `discrete_calendar` >+-- >+ >+DROP TABLE IF EXISTS `discrete_calendar`; >+CREATE TABLE `discrete_calendar` ( >+ `date` datetime NOT NULL, >+ `branchcode` varchar(10) NOT NULL, >+ `is_opened` tinyint(1) DEFAULT 1, >+ `holiday_type` varchar(1) DEFAULT '', >+ `note` varchar(30) DEFAULT '', >+ `open_hour` time NOT NULL, >+ `close_hour` time NOT NULL, >+ PRIMARY KEY (`branchcode`,`date`) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; >+ >+-- > -- Table structure for table `export_format` > -- > >@@ -1379,22 +1395,6 @@ CREATE TABLE `printers_profile` ( > ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; > > -- >--- Table structure for table `repeatable_holidays` >--- >- >-DROP TABLE IF EXISTS `repeatable_holidays`; >-CREATE TABLE `repeatable_holidays` ( -- information for the days the library is closed >- `id` int(11) NOT NULL auto_increment, -- unique identifier assigned by Koha >- `branchcode` varchar(10) NOT NULL default '', -- foreign key from the branches table, defines which branch this closing is for >- `weekday` smallint(6) default NULL, -- day of the week (0=Sunday, 1=Monday, etc) this closing is repeated on >- `day` smallint(6) default NULL, -- day of the month this closing is on >- `month` smallint(6) default NULL, -- month this closing is in >- `title` varchar(50) NOT NULL default '', -- title of this closing >- `description` MEDIUMTEXT NOT NULL, -- description for this closing >- PRIMARY KEY (`id`) >-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; >- >--- > -- Table structure for table `reports_dictionary` > -- > >@@ -1948,23 +1948,6 @@ CREATE TABLE `reviews` ( -- patron opac comments > ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; > > -- >--- Table structure for table `special_holidays` >--- >- >-DROP TABLE IF EXISTS `special_holidays`; >-CREATE TABLE `special_holidays` ( -- non repeatable holidays/library closings >- `id` int(11) NOT NULL auto_increment, -- unique identifier assigned by Koha >- `branchcode` varchar(10) NOT NULL default '', -- foreign key from the branches table, defines which branch this closing is for >- `day` smallint(6) NOT NULL default 0, -- day of the month this closing is on >- `month` smallint(6) NOT NULL default 0, -- month this closing is in >- `year` smallint(6) NOT NULL default 0, -- year this closing is in >- `isexception` smallint(1) NOT NULL default 1, -- is this a holiday exception to a repeatable holiday (1 for yes, 0 for no) >- `title` varchar(50) NOT NULL default '', -- title for this closing >- `description` MEDIUMTEXT NOT NULL, -- description of this closing >- PRIMARY KEY (`id`) >-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; >- >--- > -- Table structure for table `statistics` > -- > >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 665a85c..9160de5 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -14372,7 +14372,7 @@ if( CheckVersion( $DBversion ) ) { > > my $expirationdate = dt_from_string($hold->waitingdate); > if ( C4::Context->preference("ExcludeHolidaysFromMaxPickUpDelay") ) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $hold->branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $hold->branchcode }); > $expirationdate = $calendar->days_forward( $expirationdate, $max_pickup_delay ); > } else { > $expirationdate->add( days => $max_pickup_delay ); >diff --git a/koha-tmpl/intranet-tmpl/prog/css/discretecalendar.css b/koha-tmpl/intranet-tmpl/prog/css/discretecalendar.css >new file mode 100644 >index 0000000..3b7625e >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/css/discretecalendar.css >@@ -0,0 +1,206 @@ >+#jcalendar-container .ui-datepicker { >+ font-size:185%; >+} >+ >+#holidayweeklyrepeatable, >+#holidaysyearlyrepeatable, >+#holidaysunique, >+#holidayexceptions { >+ font-size:90%; >+ margin-bottom:1em; >+} >+ >+#showHoliday { >+ margin:.5em 0; >+} >+ >+.key { >+ padding:3px; >+ white-space:nowrap; >+ line-height:230%; >+} >+ >+.ui-datepicker { >+ font-size:150%; >+} >+ >+.ui-datepicker th, >+.ui-datepicker .ui-datepicker-title select { >+ font-size:80%; >+} >+ >+.ui-datepicker td a { >+ padding:.5em; >+} >+ >+.ui-datepicker td span { >+ padding:.5em; >+ border:1px solid #BCBCBC; >+} >+ >+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { >+ font-size:80%; >+} >+ >+.key { >+ padding:3px; >+ white-space:nowrap; >+ line-height:230%; >+} >+ >+.normalday { >+ background-color:#EDEDED; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+.ui-datepicker-unselectable { >+ padding:.5em; >+ white-space:nowrap; >+} >+ >+.ui-state-disabled { >+ padding:.5em; >+ white-space:nowrap; >+} >+ >+.exception { >+ background-color:#b3d4ff; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+.past-date { >+ background-color:#e6e6e6; >+ color:#555; >+ border:1px solid #BCBCBC; >+} >+ >+td.past-date a.ui-state-default { >+ background:#e6e6e6; >+ color:#555; >+} >+ >+.float { >+ background-color:#6f3; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+.holiday { >+ background-color:#ffaeae; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+.repeatableweekly { >+ background-color:#FF9; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+.repeatableyearly { >+ background-color:#FC6; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+td.exception a.ui-state-default { >+ background:#b3d4ff none; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+td.float a.ui-state-default { >+ background:#6f3 none; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+td.holiday a.ui-state-default { >+ background:#ffaeae none; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+td.repeatableweekly a.ui-state-default { >+ background:#FF9 none; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+td.repeatableyearly a.ui-state-default { >+ background:#FC6 none; >+ color:#000; >+ border:1px solid #BCBCBC; >+} >+ >+.information { >+ background-color:#DCD2F1; >+ width:300px; >+ display:none; >+ border:1px solid #000; >+ color:#000; >+ font-size:8pt; >+ font-weight:700; >+ background-color:#FFD700; >+ cursor:pointer; >+ padding:2px; >+} >+ >+.panel { >+ z-index:1; >+ display:none; >+ border:3px solid #CCC; >+ padding:3px; >+ margin-top:.3em; >+ background-color:#FEFEFE; >+} >+ >+fieldset.brief { >+ border:0; >+ margin-top:0; >+} >+ >+h1 select { >+ width:20em; >+} >+ >+div.yui-b fieldset.brief ol { >+ font-size:100%; >+} >+ >+div.yui-b fieldset.brief li, >+div.yui-b fieldset.brief li.radio { >+ padding:.2em 0; >+} >+ >+.help { >+ margin:.3em 0; >+ border:1px solid #EEE; >+ padding:.3em .7em; >+ font-size:90%; >+} >+ >+.calendar td, >+.calendar th, >+.calendar .button, >+.calendar tbody .day { >+ padding:.7em; >+ font-size:110%; >+} >+ >+.calendar { >+ width:auto; >+ border:0; >+} >+ >+.copyHoliday form li { >+ display:table-row; >+} >+ >+.copyHoliday form li b, >+.copyHoliday form li input { >+ display:table-cell; >+ margin-bottom:2px; >+} >\ No newline at end of file >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/discrete_calendar.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/discrete_calendar.tt >index 5e7461c..9299b18 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/discrete_calendar.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/discrete_calendar.tt >@@ -1,115 +1,411 @@ > [% USE Branches %] >+[% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Koha › Tools › [% Branches.GetName( branch ) %] calendar</title> > [% INCLUDE 'doc-head-close.inc' %] > [% INCLUDE 'calendar.inc' %] >-<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/datatables.css" /> >-<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery-ui-timepicker-addon.min.js"></script> >+<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/datatables_[% KOHA_VERSION %].css" /> >+<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/discretecalendar_[% KOHA_VERSION %].css" /> > [% INCLUDE 'datatables.inc' %] >- <script type="text/javascript"> >- //<![CDATA[ >- var weekdays = new Array(_("Sundays"),_("Mondays"),_("Tuesdays"),_("Wednesdays"),_("Thursdays"),_("Fridays"),_("Saturdays")); >- // Array containing all the information about each date in the calendar. >- var datesInfos = new Array(); >- [% FOREACH date IN datesInfos %] >- datesInfos["[% date.date %]"] = { >- title : "[% date.note %]", >- outputdate : "[% date.outputdate %]", >- holiday_type:"[% date.holiday_type %]", >- open_hour: "[% date.open_hour %]", >- close_hour: "[% date.close_hour %]" >- }; >- [% END %] >+</head> > >- /** >- * Displays the details of the selected date on a side panel >- */ >- function showHoliday (date_obj, dateString, dayName, day, month, year, weekDay, title, holidayType) { >- $("#newHoliday").slideDown("fast"); >- $("#copyHoliday").slideUp("fast"); >- $('#newDaynameOutput').html(dayName); >- $('#newDayname').val(dayName); >- $('#newBranchNameOutput').html($("#branch :selected").text()); >- $(".newHoliday ,#branch").val($('#branch').val()); >- $('#newDayOutput').html(day); >- $(".newHoliday #Day").val(day); >- $(".newHoliday #Month").val(month); >- $(".newHoliday #Year").val(year); >- $("#newMonthOutput").html(month); >- $("#newYearOutput").html(year); >- $(".newHoliday, #Weekday").val(weekDay); >+<body id="tools_holidays" class="tools"> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'cat-search.inc' %] > >- $('.newHoliday #title').val(title); >- $('#HolidayType').val(holidayType); >- $('#days_of_week option[value="'+ (weekDay + 1) +'"]').attr('selected', true); >- $('#openHour').val(datesInfos[dateString].open_hour); >- $('#closeHour').val(datesInfos[dateString].close_hour); >- $('#local_today').val(getSeparetedDate(new Date()).dateString); >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> › [% Branches.GetName( branch ) %] calendar</div> > >- //This changes the label of the date type on the edit panel >- if(holidayType == 'W') { >- $("#holtype").attr("class","key repeatableweekly").html(_("Holiday repeating weekly")); >- } else if(holidayType == 'R') { >- $("#holtype").attr("class","key repeatableyearly").html(_("Holiday repeating yearly")); >- } else if(holidayType == 'F') { >- $("#holtype").attr("class","key float").html(_("Floating holiday")); >- } else if(holidayType == 'N') { >- $("#holtype").attr("class","key exception").html(_("Needs validation")); >- } else if(holidayType == 'E') { >- $("#holtype").attr("class","key holiday").html(_("Unique holiday")); >- } else{ >- $("#holtype").attr("class","key normalday").html(_("Working day ")); >- } >+<div id="doc3" class="yui-t1"> > >- //Select the correct holiday type on the dropdown menu >- if (datesInfos[dateString].holiday_type !=''){ >- var type = datesInfos[dateString].holiday_type; >- $('#holidayType option[value="'+ type +'"]').attr('selected', true) >- }else{ >- $('#holidayType option[value="none"]').attr('selected', true) >- } >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ <h2>[% Branches.GetName( branch ) %] calendar</h2> >+ <div class="yui-g"> >+ <div class="yui-u first" style="width:60%"> >+ <label for="branch">Define the holidays for:</label> >+ <form method="post" onsubmit="return validateForm('CopyCalendar')"> >+ <select id="branch" name="branch"> >+ [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %] >+ </select> >+ Copy calendar to >+ <select id='newBranch' name ='newBranch'> >+ <option value=""></option> >+ [% FOREACH l IN Branches.all() %] >+ [% UNLESS branch == l.branchcode %] >+ <option value="[% l.branchcode %]">[% l.branchname %]</option> >+ [% END %] >+ [% END %] >+ </select> >+ <input type="hidden" name="action" value="copyBranch" /> >+ <input type="submit" value="Clone"> >+ </form> >+ <h3>Calendar information</h3> >+ <div id="jcalendar-container" style="float: left"></div> >+ <!-- ***************************** Panel to deal with new holidays ********************** --> >+ [% UNLESS datesInfos %] >+ <div class="alert alert-danger" style="float: left; margin-left:15px"> >+ <strong>Error!</strong> You have to run generate_discrete_calendar.pl in order to use Discrete Calendar. >+ </div> >+ [% END %] > >- //If it is a weekly or repeatable holiday show the option to delete the type >- if(datesInfos[dateString].holiday_type == 'W' || datesInfos[dateString].holiday_type == 'R'){ >- $('#deleteType').show("fast"); >- }else{ >- $('#deleteType').hide("fast"); >- } >+ [% IF no_branch_selected %] >+ <div class="alert alert-danger" style="float: left; margin-left:15px"> >+ <strong>No library set!</strong> You are using the default calendar. >+ </div> >+ [% END %] > >- //This value is to disable and hide input when the date is in the past, because you can't edit it. >- var value = false; >- var today = new Date(); >- today.setHours(0,0,0,0); >- if(date_obj < today ){ >- $("#holtype").attr("class","key past-date").html(_("Past date")); >- $("#CopyRadioButton").attr("checked", "checked"); >- value = true; >- $(".CopyDatePanel").toggle(value); >- } >- $("#title").prop('disabled', value); >- $("#holidayType select").prop('disabled', value); >- $("#openHour").prop('disabled', value); >- $("#closeHour").prop('disabled', value); >- $("#EditRadioButton").parent().toggle(!value); >+ <div class="panel newHoliday" id="newHoliday" style="float: left; margin-left:15px"> >+ <form method="post" onsubmit="return validateForm('newHoliday')"> >+ <fieldset class="brief"> >+ <h3>Edit date details</h3> >+ <span id="holtype"></span> >+ <ol> >+ <li> >+ <strong>Library:</strong> >+ <span id="newBranchNameOutput"></span> >+ <input type="hidden" id="branch" name="branch" /> >+ </li> >+ <li> >+ <strong>From date:</strong> >+ <span id="newDaynameOutput"></span>, > >- } >+ [% IF ( dateformat == "us" ) %]<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>/<span id="newYearOutput"></span>[% ELSIF ( dateformat == "metric" ) %]<span id="newDayOutput"></span>/<span id="newMonthOutput"></span>/<span id="newYearOutput"></span>[% ELSIF ( dateformat == "dmydot" ) %]<span id="newDayOutput"></span>.<span id="newMonthOutput"></span>.<span id="newYearOutput"></span>[% ELSE %]<span id="newYearOutput"></span>/<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>[% END %] > >- function hidePanel(aPanelName) { >- $("#"+aPanelName).slideUp("fast"); >- } >+ <input type="hidden" id="newDayname" name="showDayname" /> >+ <input type="hidden" id="Day" name="Day" /> >+ <input type="hidden" id="Month" name="Month" /> >+ <input type="hidden" id="Year" name="Year" /> >+ </li> >+ <li class="dateinsert"> >+ <b>To date: </b> >+ <input type="text" id="from_copyToDatePicker" name="toDate" size="20" class="datepicker" /> >+ </li> >+ <li> >+ <label for="title">Title: </label><input type="text" name="Title" id="title" size="35" /> >+ </li> >+ <li id="holidayType"> >+ <label for="holidayType">Date type</label> >+ <select name ='holidayType'> >+ <option value="empty"></option> >+ <option value="none">Working day</option> >+ <option value="E">Unique holiday</option> >+ <option value="W">Weekly holiday</option> >+ <option value="R">Repeatable holiday</option> >+ <option value="F">Floating holiday</option> >+ <option value="N" disabled>Need validation</option> >+ </select> >+ </li> >+ <li id="days_of_week" style="display :none"> >+ <label for="day_of_week">Week day</label> >+ <select name ='day_of_week'> >+ <option value="everyday">Everyday</option> >+ <option value="1">Sundays</option> >+ <option value="2">Mondays</option> >+ <option value="3">Tuesdays</option> >+ <option value="4">Wednesdays</option> >+ <option value="5">Thursdays</option> >+ <option value="6">Fridays</option> >+ <option value="7">Saturdays</option> >+ </select> >+ </li> >+ <li class="radio" id="deleteType" style="display : none;" > >+ <input type="checkbox" name="deleteType" id="deleteType_checkbox" value="1" ><label for="deleteType_checkbox"> Delete this type</label> >+ <a href="#" class="helptext">[?]</a> >+ <div class="hint">Remove all repeated or weekly holidays of the selected date or week day <br> if working day is selected.</div> >+ </li> >+ <li> >+ <label for="openHour">Open hours: </label><input type="text" name="openHour" id='openHour' style="display :flex" > >+ </li> >+ <li> >+ <label for="closeHour">Close hours: </label><input type="text" name="closeHour" id='closeHour' style="display :flex" > >+ </li> >+ <li class="radio"> >+ <input type="radio" name="action" id="EditRadioButton" value="edit" checked/> >+ <label for="EditRadioButton">Edit selected dates</label> >+ </li> >+ <li class="radio"> >+ <input type="radio" name="action" id="CopyRadioButton" value="copyDates" /> >+ <label for="CopyRadioButton">Copy to different dates</label> >+ <div class="CopyDatePanel" style="display:none; padding-left:15px"> >+ <b>From : </b> >+ <input type="text" id="to_copyFromDatePicker" size="20" class="datepicker"/> >+ <b>To : </b> >+ <input type="text" id="to_copyToDatePicker" size="20" class="datepicker"/> >+ </div> >+ <input type="hidden" name="daysnumber" id='daysnumber'> >+ <!-- These yyyy-mm-dd --> >+ <input type="hidden" name="from_copyFrom" id='from_copyFrom'> >+ <input type="hidden" name="from_copyTo" id='from_copyTo'> >+ <input type="hidden" name="to_copyFrom" id='to_copyFrom'> >+ <input type="hidden" name="to_copyTo" id='to_copyTo'> >+ <input type="hidden" name="local_today" id='local_today'> >+ </li> >+ </ol> >+ <fieldset class="action"> >+ <input type="submit" name="submit" value="Save" /> >+ <a href="#" class="cancel hidePanel newHoliday">Cancel</a> >+ </fieldset> >+ </fieldset> >+ </form> >+ </div> > >- function changeBranch () { >- var branch = $("#branch option:selected").val(); >- location.href='/cgi-bin/koha/tools/discrete_calendar.pl?branch=' + branch + '&calendardate=' + "[% calendardate %]"; >- } >+<!-- ************************************************************************************** --> >+<!-- ****** MAIN SCREEN CODE ****** --> >+<!-- ************************************************************************************** --> > >- function Help() { >- newin=window.open("/cgi-bin/koha/help.pl","KohaHelp",'width=600,height=600,toolbar=false,scrollbars=yes'); >- } >+</div> >+<div class="yui-u" style="width : 40%"> >+ <div class="help"> >+ <h4>Hints</h4> >+ <ul> >+ <li>Search in the calendar the day you want to set as holiday.</li> >+ <li>Click the date to add or edit a holiday.</li> >+ <li>Specify how the holiday should repeat.</li> >+ <li>Click Save to finish.</li> >+ <li>PS: >+ <ul> >+ <li>You can't edit passed dates</li> >+ <li>Weekly holidays change open/close hours for all the days affected unless inputs are empty</li> >+ </ul> >+ </li> >+ </ul> >+ <h4>Key</h4> >+ <p> >+ <span class="key normalday">Working day </span> >+ <span class="key holiday">Unique holiday</span> >+ <span class="key repeatableweekly">Holiday repeating weekly</span> >+ <span class="key repeatableyearly">Holiday repeating yearly</span> >+ <span class="key float">Floating holiday</span> >+ <span class="key exception">Need validation</span> >+ </p> >+ </div> >+<div id="holiday-list"> > >- // This function gives css clases to each kind of day >- function dateStatusHandler(date) { >- date = getSeparetedDate(date); >+ [% IF ( NEED_VALIDATION_HOLIDAYS ) %] >+ <h3>Need validation holidays</h3> >+ <table id="holidaysunique"> >+ <thead> >+ <tr> >+ <th class="exception">Date</th> >+ <th class="exception">Title</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOREACH need_validation_holiday IN NEED_VALIDATION_HOLIDAYS %] >+ <tr> >+ <td><a href="#doc3" onclick="go_to_date('[% need_validation_holiday.date %]')"><span title="[% need_validation_holiday.DATE_SORT %]">[% need_validation_holiday.outputdate %]</span></a></td> >+ <td>[% need_validation_holiday.note %]</td> >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ [% END %] >+ >+ [% IF ( WEEKLY_HOLIDAYS ) %] >+ <h3>Weekly - Repeatable holidays</h3> >+ <table id="holidayweeklyrepeatable"> >+ <thead> >+ <tr> >+ <th class="repeatableweekly">Day of week</th> >+ <th class="repeatableweekly">Title</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOREACH WEEK_DAYS_LOO IN WEEKLY_HOLIDAYS %] >+ <tr> >+ <td>[% WEEK_DAYS_LOO.weekday %]</td> >+ </td> >+ <td>[% WEEK_DAYS_LOO.note %]</td> >+ </tr> >+ [% END %] >+ </tbody> >+</table> >+[% END %] >+ >+[% IF ( REPEATABLE_HOLIDAYS ) %] >+<h3>Yearly - Repeatable holidays</h3> >+<table id="holidaysyearlyrepeatable"> >+ <thead> >+ <tr> >+ [% IF ( dateformat == "metric" ) %] >+ <th class="repeatableyearly">Day/month</th> >+ [% ELSE %] >+ <th class="repeatableyearly">Month/day</th> >+ [% END %] >+ <th class="repeatableyearly">Title</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN REPEATABLE_HOLIDAYS %] >+ <tr> >+ [% IF ( dateformat == "metric" ) %] >+ <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT %]">[% DAY_MONTH_HOLIDAYS_LOO.day %]/[% DAY_MONTH_HOLIDAYS_LOO.month %]</span></td> >+ [% ELSE %] >+ <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT %]">[% DAY_MONTH_HOLIDAYS_LOO.month %]/[% DAY_MONTH_HOLIDAYS_LOO.day %]</span></td> >+ [% END %] >+ <td>[% DAY_MONTH_HOLIDAYS_LOO.note %]</td> >+ </tr> >+ [% END %] >+ </tbody> >+</table> >+[% END %] >+ >+[% IF ( UNIQUE_HOLIDAYS ) %] >+<h3>Unique holidays</h3> >+<table id="holidaysunique"> >+ <thead> >+ <tr> >+ <th class="holiday">Date</th> >+ <th class="holiday">Title</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOREACH HOLIDAYS_LOO IN UNIQUE_HOLIDAYS %] >+ <tr> >+ <td><a href="#doc3" onclick="go_to_date('[% HOLIDAYS_LOO.date %]')"><span title="[% HOLIDAYS_LOO.DATE_SORT %]">[% HOLIDAYS_LOO.outputdate %]</span></a></td> >+ <td>[% HOLIDAYS_LOO.note %]</td> >+ </tr> >+ [% END %] >+ </tbody> >+</table> >+[% END %] >+ >+[% IF ( FLOAT_HOLIDAYS ) %] >+<h3>Floating holidays</h3> >+<table id="holidaysunique"> >+ <thead> >+ <tr> >+ <th class="float">Date</th> >+ <th class="float">Title</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOREACH float_holiday IN FLOAT_HOLIDAYS %] >+ <tr> >+ <td><a href="#doc3" onclick="go_to_date('[% float_holiday.date %]')"><span title="[% float_holiday.DATE_SORT %]">[% float_holiday.outputdate %]</span></a></td> >+ <td>[% float_holiday.note %]</td> >+ </tr> >+ [% END %] >+ </tbody> >+</table> >+[% END %] >+</div> >+</div> >+</div> >+</div> >+</div> >+ >+<div class="yui-b noprint"> >+[% INCLUDE 'tools-menu.inc' %] >+</div> >+</div> >+[% MACRO jsinclude BLOCK %] >+<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery-ui-timepicker-addon.min_[% KOHA_VERSION %].js"></script> >+<script type="text/javascript"> >+ //<![CDATA[ >+ var weekdays = new Array(_("Sundays"),_("Mondays"),_("Tuesdays"),_("Wednesdays"),_("Thursdays"),_("Fridays"),_("Saturdays")); >+ // Array containing all the information about each date in the calendar. >+ var datesInfos = new Array(); >+ [% FOREACH date IN datesInfos %] >+ datesInfos["[% date.date %]"] = { >+ title : "[% date.note %]", >+ outputdate : "[% date.outputdate %]", >+ holiday_type:"[% date.holiday_type %]", >+ open_hour: "[% date.open_hour %]", >+ close_hour: "[% date.close_hour %]" >+ }; >+ [% END %] >+ >+ /** >+ * Displays the details of the selected date on a side panel >+ */ >+ function showHoliday (date_obj, dateString, dayName, day, month, year, weekDay, title, holidayType) { >+ $("#newHoliday").slideDown("fast"); >+ $("#copyHoliday").slideUp("fast"); >+ $('#newDaynameOutput').html(dayName); >+ $('#newDayname').val(dayName); >+ $('#newBranchNameOutput').html($("#branch :selected").text()); >+ $(".newHoliday ,#branch").val($('#branch').val()); >+ $('#newDayOutput').html(day); >+ $(".newHoliday #Day").val(day); >+ $(".newHoliday #Month").val(month); >+ $(".newHoliday #Year").val(year); >+ $("#newMonthOutput").html(month); >+ $("#newYearOutput").html(year); >+ $(".newHoliday, #Weekday").val(weekDay); >+ >+ $('.newHoliday #title').val(title); >+ $('#HolidayType').val(holidayType); >+ $('#days_of_week option[value="'+ (weekDay + 1) +'"]').attr('selected', true); >+ $('#openHour').val(datesInfos[dateString].open_hour); >+ $('#closeHour').val(datesInfos[dateString].close_hour); >+ $('#local_today').val(getSeparetedDate(new Date()).dateString); >+ >+ //This changes the label of the date type on the edit panel >+ if(holidayType == 'W') { >+ $("#holtype").attr("class","key repeatableweekly").html(_("Holiday repeating weekly")); >+ } else if(holidayType == 'R') { >+ $("#holtype").attr("class","key repeatableyearly").html(_("Holiday repeating yearly")); >+ } else if(holidayType == 'F') { >+ $("#holtype").attr("class","key float").html(_("Floating holiday")); >+ } else if(holidayType == 'N') { >+ $("#holtype").attr("class","key exception").html(_("Needs validation")); >+ } else if(holidayType == 'E') { >+ $("#holtype").attr("class","key holiday").html(_("Unique holiday")); >+ } else{ >+ $("#holtype").attr("class","key normalday").html(_("Working day ")); >+ } >+ >+ //Select the correct holiday type on the dropdown menu >+ if (datesInfos[dateString].holiday_type !=''){ >+ var type = datesInfos[dateString].holiday_type; >+ $('#holidayType option[value="'+ type +'"]').attr('selected', true) >+ }else{ >+ $('#holidayType option[value="none"]').attr('selected', true) >+ } >+ >+ //If it is a weekly or repeatable holiday show the option to delete the type >+ if(datesInfos[dateString].holiday_type == 'W' || datesInfos[dateString].holiday_type == 'R'){ >+ $('#deleteType').show("fast"); >+ }else{ >+ $('#deleteType').hide("fast"); >+ } >+ >+ //This value is to disable and hide input when the date is in the past, because you can't edit it. >+ var value = false; >+ var today = new Date(); >+ today.setHours(0,0,0,0); >+ if(date_obj < today ){ >+ $("#holtype").attr("class","key past-date").html(_("Past date")); >+ $("#CopyRadioButton").attr("checked", "checked"); >+ value = true; >+ $(".CopyDatePanel").toggle(value); >+ } >+ $("#title").prop('disabled', value); >+ $("#holidayType select").prop('disabled', value); >+ $("#openHour").prop('disabled', value); >+ $("#closeHour").prop('disabled', value); >+ $("#EditRadioButton").parent().toggle(!value); >+ >+ } >+ >+ function hidePanel(aPanelName) { >+ $("#"+aPanelName).slideUp("fast"); >+ } >+ >+ function changeBranch () { >+ var branch = $("#branch option:selected").val(); >+ location.href='/cgi-bin/koha/tools/discrete_calendar.pl?branch=' + branch + '&calendardate=' + "[% calendardate %]"; >+ } >+ >+ function Help() { >+ newin=window.open("/cgi-bin/koha/help.pl","KohaHelp",'width=600,height=600,toolbar=false,scrollbars=yes'); >+ } >+ >+ // This function gives css clases to each kind of day >+ function dateStatusHandler(date) { >+ date = getSeparetedDate(date); > var day = date.day; > var month = date.month; > var year = date.year; >@@ -297,7 +593,8 @@ > }, > defaultDate: new Date("[% keydate %]"), > minDate: new Date("[% minDate %]"), >- maxDate: new Date("[% maxDate %]") >+ maxDate: new Date("[% maxDate %]"), >+ dateFormat: "yy-mm-dd" > }); > //Main datepicker > $("#jcalendar-container").datepicker({ >@@ -375,413 +672,6 @@ > }); > }); > //]]> >- </script> >- <!-- Datepicker colors --> >- <style type="text/css"> >- #jcalendar-container .ui-datepicker { >- font-size : 185%; >- } >- #holidayweeklyrepeatable, #holidaysyearlyrepeatable, #holidaysunique, #holidayexceptions { >- font-size : 90%; margin-bottom : 1em; >- } >- #showHoliday { >- margin : .5em 0; >- } >- .key { >- padding : 3px; >- white-space:nowrap; >- line-height:230%; >- } >- .ui-datepicker { >- font-size : 150%; >- } >- .ui-datepicker th, .ui-datepicker .ui-datepicker-title select { >- font-size : 80%; >- } >- .ui-datepicker td a { >- padding : .5em; >- } >- .ui-datepicker td span { >- padding : .5em; >- border : 1px solid #BCBCBC; >- } >- .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { >- font-size : 80%; >- } >- .key { >- padding : 3px; white-space:nowrap; line-height:230%; >- } >- .normalday { >- background-color : #EDEDED; >- color : Black; >- border : 1px solid #BCBCBC; >- } >- .ui-datepicker-unselectable { >- padding :.5em; white-space:nowrap; >- } >- .ui-state-disabled { >- padding :.5em; white-space:nowrap; >- } >- .exception { >- background-color : #b3d4ff; color : Black; border : 1px solid #BCBCBC; >- } >- .past-date { >- background-color : #e6e6e6; color : #555555; border : 1px solid #BCBCBC; >- } >- td.past-date a.ui-state-default { >- background : #e6e6e6 ; color : #555555; >- } >- .float { >- background-color : #66ff33; color : Black; border : 1px solid #BCBCBC; >- } >- .holiday { >- background-color : #ffaeae; color : Black; border : 1px solid #BCBCBC; >- } >- .repeatableweekly { >- background-color : #FFFF99; color : Black; border : 1px solid #BCBCBC; >- } >- .repeatableyearly { >- background-color : #FFCC66; color : Black; border : 1px solid #BCBCBC; >- } >- td.exception a.ui-state-default { >- background: #b3d4ff none; color : Black; border : 1px solid #BCBCBC; >- } >- td.float a.ui-state-default { >- background: #66ff33 none; color : Black; border : 1px solid #BCBCBC; >- } >- td.holiday a.ui-state-default { >- background: #ffaeae none; color : Black; border : 1px solid #BCBCBC; >- } >- td.repeatableweekly a.ui-state-default { >- background: #FFFF99 none; color : Black; border : 1px solid #BCBCBC; >- } >- td.repeatableyearly a.ui-state-default { >- background: #FFCC66 none; color : Black; border : 1px solid #BCBCBC; >- } >- .information { >- z-index : ; background-color : #DCD2F1; width : 300px; display : none; border : 1px solid #000000; color : #000000; font-size : 8pt; font-weight : bold; background-color : #FFD700; cursor : pointer; padding : 2px; >- } >- .panel { >- z-index : 1; display : none; border : 3px solid #CCC; padding : 3px; margin-top: .3em; background-color: #FEFEFE; >- } >- fieldset.brief { >- border : 0; margin-top: 0; >- } >- h1 select { >- width: 20em; >- } >- div.yui-b fieldset.brief ol { >- font-size:100%; >- } >- div.yui-b fieldset.brief li, div.yui-b fieldset.brief li.radio { >- padding:0.2em 0; >- } >- .help { >- margin:.3em 0;border:1px solid #EEE;padding:.3em .7em; font-size : 90%; >- } >- .calendar td, .calendar th, .calendar .button, .calendar tbody .day { >- padding : .7em; font-size: 110%; >- } >- .calendar { width: auto; border : 0; >- } >- .copyHoliday form li{ >- display:table-row >- } >- .copyHoliday form li b, .copyHoliday form li input{ >- display:table-cell; margin-bottom: 2px; >- } >- </style> >-</head> >- >-<body id="tools_holidays" class="tools"> >-[% INCLUDE 'header.inc' %] >-[% INCLUDE 'cat-search.inc' %] >- >-<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> › [% Branches.GetName( branch ) %] calendar</div> >- >-<div id="doc3" class="yui-t1"> >- >- <div id="bd"> >- <div id="yui-main"> >- <div class="yui-b"> >- <h2>[% Branches.GetName( branch ) %] calendar</h2> >- <div class="yui-g"> >- <div class="yui-u first" style="width:60%"> >- <label for="branch">Define the holidays for:</label> >- <form method="post" onsubmit="return validateForm('CopyCalendar')"> >- <select id="branch" name="branch"> >- [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %] >- </select> >- Copy calendar to >- <select id='newBranch' name ='newBranch'> >- <option value=""></option> >- [% FOREACH l IN Branches.all() %] >- [% UNLESS branch == l.branchcode %] >- <option value="[% l.branchcode %]">[% l.branchname %]</option> >- [% END %] >- [% END %] >- </select> >- <input type="hidden" name="action" value="copyBranch" /> >- <input type="submit" value="Clone"> >- </form> >- <h3>Calendar information</h3> >- <div id="jcalendar-container" style="float: left"></div> >- <!-- ***************************** Panel to deal with new holidays ********************** --> >- [% UNLESS datesInfos %] >- <div class="alert alert-danger" style="float: left; margin-left:15px"> >- <strong>Error!</strong> You have to run generate_discrete_calendar.pl in order to use Discrete Calendar. >- </div> >- [% END %] >- >- [% IF no_branch_selected %] >- <div class="alert alert-danger" style="float: left; margin-left:15px"> >- <strong>No library set!</strong> You are using the default calendar. >- </div> >- [% END %] >- >- <div class="panel newHoliday" id="newHoliday" style="float: left; margin-left:15px"> >- <form method="post" onsubmit="return validateForm('newHoliday')"> >- <fieldset class="brief"> >- <h3>Edit date details</h3> >- <span id="holtype"></span> >- <ol> >- <li> >- <strong>Library:</strong> >- <span id="newBranchNameOutput"></span> >- <input type="hidden" id="branch" name="branch" /> >- </li> >- <li> >- <strong>From date:</strong> >- <span id="newDaynameOutput"></span>, >- >- [% IF ( dateformat == "us" ) %]<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>/<span id="newYearOutput"></span>[% ELSIF ( dateformat == "metric" ) %]<span id="newDayOutput"></span>/<span id="newMonthOutput"></span>/<span id="newYearOutput"></span>[% ELSIF ( dateformat == "dmydot" ) %]<span id="newDayOutput"></span>.<span id="newMonthOutput"></span>.<span id="newYearOutput"></span>[% ELSE %]<span id="newYearOutput"></span>/<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>[% END %] >- >- <input type="hidden" id="newDayname" name="showDayname" /> >- <input type="hidden" id="Day" name="Day" /> >- <input type="hidden" id="Month" name="Month" /> >- <input type="hidden" id="Year" name="Year" /> >- </li> >- <li class="dateinsert"> >- <b>To date: </b> >- <input type="text" id="from_copyToDatePicker" name="toDate" size="20" class="datepicker" /> >- </li> >- <li> >- <label for="title">Title: </label><input type="text" name="Title" id="title" size="35" /> >- </li> >- <li id="holidayType"> >- <label for="holidayType">Date type</label> >- <select name ='holidayType'> >- <option value="empty"></option> >- <option value="none">Working day</option> >- <option value="E">Unique holiday</option> >- <option value="W">Weekly holiday</option> >- <option value="R">Repeatable holiday</option> >- <option value="F">Floating holiday</option> >- <option value="N" disabled>Need validation</option> >- </select> >- </li> >- <li id="days_of_week" style="display :none"> >- <label for="day_of_week">Week day</label> >- <select name ='day_of_week'> >- <option value="everyday">Everyday</option> >- <option value="1">Sundays</option> >- <option value="2">Mondays</option> >- <option value="3">Tuesdays</option> >- <option value="4">Wednesdays</option> >- <option value="5">Thursdays</option> >- <option value="6">Fridays</option> >- <option value="7">Saturdays</option> >- </select> >- </li> >- <li class="radio" id="deleteType" style="display : none;" > >- <input type="checkbox" name="deleteType" id="deleteType_checkbox" value="1" ><label for="deleteType_checkbox"> Delete this type</label> >- <a href="#" class="helptext">[?]</a> >- <div class="hint">Remove all repeated or weekly holidays of the selected date or week day <br> if working day is selected.</div> >- </li> >- <li> >- <label for="openHour">Open hours: </label><input type="text" name="openHour" id='openHour' style="display :flex" > >- </li> >- <li> >- <label for="closeHour">Close hours: </label><input type="text" name="closeHour" id='closeHour' style="display :flex" > >- </li> >- <li class="radio"> >- <input type="radio" name="action" id="EditRadioButton" value="edit" checked/> >- <label for="EditRadioButton">Edit selected dates</label> >- </li> >- <li class="radio"> >- <input type="radio" name="action" id="CopyRadioButton" value="copyDates" /> >- <label for="CopyRadioButton">Copy to different dates</label> >- <div class="CopyDatePanel" style="display:none; padding-left:15px"> >- <b>From : </b> >- <input type="text" id="to_copyFromDatePicker" size="20" class="datepicker"/> >- <b>To : </b> >- <input type="text" id="to_copyToDatePicker" size="20" class="datepicker"/> >- </div> >- <input type="hidden" name="daysnumber" id='daysnumber'> >- <!-- These yyyy-mm-dd --> >- <input type="hidden" name="from_copyFrom" id='from_copyFrom'> >- <input type="hidden" name="from_copyTo" id='from_copyTo'> >- <input type="hidden" name="to_copyFrom" id='to_copyFrom'> >- <input type="hidden" name="to_copyTo" id='to_copyTo'> >- <input type="hidden" name="local_today" id='local_today'> >- </li> >- </ol> >- <fieldset class="action"> >- <input type="submit" name="submit" value="Save" /> >- <a href="#" class="cancel hidePanel newHoliday">Cancel</a> >- </fieldset> >- </fieldset> >- </form> >- </div> >- >-<!-- ************************************************************************************** --> >-<!-- ****** MAIN SCREEN CODE ****** --> >-<!-- ************************************************************************************** --> >- >-</div> >-<div class="yui-u" style="width : 40%"> >- <div class="help"> >- <h4>Hints</h4> >- <ul> >- <li>Search in the calendar the day you want to set as holiday.</li> >- <li>Click the date to add or edit a holiday.</li> >- <li>Specify how the holiday should repeat.</li> >- <li>Click Save to finish.</li> >- <li>PS: >- <ul> >- <li>You can't edit passed dates</li> >- <li>Weekly holidays change open/close hours for all the days affected unless inputs are empty</li> >- </ul> >- </li> >- </ul> >- <h4>Key</h4> >- <p> >- <span class="key normalday">Working day </span> >- <span class="key holiday">Unique holiday</span> >- <span class="key repeatableweekly">Holiday repeating weekly</span> >- <span class="key repeatableyearly">Holiday repeating yearly</span> >- <span class="key float">Floating holiday</span> >- <span class="key exception">Need validation</span> >- </p> >- </div> >-<div id="holiday-list"> >- >- [% IF ( NEED_VALIDATION_HOLIDAYS ) %] >- <h3>Need validation holidays</h3> >- <table id="holidaysunique"> >- <thead> >- <tr> >- <th class="exception">Date</th> >- <th class="exception">Title</th> >- </tr> >- </thead> >- <tbody> >- [% FOREACH need_validation_holiday IN NEED_VALIDATION_HOLIDAYS %] >- <tr> >- <td><a href="#doc3" onclick="go_to_date('[% need_validation_holiday.date %]')"><span title="[% need_validation_holiday.DATE_SORT %]">[% need_validation_holiday.outputdate %]</span></a></td> >- <td>[% need_validation_holiday.note %]</td> >- </tr> >- [% END %] >- </tbody> >- </table> >- [% END %] >- >- [% IF ( WEEKLY_HOLIDAYS ) %] >- <h3>Weekly - Repeatable holidays</h3> >- <table id="holidayweeklyrepeatable"> >- <thead> >- <tr> >- <th class="repeatableweekly">Day of week</th> >- <th class="repeatableweekly">Title</th> >- </tr> >- </thead> >- <tbody> >- [% FOREACH WEEK_DAYS_LOO IN WEEKLY_HOLIDAYS %] >- <tr> >- <td>[% WEEK_DAYS_LOO.weekday %]</td> >- </td> >- <td>[% WEEK_DAYS_LOO.note %]</td> >- </tr> >- [% END %] >- </tbody> >-</table> >-[% END %] >- >-[% IF ( REPEATABLE_HOLIDAYS ) %] >-<h3>Yearly - Repeatable holidays</h3> >-<table id="holidaysyearlyrepeatable"> >- <thead> >- <tr> >- [% IF ( dateformat == "metric" ) %] >- <th class="repeatableyearly">Day/month</th> >- [% ELSE %] >- <th class="repeatableyearly">Month/day</th> >- [% END %] >- <th class="repeatableyearly">Title</th> >- </tr> >- </thead> >- <tbody> >- [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN REPEATABLE_HOLIDAYS %] >- <tr> >- [% IF ( dateformat == "metric" ) %] >- <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT %]">[% DAY_MONTH_HOLIDAYS_LOO.day %]/[% DAY_MONTH_HOLIDAYS_LOO.month %]</span></td> >- [% ELSE %] >- <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT %]">[% DAY_MONTH_HOLIDAYS_LOO.month %]/[% DAY_MONTH_HOLIDAYS_LOO.day %]</span></td> >- [% END %] >- <td>[% DAY_MONTH_HOLIDAYS_LOO.note %]</td> >- </tr> >- [% END %] >- </tbody> >-</table> >+</script> > [% END %] >- >-[% IF ( UNIQUE_HOLIDAYS ) %] >-<h3>Unique holidays</h3> >-<table id="holidaysunique"> >- <thead> >- <tr> >- <th class="holiday">Date</th> >- <th class="holiday">Title</th> >- </tr> >- </thead> >- <tbody> >- [% FOREACH HOLIDAYS_LOO IN UNIQUE_HOLIDAYS %] >- <tr> >- <td><a href="#doc3" onclick="go_to_date('[% HOLIDAYS_LOO.date %]')"><span title="[% HOLIDAYS_LOO.DATE_SORT %]">[% HOLIDAYS_LOO.outputdate %]</span></a></td> >- <td>[% HOLIDAYS_LOO.note %]</td> >- </tr> >- [% END %] >- </tbody> >-</table> >-[% END %] >- >-[% IF ( FLOAT_HOLIDAYS ) %] >-<h3>Floating holidays</h3> >-<table id="holidaysunique"> >- <thead> >- <tr> >- <th class="float">Date</th> >- <th class="float">Title</th> >- </tr> >- </thead> >- <tbody> >- [% FOREACH float_holiday IN FLOAT_HOLIDAYS %] >- <tr> >- <td><a href="#doc3" onclick="go_to_date('[% float_holiday.date %]')"><span title="[% float_holiday.DATE_SORT %]">[% float_holiday.outputdate %]</span></a></td> >- <td>[% float_holiday.note %]</td> >- </tr> >- [% END %] >- </tbody> >-</table> >-[% END %] >-</div> >-</div> >-</div> >-</div> >-</div> >- >-<div class="yui-b noprint"> >-[% INCLUDE 'tools-menu.inc' %] >-</div> >-</div> > [% INCLUDE 'intranet-bottom.inc' %] >diff --git a/misc/cronjobs/add_days_discrete_calendar.pl b/misc/cronjobs/add_days_discrete_calendar.pl >index 83fd836..5d3849a 100755 >--- a/misc/cronjobs/add_days_discrete_calendar.pl >+++ b/misc/cronjobs/add_days_discrete_calendar.pl >@@ -3,8 +3,7 @@ > # > # This script adds one day into discrete_calendar table based on the same day from the week before > # >-use strict; >-use warnings; >+use Modern::Perl; > use DateTime; > use DateTime::Format::Strptime; > use Data::Dumper; >diff --git a/misc/cronjobs/fines.pl b/misc/cronjobs/fines.pl >index 4c5c20d..1db1820 100755 >--- a/misc/cronjobs/fines.pl >+++ b/misc/cronjobs/fines.pl >@@ -176,7 +176,7 @@ EOM > sub set_holiday { > my ( $branch, $dt ) = @_; > >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branch ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branch }); > return $calendar->is_holiday($dt); > } > >diff --git a/misc/cronjobs/overdue_notices.pl b/misc/cronjobs/overdue_notices.pl >index 48b6337..e663af0 100755 >--- a/misc/cronjobs/overdue_notices.pl >+++ b/misc/cronjobs/overdue_notices.pl >@@ -445,7 +445,7 @@ elsif ( defined $text_filename ) { > > foreach my $branchcode (@branches) { > if ( C4::Context->preference('OverdueNoticeCalendar') ) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branchcode }); > if ( $calendar->is_holiday($date_to_run) ) { > next; > } >@@ -546,7 +546,7 @@ END_SQL > my $days_between; > if ( C4::Context->preference('OverdueNoticeCalendar') ) > { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branchcode }); > $days_between = $calendar->days_between( dt_from_string($data->{date_due}), $date_to_run ); > } > else { >@@ -626,7 +626,7 @@ END_SQL > my $exceededPrintNoticesMaxLines = 0; > while ( my $item_info = $sth2->fetchrow_hashref() ) { > if ( C4::Context->preference('OverdueNoticeCalendar') ) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $branchcode ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $branchcode }); > $days_between = $calendar->days_between( dt_from_string( $item_info->{date_due} ), $date_to_run ); > } > else { >diff --git a/misc/cronjobs/staticfines.pl b/misc/cronjobs/staticfines.pl >index 1535790..1a960fb 100755 >--- a/misc/cronjobs/staticfines.pl >+++ b/misc/cronjobs/staticfines.pl >@@ -176,7 +176,7 @@ for ( my $i = 0 ; $i < scalar(@$data) ; $i++ ) { > > my $calendar; > unless ( defined( $calendars{$branchcode} ) ) { >- $calendars{$branchcode} = Koha::DiscreteCalendar->new( branchcode => $branchcode ); >+ $calendars{$branchcode} = Koha::DiscreteCalendar->new({ branchcode => $branchcode }); > } > $calendar = $calendars{$branchcode}; > my $isHoliday = $calendar->isHoliday( $tday, $tmonth, $tyear ); >diff --git a/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl b/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl >index 91e65a6..f8971f4 100755 >--- a/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl >+++ b/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl >@@ -294,7 +294,7 @@ sub GetWaitingHolds { > $sth->execute(); > my @results; > while ( my $issue = $sth->fetchrow_hashref() ) { >- my $calendar = Koha::DiscreteCalendar->new( branchcode => $issue->{'site'} ); >+ my $calendar = Koha::DiscreteCalendar->new({ branchcode => $issue->{'site'} }); > > my $waiting_date = dt_from_string( $issue->{waitingdate}, 'sql' ); > my $pickup_date = $waiting_date->clone->add( days => $pickupdelay ); >diff --git a/t/db_dependent/Circulation/CalcDateDue.t b/t/db_dependent/Circulation/CalcDateDue.t >index c6b6b52..5399472 100644 >--- a/t/db_dependent/Circulation/CalcDateDue.t >+++ b/t/db_dependent/Circulation/CalcDateDue.t >@@ -8,7 +8,8 @@ use DBI; > use DateTime; > use t::lib::Mocks; > use t::lib::TestBuilder; >-use C4::Calendar; >+use Koha::DateUtils; >+use Koha::DiscreteCalendar; > > use_ok('C4::Circulation'); > >@@ -39,12 +40,11 @@ t::lib::Mocks::mock_preference('useDaysMode', 'Days'); > my $cache = Koha::Caches->get_instance(); > $cache->clear_from_cache('single_holidays'); > >-my $dateexpiry = '2013-01-01'; >- >+my $dateexpiry = dt_from_string->truncate(to => 'day')->add(days => 30, hours => 23, minutes => 59)->iso8601; > my $borrower = {categorycode => 'B', dateexpiry => $dateexpiry}; >-my $start_date = DateTime->new({year => 2013, month => 2, day => 9}); >+my $start_date =dt_from_string->truncate(to => 'day')->add(days => 60); > my $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower ); >-is($date, $dateexpiry . 'T23:59:00', 'date expiry'); >+is($date, $dateexpiry, 'date expiry'); > $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 ); > > >@@ -53,31 +53,30 @@ t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1); > t::lib::Mocks::mock_preference('useDaysMode', 'noDays'); > > $borrower = {categorycode => 'B', dateexpiry => $dateexpiry}; >-$start_date = DateTime->new({year => 2013, month => 2, day => 9}); >+$start_date =dt_from_string->truncate(to => 'day')->add(days => 60); > $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower ); >-is($date, $dateexpiry . 'T23:59:00', 'date expiry with useDaysMode to noDays'); >+is($date, $dateexpiry, 'date expiry with useDaysMode to noDays'); > > # Let's add a special holiday on 2013-01-01. With ReturnBeforeExpiry and > # useDaysMode different from 'Days', return should forward the dateexpiry. >-my $calendar = C4::Calendar->new(branchcode => $branchcode); >-$calendar->insert_single_holiday( >- day => 1, >- month => 1, >- year => 2013, >- title =>'holidayTest', >- description => 'holidayDesc' >-); >+my $calendar = Koha::DiscreteCalendar->new({branchcode => $branchcode}); >+$calendar->edit_holiday({ >+ title => 'holidayTest', >+ holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, >+ start_date => dt_from_string->add(days=>30), >+ end_date => dt_from_string->add(days=>30) >+}); > $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower ); >-is($date, '2012-12-31T23:59:00', 'date expiry should be 2013-01-01 -1 day'); >-$calendar->insert_single_holiday( >- day => 31, >- month => 12, >- year => 2012, >- title =>'holidayTest', >- description => 'holidayDesc' >-); >+is($date, dt_from_string->truncate(to => 'day')->add(days=>29, hours=>23, minutes=>59), 'date expiry should be 2013-01-01 -1 day'); >+ >+$calendar->edit_holiday({ >+ title => 'holidayTest', >+ holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, >+ start_date => dt_from_string->add(days => 29), >+ end_date => dt_from_string->add(days => 29) >+}); > $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower ); >-is($date, '2012-12-30T23:59:00', 'date expiry should be 2013-01-01 -2 day'); >+is($date, dt_from_string->truncate(to => 'day')->add(days=> 28, hours=>23, minutes=>59), 'date expiry should be 2013-01-01 -2 day'); > > > $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 ); >diff --git a/t/db_dependent/DiscreteCalendar.t b/t/db_dependent/DiscreteCalendar.t >index a0fb1e4..e445303 100644 >--- a/t/db_dependent/DiscreteCalendar.t >+++ b/t/db_dependent/DiscreteCalendar.t >@@ -18,7 +18,7 @@ > # along with Koha; if not, see <http://www.gnu.org/licenses>. > > use Modern::Perl; >-use Test::More tests => 47; >+use Test::More tests => 50; > use Test::MockModule; > > use C4::Context; >@@ -53,8 +53,8 @@ isnt($branch1,'', "First branch to do tests. BranchCode => $branch1"); > isnt($branch2,'', "Second branch to do tests. BranchCode => $branch2"); > > #2 Calendars to make sure branches are treated separately. >-my $calendar = Koha::DiscreteCalendar->new(branchcode => $branch1); >-my $calendar2 = Koha::DiscreteCalendar->new(branchcode => $branch2); >+my $calendar = Koha::DiscreteCalendar->new({branchcode => $branch1}); >+my $calendar2 = Koha::DiscreteCalendar->new({branchcode => $branch2}); > > my $unique_holiday = DateTime->today; > $calendar->edit_holiday({ >@@ -68,6 +68,25 @@ is($calendar->is_opened($unique_holiday), 0, "Branch closed today : $unique_holi > my @unique_holidays = $calendar->get_unique_holidays(); > is(scalar @unique_holidays, 1, "Set of exception holidays at 1"); > >+my $yesterday = DateTime->today->subtract(days => 1); >+$calendar->edit_holiday({ >+ title => "Single holiday Today", >+ holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, >+ start_date => $yesterday, >+ end_date => $yesterday >+}); >+is($calendar->is_opened($yesterday), 1, "Cannot edit dates in the past without override : $yesterday is not a holiday"); >+ >+$calendar->edit_holiday({ >+ title => "Single holiday Today", >+ holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, >+ start_date => $yesterday, >+ end_date => $yesterday, >+ override => 1 >+}); >+is($calendar->is_opened($yesterday), 0, "Can edit dates in the past without override : $yesterday is a holiday"); >+ >+ > my $days_between_start = DateTime->today; > my $days_between_end = DateTime->today->add(days => 6); > my $days_between = $calendar->days_between($days_between_start, $days_between_end)->in_units('days'); >@@ -108,7 +127,7 @@ $calendar->edit_holiday({ > end_date=>$unique_holiday_range_end > }); > @unique_holidays = $calendar->get_unique_holidays(); >-is(scalar @unique_holidays, 7, "Set of exception holidays at 7"); >+is(scalar @unique_holidays, 8, "Set of exception holidays at 7"); > > my $repeatable_holiday_range_start = DateTime->today->add(days => 8); > my $repeatable_holiday_range_end = DateTime->today->add(days => 13); >@@ -126,12 +145,12 @@ is(scalar @repeatable_holidays, 7, "Set of repeatable holidays at 7"); > # item due : 2017-01-24 11:00:00 > # item returned : 2017-01-26 10:00:00 > # Branch closed : 2017-01-25 >-# Open/close hours : 8AM to 4PM (8h day) >+# Open/close hours : 08:00 to 16:00 (8h day) > # Hours due : 5 hours on 2017-01-24 + 2 hours on 2017-01-26 = 7hours > >-my $open_hours_since_start = DateTime->today->add(days => 40, hours => 11); >-my $open_hours_since_end = DateTime->today->add(days => 42, hours => 10); >-my $holiday_between = DateTime->today->add(days => 41); >+my $open_hours_since_start = dt_from_string->truncate(to => 'day')->add(days => 40, hours => 11); >+my $open_hours_since_end = dt_from_string->truncate(to => 'day')->add(days => 42, hours => 10); >+my $holiday_between = dt_from_string->truncate(to => 'day')->add(days => 41); > $calendar->edit_holiday({ > title => '', > holiday_type=>$Koha::DiscreteCalendar::HOLIDAYS->{NONE}, >@@ -199,6 +218,15 @@ $calendar->edit_holiday({ > }); > is($calendar->is_opened($today), 1, "Today's holiday was removed"); > >+$calendar->edit_holiday({ >+ title => '', >+ holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{NONE}, >+ start_date => $yesterday, >+ end_date => $yesterday, >+ override => 1 >+}); >+is($calendar->is_opened($yesterday), 1, "Yesterdays's holiday was removed with override"); >+ > my $new_open_hours = '08:00'; > $calendar->edit_holiday({ > title => '', >diff --git a/t/db_dependent/Hold.t b/t/db_dependent/Hold.t >index 1ec5d04..73c0e5c 100755 >--- a/t/db_dependent/Hold.t >+++ b/t/db_dependent/Hold.t >@@ -22,7 +22,7 @@ use C4::Context; > use C4::Biblio qw( AddBiblio ); > use Koha::Database; > use Koha::Libraries; >-use C4::Calendar; >+use Koha::DiscreteCalendar; > use Koha::Patrons; > use Koha::Holds; > use Koha::Item; >@@ -67,7 +67,7 @@ my $hold = Koha::Hold->new( > { > biblionumber => $biblionumber, > itemnumber => $item->id(), >- reservedate => '2017-01-01', >+ reservedate => dt_from_string->subtract(days => 2), > waitingdate => '2000-01-01', > borrowernumber => $borrower->{borrowernumber}, > branchcode => $branches[1]->{branchcode}, >@@ -76,11 +76,19 @@ my $hold = Koha::Hold->new( > ); > $hold->store(); > >-my $b1_cal = C4::Calendar->new( branchcode => $branches[1]->{branchcode} ); >-$b1_cal->insert_single_holiday( day => 02, month => 01, year => 2017, title => "Morty Day", description => "Rick" ); #Add a holiday >+my $b1_cal = Koha::DiscreteCalendar->new({ branchcode => $branches[1]->{branchcode} }); >+my $holiday = dt_from_string->subtract(days => 1); >+$b1_cal->edit_holiday({ >+ title => "Morty Day", >+ holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, >+ start_date => $holiday, >+ end_date => $holiday, >+ override => 1 >+}); #Add a holiday >+ > my $today = dt_from_string; >-is( $hold->age(), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days') , "Age of hold is days from reservedate to now if calendar ignored"); >-is( $hold->age(1), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days' ) - 1 , "Age of hold is days from reservedate to now minus 1 if calendar used"); >+is( $hold->age(), $today->delta_days( dt_from_string->subtract(days => 2) )->in_units( 'days' ), "Age of hold is days from reservedate to now if calendar ignored"); >+is( $hold->age(1), $today->delta_days( dt_from_string->subtract(days => 2) )->in_units( 'days' ) - 1, "Age of hold is days from reservedate to now minus 1 if calendar used"); > > is( $hold->suspend, 0, "Hold is not suspended" ); > $hold->suspend_hold(); >diff --git a/t/db_dependent/Holds.t b/t/db_dependent/Holds.t >index 1e6c234..c45b6fa 100755 >--- a/t/db_dependent/Holds.t >+++ b/t/db_dependent/Holds.t >@@ -12,7 +12,6 @@ use MARC::Record; > use C4::Biblio; > use C4::Items; > use C4::Members; >-use C4::Calendar; > use Koha::Database; > use Koha::DateUtils qw( dt_from_string output_pref ); > use Koha::Biblios; >diff --git a/t/db_dependent/HoldsQueue.t b/t/db_dependent/HoldsQueue.t >index ea6d547..ad32ebb 100755 >--- a/t/db_dependent/HoldsQueue.t >+++ b/t/db_dependent/HoldsQueue.t >@@ -200,9 +200,9 @@ $schema->resultset('DiscreteCalendar')->search({ > close_hour => '16:00:00' > }); > >-Koha::DiscreteCalendar->new( branchcode => '' )->add_new_branch('', $library1->{branchcode}); >-Koha::DiscreteCalendar->new( branchcode => '' )->add_new_branch('', $library2->{branchcode}); >-Koha::DiscreteCalendar->new( branchcode => '' )->add_new_branch('', $library3->{branchcode}); >+Koha::DiscreteCalendar->new({ branchcode => '' })->add_new_branch('', $library1->{branchcode}); >+Koha::DiscreteCalendar->new({ branchcode => '' })->add_new_branch('', $library2->{branchcode}); >+Koha::DiscreteCalendar->new({ branchcode => '' })->add_new_branch('', $library3->{branchcode}); > > @branchcodes = ( $library1->{branchcode}, $library2->{branchcode}, $library3->{branchcode} ); > >@@ -320,14 +320,14 @@ my $today = dt_from_string(); > > # If the test below is removed, aother tests using the holiday will fail. For some reason if we call is_holiday now > # the holiday will get set in cache correctly, but not if we let C4::HoldsQueue call is_holiday instead. >-Koha::DiscreteCalendar->new( branchcode => $branchcodes[0] )->edit_holiday({ >+Koha::DiscreteCalendar->new({ branchcode => $branchcodes[0] })->edit_holiday({ > title => "Today", >- holiday_type => "E", >+ holiday_type => $Koha::DiscreteCalendar::HOLIDAYS->{EXCEPTION}, > start_date => $today, > end_date => $today > }); > >-is( Koha::DiscreteCalendar->new( branchcode => $branchcodes[0] )->is_holiday( $today ), 1, 'Is today a holiday for pickup branch' ); >+is( Koha::DiscreteCalendar->new({ branchcode => $branchcodes[0] })->is_holiday( $today ), 1, 'Is today a holiday for pickup branch' ); > C4::HoldsQueue::CreateQueue(); > $holds_queue = $dbh->selectall_arrayref("SELECT * FROM tmp_holdsqueue", { Slice => {} }); > is( scalar( @$holds_queue ), 1, "Holds not filled with items from closed libraries" ); >diff --git a/tools/discrete_calendar.pl b/tools/discrete_calendar.pl >index 2168e42..fa40c9b 100755 >--- a/tools/discrete_calendar.pl >+++ b/tools/discrete_calendar.pl >@@ -16,8 +16,7 @@ > # along with Koha; if not, see <http://www.gnu.org/licenses>. > > #####Sets holiday periods for each branch. Datedues will be extended if branch is closed -TG >-use strict; >-use warnings; >+use Modern::Perl; > > use CGI qw ( -utf8 ); > >@@ -40,7 +39,7 @@ my ($template, $loggedinuser, $cookie) > }); > > my $branch = $input->param('branch') || C4::Context->userenv->{'branch'}; >-my $calendar = Koha::DiscreteCalendar->new(branchcode => $branch); >+my $calendar = Koha::DiscreteCalendar->new({branchcode => $branch}); > #alert the user that they are using the default calendar because they do not have a library set > my $no_branch_selected = $calendar->{no_branch_selected}; > >@@ -89,6 +88,8 @@ if($action eq 'copyBranch'){ > $endDate = $startDate->clone(); > } > >+ warn $startDate; >+ warn $endDate; > $calendar->edit_holiday( { > title => $title, > weekday => $weekday, >-- >2.7.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 17015
:
53859
|
54318
|
54419
|
59166
|
59167
|
59168
|
59169
|
59170
|
59171
|
59267
|
59268
|
59269
|
59270
|
59271
|
59463
|
59516
|
59517
|
59518
|
59519
|
59520
|
59561
|
59562
|
59586
|
59587
|
59888
|
59889
|
60902
|
60903
|
60904
|
60905
|
60906
|
60986
|
61737
|
62375
|
62376
|
62380
|
63257
|
63282
|
63362
|
63363
|
63364
|
63365
|
63366
|
63367
|
64235
|
65073
|
65074
|
65075
|
65076
|
65077
|
67721
|
67722
|
67723
|
67724
|
67725
|
67879
|
67929
|
67930
|
67931
|
67932
|
67933
|
67934
|
68392
|
68393
|
68394
|
68395
|
68396
|
68397
|
71634
|
71635
|
71636
|
71637
|
71638
|
72890
|
73145
|
74859
|
74860
|
74861
|
74862
|
74863
|
74864
|
74865
|
74866
|
75444
|
75479
|
76594
|
77249
|
77250
|
77607
|
77608
|
77609
|
77610
|
77611
|
77612
|
77613
|
77770
|
77771
|
77772
|
77773
|
77774
|
79035
|
80523
|
80524
|
80525
|
80526
|
80527
|
80528
|
80529
|
80530
|
80531
|
80532
|
80533
|
80534
|
80535
|
83547
|
85394
|
85677
|
85678
|
85679
|
85680
|
85681
|
85682
|
85683
|
85684
|
85685
|
85686
|
85687
|
85688
|
85689
|
85690
|
85691
|
92595
|
92596
|
92597
|
92598
|
100079
|
110383
|
110384
|
110386
|
110387
|
110388
|
110389
|
113541
|
113905
|
115501
|
115502
|
115503
|
115504
|
115505
|
115506
|
115507
|
115508
|
115509
|
115510
|
115511
|
118554
|
118555
|
118556
|
118557
|
118558
|
118559
|
119095
|
119097
|
119099
|
119100
|
119101
|
119102
|
131619
|
131620
|
131621
|
131622
|
131623
|
131624
|
131625
|
131626
|
131634
|
131635
|
131636
|
131637
|
131638
|
131639
|
131640
|
131641
|
131667
|
132199
|
133596
|
133597
|
133598
|
133599
|
133600
|
133601
|
133602
|
133603
|
133604
|
133605
|
133678
|
137219
|
137220
|
137221
|
137222
|
137223
|
137224
|
137225
|
137226
|
137227
|
137228
|
137229
|
139378
|
139379
|
139380
|
139381
|
139382
|
139599
|
139600
|
139601
|
139602
|
139603
|
139851
|
140150
|
141176
|
144257
|
144258
|
144259
|
144260
|
144261
|
144262
|
144264
|
144268
|
144269
|
144270
|
144271
|
144272
|
144273
|
151438
|
151439
|
151440
|
151441
|
151442
|
151443
|
151444
|
151445
|
151446
|
151447
|
151448
|
151449
|
151450
|
156340
|
156341
|
156342
|
156343
|
156344
|
156345
|
156346
|
156347
|
156348
|
156349
|
156350
|
156351
|
156352
|
156353
|
156354
|
156355
|
157656
|
157657
|
157658
|
157659
|
157660
|
157661
|
157662
|
157663
|
157664
|
157665
|
157666
|
157667
|
157668
|
157669
|
157670
|
157671
|
157672
|
167805
|
167806
|
167807
|
167808
|
167809