@@ -, +, @@
works as expected.
---
C4/Calendar.pm | 738 ++++----------------
C4/Circulation.pm | 88 ---
C4/Overdues.pm | 124 ----
Koha/Calendar.pm | 342 ++++-----
.../data/mysql/de-DE/optional/sample_holidays.sql | 10 +-
.../data/mysql/en/optional/sample_holidays.sql | 8 +-
.../data/mysql/es-ES/optional/sample_holidays.sql | 8 +-
.../data/mysql/it-IT/necessari/sample_holidays.sql | 10 +-
installer/data/mysql/kohastructure.sql | 70 +-
.../mysql/nb-NO/2-Valgfritt/sample_holidays.sql | 14 +-
.../data/mysql/pl-PL/optional/sample_holidays.sql | 8 +-
installer/data/mysql/ru-RU/optional/holidays.sql | 30 +-
installer/data/mysql/uk-UA/optional/holidays.sql | 42 +-
installer/data/mysql/updatedatabase.pl | 75 ++
.../intranet-tmpl/prog/en/includes/tools-menu.inc | 2 +-
.../prog/en/modules/tools/calendar.tt | 597 ++++++++++++++++
.../prog/en/modules/tools/holidays.tt | 538 --------------
.../prog/en/modules/tools/tools-home.tt | 2 +-
misc/cronjobs/staticfines.pl | 11 +-
.../thirdparty/TalkingTech_itiva_outbound.pl | 31 +-
t/Calendar.t | 143 +++-
t/db_dependent/Calendar.t | 78 +++
t/db_dependent/lib/KohaTest/Calendar/New.pm | 186 -----
t/db_dependent/lib/KohaTest/Circulation.pm | 3 -
t/db_dependent/lib/KohaTest/Overdues.pm | 3 -
tools/calendar.pl | 255 +++++++
tools/copy-holidays.pl | 39 --
tools/exceptionHolidays.pl | 145 ----
tools/holidays.pl | 163 -----
tools/newHolidays.pl | 144 ----
30 files changed, 1539 insertions(+), 2368 deletions(-)
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt
delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt
create mode 100644 t/db_dependent/Calendar.t
delete mode 100644 t/db_dependent/lib/KohaTest/Calendar/New.pm
create mode 100755 tools/calendar.pl
delete mode 100755 tools/copy-holidays.pl
delete mode 100755 tools/exceptionHolidays.pl
delete mode 100755 tools/holidays.pl
delete mode 100755 tools/newHolidays.pl
--- a/C4/Calendar.pm
+++ a/C4/Calendar.pm
@@ -15,712 +15,210 @@ package C4::Calendar;
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA 02111-1307 USA
-use strict;
-use warnings;
+use Modern::Perl;
use vars qw($VERSION @EXPORT);
use Carp;
-use Date::Calc qw( Date_to_Days Today);
use C4::Context;
+our ( @ISA, @EXPORT );
+
+BEGIN {
+ @ISA = qw( Exporter );
+ @EXPORT = qw(
+ GetSingleEvents
+ GetWeeklyEvents
+ GetYearlyEvents
+ ModSingleEvent
+ ModRepeatingEvent
+ DelSingleEvent
+ DelRepeatingEvent
+ CopyAllEvents
+ );
+}
+
use constant ISO_DATE_FORMAT => "%04d-%02d-%02d";
=head1 NAME
-C4::Calendar::Calendar - Koha module dealing with holidays.
+C4::Calendar - Koha module dealing with holidays.
=head1 SYNOPSIS
- use C4::Calendar::Calendar;
+ use C4::Calendar;
=head1 DESCRIPTION
-This package is used to deal with holidays. Through this package, you can set
-all kind of holidays for the library.
+This package is used to deal with hours and holidays;
=head1 FUNCTIONS
-=head2 new
+=head2 GetSingleEvents
- $calendar = C4::Calendar->new(branchcode => $branchcode);
+ \@events = GetSingleEvents( $branchcode )
-Each library branch has its own Calendar.
-C<$branchcode> specifies which Calendar you want.
+Get the non-repeating events for the given library.
=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 GetSingleEvents {
+ my ( $branchcode ) = @_;
-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;
+ return C4::Context->dbh->selectall_arrayref( q{
+ SELECT
+ event_date, open_hour, open_minute, close_hour, close_minute, title, description,
+ (open_hour = 0 AND open_minute = 0 AND close_hour = 0 AND close_minute = 0) AS closed
+ FROM calendar_events
+ WHERE branchcode = ?
+ }, { Slice => {} }, $branchcode );
}
-=head2 get_week_days_holidays
+=head2 GetWeeklyEvents
- $week_days_holidays = $calendar->get_week_days_holidays();
+ \@events = GetWeeklyEvents( $branchcode )
-Returns a hash reference to week days holidays.
+Get the weekly-repeating events for the given library.
=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 GetWeeklyEvents {
+ my ( $branchcode ) = @_;
-sub get_day_month_holidays {
- my $self = shift @_;
- my $day_month_holidays = $self->{'day_month_holidays'};
- return $day_month_holidays;
+ return C4::Context->dbh->selectall_arrayref( q{
+ SELECT
+ weekday, open_hour, open_minute, close_hour, close_minute, title, description,
+ (open_hour = 0 AND open_minute = 0 AND close_hour = 0 AND close_minute = 0) AS closed
+ FROM calendar_repeats
+ WHERE branchcode = ? AND weekday IS NOT NULL
+ }, { Slice => {} }, $branchcode );
}
-=head2 get_exception_holidays
+=head2 GetYearlyEvents
- $exception_holidays = $calendar->exception_holidays();
+ \@events = GetYearlyEvents( $branchcode )
-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.
+Get the yearly-repeating events for the given library.
=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();
+sub GetYearlyEvents {
+ my ( $branchcode ) = @_;
-Returns a hash reference to single holidays. This kind of holidays are those which
-happend just one time.
-
-=cut
-
-sub get_single_holidays {
- my $self = shift @_;
- my $single_holidays = $self->{'single_holidays'};
- return $single_holidays;
+ return C4::Context->dbh->selectall_arrayref( q{
+ SELECT
+ month, day, open_hour, open_minute, close_hour, close_minute, title, description,
+ (open_hour = 0 AND open_minute = 0 AND close_hour = 0 AND close_minute = 0) AS closed
+ FROM calendar_repeats
+ WHERE branchcode = ? AND weekday IS NULL
+ }, { Slice => {} }, $branchcode );
}
-=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.
+=head2 ModSingleEvent
-C<$title> Is the title to store for the holiday formed by $year/$month/$day.
+ ModSingleEvent( $branchcode, $date, \%info )
-C<$description> Is the description to store for the holiday formed by $year/$month/$day.
+Creates or updates an event for a single date. $date should be an ISO-formatted
+date string, and \%info should contain the following keys: open_hour,
+open_minute, close_hour, close_minute, title and description.
=cut
-sub insert_week_day_holiday {
- my $self = shift @_;
- my %options = @_;
+sub ModSingleEvent {
+ my ( $branchcode, $date, $info ) = @_;
- my $weekday = $options{weekday};
- croak "Invalid weekday $weekday" unless $weekday =~ m/^[0-6]$/;
-
- my $dbh = C4::Context->dbh();
- my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ( '',?,?,NULL,NULL,?,? )");
- $insertHoliday->execute( $self->{branchcode}, $weekday, $options{title}, $options{description});
- $self->{'week_days_holidays'}->{$weekday}{title} = $options{title};
- $self->{'week_days_holidays'}->{$weekday}{description} = $options{description};
- return $self;
+ C4::Context->dbh->do( q{
+ INSERT INTO calendar_events(branchcode, event_date, open_hour, open_minute, close_hour, close_minute, title, description)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+ ON DUPLICATE KEY UPDATE open_hour = ?, open_minute = ?, close_hour = ?, close_minute = ?, title = ?, description = ?
+ }, {}, $branchcode, $date, ( map { $info->{$_} } qw(open_hour open_minute close_hour close_minute title description) ) x 2 );
}
-=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.
+=head2 ModRepeatingEvent
-C<$title> Is the title to store for the holiday formed by $year/$month/$day.
+ ModRepeatingEvent( $branchcode, $weekday, $month, $day, \%info )
-C<$description> Is the description to store for the holiday formed by $year/$month/$day.
+Creates or updates a weekly- or yearly-repeating event. Either $weekday,
+or $month and $day should be set, for a weekly or yearly event, respectively.
=cut
-sub insert_day_month_holiday {
- my $self = shift @_;
- my %options = @_;
+sub ModRepeatingEvent {
+ my ( $branchcode, $weekday, $month, $day, $info ) = @_;
- my $dbh = C4::Context->dbh();
- my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ('', ?, NULL, ?, ?, ?,? )");
- $insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{title}, $options{description});
- $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{title} = $options{title};
- $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{description} = $options{description};
- return $self;
+ C4::Context->dbh->do( q{
+ INSERT INTO calendar_repeats(branchcode, weekday, month, day, open_hour, open_minute, close_hour, close_minute, title, description)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ ON DUPLICATE KEY UPDATE open_hour = ?, open_minute = ?, close_hour = ?, close_minute = ?, title = ?, description = ?
+ }, {}, $branchcode, $weekday, $month, $day, ( map { $info->{$_} } qw(open_hour open_minute close_hour close_minute title description) ) x 2 );
}
-=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.
+=head2 DelSingleEvent
-C<$year> Is year to make the date to insert.
+ DelSingleEvent( $branchcode, $date, \%info )
-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.
+Deletes an event for a single date. $date should be an ISO-formatted date string.
=cut
-sub insert_single_holiday {
- my $self = shift @_;
- my %options = @_;
-
- @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o )
- if $options{date} && !$options{day};
-
- my $dbh = C4::Context->dbh();
- my $isexception = 0;
- my $insertHoliday = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)");
- $insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $options{description});
- $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
- $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
- return $self;
-}
-
-=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.
+sub DelSingleEvent {
+ my ( $branchcode, $date ) = @_;
-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 (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)");
- $insertException->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $options{description});
- $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
- $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
- return $self;
+ C4::Context->dbh->do( q{
+ DELETE FROM calendar_events
+ WHERE branchcode = ? AND event_date = ?
+ }, {}, $branchcode, $date );
}
-=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.
+sub _get_compare {
+ my ( $colname, $value ) = @_;
-=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;
+ return ' AND ' . $colname . ' ' . ( defined( $value ) ? '=' : 'IS' ) . ' ?';
}
-=head2 ModDaymonthholiday
-
- ModDaymonthholiday(day => $day,
- month => $month,
- title => $title,
- description => $description);
-
-Modifies the title and description for a day/month holiday for $self->{branchcode}.
+=head2 DelRepeatingEvent
-C<$day> The day of the month for the update.
+ DelRepeatingEvent( $branchcode, $weekday, $month, $day )
-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.
+Deletes a weekly- or yearly-repeating event. Either $weekday, or $month and
+$day should be set, for a weekly or yearly event, respectively.
=cut
-sub ModDaymonthholiday {
- my $self = shift @_;
- my %options = @_;
+sub DelRepeatingEvent {
+ my ( $branchcode, $weekday, $month, $day ) = @_;
- 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;
+ C4::Context->dbh->do( q{
+ DELETE FROM calendar_repeats
+ WHERE branchcode = ?
+ } . _get_compare( 'weekday', $weekday ) . _get_compare( 'month', $month ) . _get_compare( 'day', $day ), {}, $branchcode, $weekday, $month, $day );
}
-=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}.
+=head2 CopyAllEvents
-C<$day> Is the day of the month to make the update.
+ CopyAllEvents( $from_branchcode, $to_branchcode )
-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.
+Copies all events from one branch to another.
=cut
-sub ModSingleholiday {
- my $self = shift @_;
- my %options = @_;
-
- my $dbh = C4::Context->dbh();
- my $isexception = 0;
- my $updateHoliday = $dbh->prepare("UPDATE special_holidays SET title = ?, description = ? WHERE day = ? AND month = ? AND year = ? AND branchcode = ? AND isexception = ?");
- $updateHoliday->execute($options{title},$options{description},$options{day},$options{month},$options{year},$self->{branchcode},$isexception);
- $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
- $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
- return $self;
-}
-
-=head2 ModExceptionholiday
-
- ModExceptionholiday(day => $day,
- month => $month,
- year => $year,
- title => $title,
- description => $description);
-
-Modifies the title and description for an exception holiday for $self->{branchcode}.
-
-C<$day> Is the day of the month for the holiday.
-
-C<$month> Is the month for the holiday.
+sub CopyAllEvents {
+ my ( $from_branchcode, $to_branchcode ) = @_;
-C<$year> Is the year for the holiday.
+ C4::Context->dbh->do( q{
+ INSERT IGNORE INTO calendar_events(branchcode, event_date, open_hour, open_minute, close_hour, close_minute, title, description)
+ SELECT ?, event_date, open_hour, open_minute, close_hour, close_minute, title, description
+ FROM calendar_events
+ WHERE branchcode = ?
+ }, {}, $to_branchcode, $from_branchcode );
-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};
- return $self;
+ C4::Context->dbh->do( q{
+ INSERT IGNORE INTO calendar_repeats(branchcode, weekday, month, day, open_hour, open_minute, close_hour, close_minute, title, description)
+ SELECT ?, weekday, month, day, open_hour, open_minute, close_hour, close_minute, title, description
+ FROM calendar_repeats
+ WHERE branchcode = ?
+ }, {}, $to_branchcode, $from_branchcode );
}
-=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}"});
- }
- }
- }
- return $self;
-}
-=head2 delete_holiday_range
-
- delete_holiday_range(day => $day,
- month => $month,
- year => $year);
-
-Delete a holiday range of dates for $self->{branchcode}.
-
-C<$day> Is the day month to make the date to delete.
-
-C<$month> Is month to make the date to delete.
-
-C<$year> Is year to make the date to delete.
-
-=cut
-
-sub delete_holiday_range {
- my $self = shift;
- my %options = @_;
-
- my $dbh = C4::Context->dbh();
- my $sth = $dbh->prepare("DELETE FROM special_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?) AND (year = ?)");
- $sth->execute($self->{branchcode}, $options{day}, $options{month}, $options{year});
-}
-
-=head2 delete_holiday_range_repeatable
-
- 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});
-}
-
-=head2 isHoliday
-
- $isHoliday = isHoliday($day, $month $year);
-
-C<$day> Is the day to check whether if is a holiday or not.
-
-C<$month> Is the month to check whether if is a holiday or not.
-
-C<$year> Is the year to check whether if is a holiday or not.
-
-=cut
-
-sub isHoliday {
- my ($self, $day, $month, $year) = @_;
- # FIXME - date strings are stored in non-padded metric format. should change to iso.
- # FIXME - should change arguments to accept C4::Dates object
- $month=$month+0;
- $year=$year+0;
- $day=$day+0;
- my $weekday = &Date::Calc::Day_of_Week($year, $month, $day) % 7;
- my $weekDays = $self->get_week_days_holidays();
- my $dayMonths = $self->get_day_month_holidays();
- my $exceptions = $self->get_exception_holidays();
- my $singles = $self->get_single_holidays();
- if (defined($exceptions->{"$year/$month/$day"})) {
- return 0;
- } else {
- if ((exists($weekDays->{$weekday})) ||
- (exists($dayMonths->{"$month/$day"})) ||
- (exists($singles->{"$year/$month/$day"}))) {
- return 1;
- } else {
- return 0;
- }
- }
-
-}
-
-=head2 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;
-}
-
-=head2 addDate
-
- my ($day, $month, $year) = $calendar->addDate($date, $offset)
-
-C<$date> is a C4::Dates object representing the starting date of the interval.
-
-C<$offset> Is the number of days that this function has to count from $date.
-
-=cut
-
-sub addDate {
- my ($self, $startdate, $offset) = @_;
- my ($year,$month,$day) = split("-",$startdate->output('iso'));
- my $daystep = 1;
- if ($offset < 0) { # In case $offset is negative
- # $offset = $offset*(-1);
- $daystep = -1;
- }
- my $daysMode = C4::Context->preference('useDaysMode');
- if ($daysMode eq 'Datedue') {
- ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset );
- while ($self->isHoliday($day, $month, $year)) {
- ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep);
- }
- } elsif($daysMode eq 'Calendar') {
- while ($offset != 0) {
- ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep);
- if (!($self->isHoliday($day, $month, $year))) {
- $offset = $offset - $daystep;
- }
- }
- } else { ## ($daysMode eq 'Days')
- ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset );
- }
- return(C4::Dates->new( sprintf(ISO_DATE_FORMAT,$year,$month,$day),'iso'));
-}
-
-=head2 daysBetween
-
- my $daysBetween = $calendar->daysBetween($startdate, $enddate)
-
-C<$startdate> and C<$enddate> are C4::Dates objects that define the interval.
-
-Returns the number of non-holiday days in the interval.
-useDaysMode syspref has no effect here.
-=cut
-
-sub daysBetween {
- my $self = shift or return;
- my $startdate = shift or return;
- my $enddate = shift or return;
- my ($yearFrom,$monthFrom,$dayFrom) = split("-",$startdate->output('iso'));
- my ($yearTo, $monthTo, $dayTo ) = split("-", $enddate->output('iso'));
- if (Date_to_Days($yearFrom,$monthFrom,$dayFrom) > Date_to_Days($yearTo,$monthTo,$dayTo)) {
- return 0;
- # we don't go backwards ( FIXME - handle this error better )
- }
- my $count = 0;
- while (1) {
- ($yearFrom != $yearTo or $monthFrom != $monthTo or $dayFrom != $dayTo) or last; # if they all match, it's the last day
- unless ($self->isHoliday($dayFrom, $monthFrom, $yearFrom)) {
- $count++;
- }
- ($yearFrom, $monthFrom, $dayFrom) = &Date::Calc::Add_Delta_Days($yearFrom, $monthFrom, $dayFrom, 1);
- }
- return($count);
-}
1;
--- a/C4/Circulation.pm
+++ a/C4/Circulation.pm
@@ -3101,94 +3101,6 @@ sub CalcDateDue {
}
-=head2 CheckRepeatableHolidays
-
- $countrepeatable = CheckRepeatableHoliday($itemnumber,$week_day,$branchcode);
-
-This function checks if the date due is a repeatable holiday
-
-C<$date_due> = returndate calculate with no day check
-C<$itemnumber> = itemnumber
-C<$branchcode> = localisation of issue
-
-=cut
-
-sub CheckRepeatableHolidays{
-my($itemnumber,$week_day,$branchcode)=@_;
-my $dbh = C4::Context->dbh;
-my $query = qq|SELECT count(*)
- FROM repeatable_holidays
- WHERE branchcode=?
- AND weekday=?|;
-my $sth = $dbh->prepare($query);
-$sth->execute($branchcode,$week_day);
-my $result=$sth->fetchrow;
-$sth->finish;
-return $result;
-}
-
-
-=head2 CheckSpecialHolidays
-
- $countspecial = CheckSpecialHolidays($years,$month,$day,$itemnumber,$branchcode);
-
-This function check if the date is a special holiday
-
-C<$years> = the years of datedue
-C<$month> = the month of datedue
-C<$day> = the day of datedue
-C<$itemnumber> = itemnumber
-C<$branchcode> = localisation of issue
-
-=cut
-
-sub CheckSpecialHolidays{
-my ($years,$month,$day,$itemnumber,$branchcode) = @_;
-my $dbh = C4::Context->dbh;
-my $query=qq|SELECT count(*)
- FROM `special_holidays`
- WHERE year=?
- AND month=?
- AND day=?
- AND branchcode=?
- |;
-my $sth = $dbh->prepare($query);
-$sth->execute($years,$month,$day,$branchcode);
-my $countspecial=$sth->fetchrow ;
-$sth->finish;
-return $countspecial;
-}
-
-=head2 CheckRepeatableSpecialHolidays
-
- $countspecial = CheckRepeatableSpecialHolidays($month,$day,$itemnumber,$branchcode);
-
-This function check if the date is a repeatble special holidays
-
-C<$month> = the month of datedue
-C<$day> = the day of datedue
-C<$itemnumber> = itemnumber
-C<$branchcode> = localisation of issue
-
-=cut
-
-sub CheckRepeatableSpecialHolidays{
-my ($month,$day,$itemnumber,$branchcode) = @_;
-my $dbh = C4::Context->dbh;
-my $query=qq|SELECT count(*)
- FROM `repeatable_holidays`
- WHERE month=?
- AND day=?
- AND branchcode=?
- |;
-my $sth = $dbh->prepare($query);
-$sth->execute($month,$day,$branchcode);
-my $countspecial=$sth->fetchrow ;
-$sth->finish;
-return $countspecial;
-}
-
-
sub CheckValidBarcode{
my ($barcode) = @_;
--- a/C4/Overdues.pm
+++ a/C4/Overdues.pm
@@ -306,130 +306,6 @@ sub _get_chargeable_units {
}
-=head2 GetSpecialHolidays
-
- &GetSpecialHolidays($date_dues,$itemnumber);
-
-return number of special days between date of the day and date due
-
-C<$date_dues> is the envisaged date of book return.
-
-C<$itemnumber> is the book's item number.
-
-=cut
-
-sub GetSpecialHolidays {
- my ( $date_dues, $itemnumber ) = @_;
-
- # calcul the today date
- my $today = join "-", &Today();
-
- # return the holdingbranch
- my $iteminfo = GetIssuesIteminfo($itemnumber);
-
- # use sql request to find all date between date_due and today
- my $dbh = C4::Context->dbh;
- my $query =
- qq|SELECT DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') as date
-FROM `special_holidays`
-WHERE DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') >= ?
-AND DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') <= ?
-AND branchcode=?
-|;
- my @result = GetWdayFromItemnumber($itemnumber);
- my @result_date;
- my $wday;
- my $dateinsec;
- my $sth = $dbh->prepare($query);
- $sth->execute( $date_dues, $today, $iteminfo->{'branchcode'} )
- ; # FIXME: just use NOW() in SQL instead of passing in $today
-
- while ( my $special_date = $sth->fetchrow_hashref ) {
- push( @result_date, $special_date );
- }
-
- my $specialdaycount = scalar(@result_date);
-
- for ( my $i = 0 ; $i < scalar(@result_date) ; $i++ ) {
- $dateinsec = UnixDate( $result_date[$i]->{'date'}, "%o" );
- ( undef, undef, undef, undef, undef, undef, $wday, undef, undef ) =
- localtime($dateinsec);
- for ( my $j = 0 ; $j < scalar(@result) ; $j++ ) {
- if ( $wday == ( $result[$j]->{'weekday'} ) ) {
- $specialdaycount--;
- }
- }
- }
-
- return $specialdaycount;
-}
-
-=head2 GetRepeatableHolidays
-
- &GetRepeatableHolidays($date_dues, $itemnumber, $difference,);
-
-return number of day closed between date of the day and date due
-
-C<$date_dues> is the envisaged date of book return.
-
-C<$itemnumber> is item number.
-
-C<$difference> numbers of between day date of the day and date due
-
-=cut
-
-sub GetRepeatableHolidays {
- my ( $date_dues, $itemnumber, $difference ) = @_;
- my $dateinsec = UnixDate( $date_dues, "%o" );
- my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
- localtime($dateinsec);
- my @result = GetWdayFromItemnumber($itemnumber);
- my @dayclosedcount;
- my $j;
-
- for ( my $i = 0 ; $i < scalar(@result) ; $i++ ) {
- my $k = $wday;
-
- for ( $j = 0 ; $j < $difference ; $j++ ) {
- if ( $result[$i]->{'weekday'} == $k ) {
- push( @dayclosedcount, $k );
- }
- $k++;
- ( $k = 0 ) if ( $k eq 7 );
- }
- }
- return scalar(@dayclosedcount);
-}
-
-
-=head2 GetWayFromItemnumber
-
- &Getwdayfromitemnumber($itemnumber);
-
-return the different week day from repeatable_holidays table
-
-C<$itemnumber> is item number.
-
-=cut
-
-sub GetWdayFromItemnumber {
- my ($itemnumber) = @_;
- my $iteminfo = GetIssuesIteminfo($itemnumber);
- my @result;
- my $query = qq|SELECT weekday
- FROM repeatable_holidays
- WHERE branchcode=?
-|;
- my $sth = C4::Context->dbh->prepare($query);
-
- $sth->execute( $iteminfo->{'branchcode'} );
- while ( my $weekday = $sth->fetchrow_hashref ) {
- push( @result, $weekday );
- }
- return @result;
-}
-
-
=head2 GetIssuesIteminfo
&GetIssuesIteminfo($itemnumber);
--- a/Koha/Calendar.pm
+++ a/Koha/Calendar.pm
@@ -18,10 +18,6 @@ sub new {
my $o = lc $o_name;
$self->{$o} = $options{$o_name};
}
- if ( exists $options{TEST_MODE} ) {
- $self->_mockinit();
- return $self;
- }
if ( !defined $self->{branchcode} ) {
croak 'No branchcode argument passed to Koha::Calendar->new';
}
@@ -33,57 +29,36 @@ sub _init {
my $self = shift;
my $branch = $self->{branchcode};
my $dbh = C4::Context->dbh();
- my $weekly_closed_days_sth = $dbh->prepare(
-'SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL'
- );
- $weekly_closed_days_sth->execute( $branch );
- $self->{weekly_closed_days} = [ 0, 0, 0, 0, 0, 0, 0 ];
- Readonly::Scalar my $sunday => 7;
- while ( my $tuple = $weekly_closed_days_sth->fetchrow_hashref ) {
- $self->{weekly_closed_days}->[ $tuple->{weekday} ] = 1;
- }
- my $day_month_closed_days_sth = $dbh->prepare(
-'SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL'
- );
- $day_month_closed_days_sth->execute( $branch );
- $self->{day_month_closed_days} = {};
- while ( my $tuple = $day_month_closed_days_sth->fetchrow_hashref ) {
- $self->{day_month_closed_days}->{ $tuple->{month} }->{ $tuple->{day} } =
- 1;
- }
- my $exception_holidays_sth = $dbh->prepare(
-'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1'
- );
- $exception_holidays_sth->execute( $branch );
- my $dates = [];
- while ( my ( $day, $month, $year ) = $exception_holidays_sth->fetchrow ) {
- push @{$dates},
- DateTime->new(
- day => $day,
- month => $month,
- year => $year,
- time_zone => C4::Context->tz()
- )->truncate( to => 'day' );
+ $self->{weekday_hours} = $dbh->selectall_hashref( q{
+ SELECT
+ weekday, open_hour, open_minute, close_hour, close_minute,
+ (open_hour = 0 AND open_minute = 0 AND close_hour = 0 AND close_minute = 0) AS closed
+ FROM calendar_repeats
+ WHERE branchcode = ? AND weekday IS NOT NULL
+ }, 'weekday', { Slice => {} }, $branch );
+
+ my $day_month_hours = $dbh->selectall_arrayref( q{
+ SELECT
+ month, day, open_hour, open_minute, close_hour, close_minute,
+ (open_hour = 0 AND open_minute = 0 AND close_hour = 0 AND close_minute = 0) AS closed
+ FROM calendar_repeats
+ WHERE branchcode = ? AND weekday IS NULL
+ }, { Slice => {} }, $branch );
+
+ # DBD::Mock doesn't support multi-key selectall_hashref, so we do it ourselves for now
+ foreach my $day_month ( @$day_month_hours ) {
+ $self->{day_month_hours}->{ $day_month->{month} }->{ $day_month->{day} } = $day_month;
}
- $self->{exception_holidays} =
- DateTime::Set->from_datetimes( dates => $dates );
-
- my $single_holidays_sth = $dbh->prepare(
-'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0'
- );
- $single_holidays_sth->execute( $branch );
- $dates = [];
- while ( my ( $day, $month, $year ) = $single_holidays_sth->fetchrow ) {
- push @{$dates},
- DateTime->new(
- day => $day,
- month => $month,
- year => $year,
- time_zone => C4::Context->tz()
- )->truncate( to => 'day' );
- }
- $self->{single_holidays} = DateTime::Set->from_datetimes( dates => $dates );
+
+ $self->{date_hours} = $dbh->selectall_hashref( q{
+ SELECT
+ event_date, open_hour, open_minute, close_hour, close_minute,
+ (open_hour = 0 AND open_minute = 0 AND close_hour = 0 AND close_minute = 0) AS closed
+ FROM calendar_events
+ WHERE branchcode = ?
+ }, 'event_date', { Slice => {} }, $branch );
+
$self->{days_mode} = C4::Context->preference('useDaysMode');
$self->{test} = 0;
return;
@@ -101,10 +76,7 @@ sub addDate {
my $dt;
if ( $unit eq 'hours' ) {
- # Fixed for legacy support. Should be set as a branch parameter
- Readonly::Scalar my $return_by_hour => 10;
-
- $dt = $self->addHours($startdate, $add_duration, $return_by_hour);
+ $dt = $self->addHours($startdate, $add_duration);
} else {
# days
$dt = $self->addDays($startdate, $add_duration);
@@ -114,25 +86,73 @@ sub addDate {
}
sub addHours {
- my ( $self, $startdate, $hours_duration, $return_by_hour ) = @_;
+ my ( $self, $startdate, $hours_duration ) = @_;
my $base_date = $startdate->clone();
- $base_date->add_duration($hours_duration);
+ if ( $self->{days_mode} eq 'Days' ) {
+ $base_date->add_duration( $hours_duration );
+ return $base_date;
+ }
+ my $hours = $self->get_hours_full( $base_date );
+
+ if ( $hours_duration->is_negative() ) {
+ if ( $base_date <= $hours->{open_time} ) {
+ # Library is already closed
+ $base_date = $self->prev_open_day( $base_date );
+ $hours = $self->get_hours_full( $base_date );
+ $base_date = $hours->{close_time}->clone;
+
+ if ( $self->{days_mode} eq 'Calendar' ) {
+ return $base_date;
+ }
+ }
- # If we are using the calendar behave for now as if Datedue
- # was the chosen option (current intended behaviour)
+ while ( $hours_duration->is_negative ) {
+ my $day_len = $hours->{open_time} - $base_date;
- if ( $self->{days_mode} ne 'Days' &&
- $self->is_holiday($base_date) ) {
+ if ( DateTime::Duration->compare( $day_len, $hours_duration, $base_date ) > 0 ) {
+ if ( $self->{days_mode} eq 'Calendar' ) {
+ return $hours->{open_time};
+ }
- if ( $hours_duration->is_negative() ) {
- $base_date = $self->prev_open_day($base_date);
- } else {
- $base_date = $self->next_open_day($base_date);
+ $hours_duration->subtract( $day_len );
+ $base_date = $self->prev_open_day( $base_date );
+ $hours = $self->get_hours_full( $base_date );
+ $base_date = $hours->{close_time}->clone;
+ } else {
+ $base_date->add_duration( $hours_duration );
+ return $base_date;
+ }
+ }
+ } else {
+ if ( $base_date >= $hours->{close_time} ) {
+ # Library is already closed
+ $base_date = $self->next_open_day( $base_date );
+ $hours = $self->get_hours_full( $base_date );
+ $base_date = $hours->{open_time}->clone;
+
+ if ( $self->{days_mode} eq 'Calendar' ) {
+ return $base_date;
+ }
}
- $base_date->set_hour($return_by_hour);
+ while ( $hours_duration->is_positive ) {
+ my $day_len = $hours->{close_time} - $base_date;
+
+ if ( DateTime::Duration->compare( $day_len, $hours_duration, $base_date ) < 0 ) {
+ if ( $self->{days_mode} eq 'Calendar' ) {
+ return $hours->{close_time};
+ }
+ $hours_duration->subtract( $day_len );
+ $base_date = $self->next_open_day( $base_date );
+ $hours = $self->get_hours_full( $base_date );
+ $base_date = $hours->{open_time}->clone;
+ } else {
+ $base_date->add_duration( $hours_duration );
+ return $base_date;
+ }
+ }
}
return $base_date;
@@ -182,33 +202,25 @@ sub addDays {
sub is_holiday {
my ( $self, $dt ) = @_;
- my $localdt = $dt->clone();
- my $day = $localdt->day;
- my $month = $localdt->month;
-
- $localdt->truncate( to => 'day' );
+ my $day = $dt->day;
+ my $month = $dt->month;
- if ( $self->{exception_holidays}->contains($localdt) ) {
- # exceptions are not holidays
+ if ( exists $self->{date_hours}->{ $dt->ymd } && !$self->{date_hours}->{ $dt->ymd }->{closed} ) {
return 0;
}
- my $dow = $localdt->day_of_week;
- # Representation fix
- # TODO: Shouldn't we shift the rest of the $dow also?
- if ( $dow == 7 ) {
- $dow = 0;
- }
-
- if ( $self->{weekly_closed_days}->[$dow] == 1 ) {
+ if ( ( $self->{day_month_hours}->{$month}->{$day} || {} )->{closed} ) {
return 1;
}
- if ( exists $self->{day_month_closed_days}->{$month}->{$day} ) {
+ # We use 0 for Sunday, not 7
+ my $dow = $dt->day_of_week % 7;
+
+ if ( ( $self->{weekday_hours}->{ $dow } || {} )->{closed} ) {
return 1;
}
- if ( $self->{single_holidays}->contains($localdt) ) {
+ if ( ( $self->{date_hours}->{ $dt->ymd } || {} )->{closed} ) {
return 1;
}
@@ -216,6 +228,60 @@ sub is_holiday {
return 0;
}
+sub get_hours {
+ my ( $self, $dt ) = @_;
+ my $day = $dt->day;
+ my $month = $dt->month;
+
+ if ( exists $self->{date_hours}->{ $dt->ymd } ) {
+ return $self->{date_hours}->{ $dt->ymd };
+ }
+
+ if ( exists $self->{day_month_hours}->{$month}->{$day} ) {
+ return $self->{day_month_hours}->{$month}->{$day};
+ }
+
+ # We use 0 for Sunday, not 7
+ my $dow = $dt->day_of_week % 7;
+
+ if ( exists $self->{weekday_hours}->{ $dow } ) {
+ return $self->{weekday_hours}->{ $dow };
+ }
+
+ # Assume open
+ return {
+ open_hour => 0,
+ open_minute => 0,
+ close_hour => 24,
+ close_minute => 0,
+ closed => 0
+ };
+}
+
+sub get_hours_full {
+ my ( $self, $dt ) = @_;
+
+ my $hours = { %{ $self->get_hours( $dt ) } };
+
+ $hours->{open_time} = $dt
+ ->clone->truncate( to => 'day' )
+ ->set_hour( $hours->{open_hour} )
+ ->set_minute( $hours->{open_minute} );
+
+ if ( $hours->{close_hour} == 24 ) {
+ $hours->{close_time} = $dt
+ ->clone->truncate( to => 'day' )
+ ->add( days => 1 );
+ } else {
+ $hours->{close_time} = $dt
+ ->clone->truncate( to => 'day' )
+ ->set_hour( $hours->{close_hour} )
+ ->set_minute( $hours->{close_minute} );
+ }
+
+ return $hours;
+}
+
sub next_open_day {
my ( $self, $dt ) = @_;
my $base_date = $dt->clone();
@@ -273,81 +339,39 @@ sub hours_between {
my ($self, $start_date, $end_date) = @_;
my $start_dt = $start_date->clone();
my $end_dt = $end_date->clone();
- my $duration = $end_dt->delta_ms($start_dt);
- $start_dt->truncate( to => 'day' );
- $end_dt->truncate( to => 'day' );
- # NB this is a kludge in that it assumes all days are 24 hours
- # However for hourly loans the logic should be expanded to
- # take into account open/close times then it would be a duration
- # of library open hours
- my $skipped_days = 0;
- for (my $dt = $start_dt->clone();
- $dt <= $end_dt;
- $dt->add(days => 1)
- ) {
- if ($self->is_holiday($dt)) {
- ++$skipped_days;
- }
- }
- if ($skipped_days) {
- $duration->subtract_duration(DateTime::Duration->new( hours => 24 * $skipped_days));
+
+ if ( $start_dt->compare($end_dt) > 0 ) {
+ # swap dates
+ my $int_dt = $end_dt;
+ $end_dt = $start_dt;
+ $start_dt = $int_dt;
}
- return $duration;
+ my $start_hours = $self->get_hours_full( $start_dt );
+ my $end_hours = $self->get_hours_full( $end_dt );
-}
+ $start_dt = $start_hours->{open_time} if ( $start_dt < $start_hours->{open_time} );
+ $end_dt = $end_hours->{close_time} if ( $end_dt > $end_hours->{close_time} );
-sub _mockinit {
- my $self = shift;
- $self->{weekly_closed_days} = [ 1, 0, 0, 0, 0, 0, 0 ]; # Sunday only
- $self->{day_month_closed_days} = { 6 => { 16 => 1, } };
- my $dates = [];
- $self->{exception_holidays} =
- DateTime::Set->from_datetimes( dates => $dates );
- my $special = DateTime->new(
- year => 2011,
- month => 6,
- day => 1,
- time_zone => 'Europe/London',
- );
- push @{$dates}, $special;
- $self->{single_holidays} = DateTime::Set->from_datetimes( dates => $dates );
-
- # if not defined, days_mode defaults to 'Calendar'
- if ( !defined($self->{days_mode}) ) {
- $self->{days_mode} = 'Calendar';
- }
+ return $end_dt - $start_dt if ( $start_dt->ymd eq $end_dt->ymd );
- $self->{test} = 1;
- return;
-}
+ my $duration = DateTime::Duration->new;
+
+ $duration->add_duration( $start_hours->{close_time} - $start_dt ) if ( $start_dt < $start_hours->{close_time} );
-sub set_daysmode {
- my ( $self, $mode ) = @_;
+ for (my $date = $start_dt->clone->truncate( to => 'day' )->add( days => 1 );
+ $date->ymd lt $end_dt->ymd;
+ $date->add(days => 1)
+ ) {
+ my $hours = $self->get_hours_full( $date );
- # if not testing this is a no op
- if ( $self->{test} ) {
- $self->{days_mode} = $mode;
+ $duration->add_duration( $hours->{close_time}->delta_ms( $hours->{open_time} ) );
}
- return;
-}
-
-sub clear_weekly_closed_days {
- my $self = shift;
- $self->{weekly_closed_days} = [ 0, 0, 0, 0, 0, 0, 0 ]; # Sunday only
- return;
-}
+ $duration->add_duration( $end_dt - $end_hours->{open_time} ) if ( $end_dt > $start_hours->{open_time} );
-sub add_holiday {
- my $self = shift;
- my $new_dt = shift;
- my @dt = $self->{single_holidays}->as_list;
- push @dt, $new_dt;
- $self->{single_holidays} =
- DateTime::Set->from_datetimes( dates => \@dt );
+ return $duration;
- return;
}
1;
@@ -403,14 +427,12 @@ parameter will be removed when issuingrules properly cope with that
=head2 addHours
- my $dt = $calendar->addHours($date, $dur, $return_by_hour )
+ my $dt = $calendar->addHours($date, $dur )
C<$date> is a DateTime object representing the starting date of the interval.
C<$offset> is a DateTime::Duration to add to it
-C<$return_by_hour> is an integer value representing the opening hour for the branch
-
=head2 addDays
@@ -457,22 +479,6 @@ Passed a Datetime returns another Datetime representing the previous open day. I
intended for use to calculate the due date when useDaysMode syspref is set to either
'Datedue' or 'Calendar'.
-=head2 set_daysmode
-
-For testing only allows the calling script to change days mode
-
-=head2 clear_weekly_closed_days
-
-In test mode changes the testing set of closed days to a new set with
-no closed days. TODO passing an array of closed days to this would
-allow testing of more configurations
-
-=head2 add_holiday
-
-Passed a datetime object this will add it to the calendar's list of
-closed days. This is for testing so that we can alter the Calenfar object's
-list of specified dates
-
=head1 DIAGNOSTICS
Will croak if not passed a branchcode in new
--- a/installer/data/mysql/de-DE/optional/sample_holidays.sql
+++ a/installer/data/mysql/de-DE/optional/sample_holidays.sql
@@ -1,5 +1,5 @@
-INSERT INTO `repeatable_holidays` VALUES
-(2,'MPL',0,NULL,NULL,'','Sonntag'),
-(3,'MPL',NULL,1,1,'','Neujahr'),
-(4,'MPL',NULL,25,12,'','1. Weihnachtsfeiertag'),
-(5,'MPL',NULL,25,12,'','2. Weihnachtsfeiertag');
+INSERT INTO `calendar_repeats` VALUES
+(2,'MPL',0,NULL,NULL,'','Sonntag',0,0,0,0),
+(3,'MPL',NULL,1,1,'','Neujahr',0,0,0,0),
+(4,'MPL',NULL,12,25,'','1. Weihnachtsfeiertag',0,0,0,0),
+(5,'MPL',NULL,12,25,'','2. Weihnachtsfeiertag',0,0,0,0);
--- a/installer/data/mysql/en/optional/sample_holidays.sql
+++ a/installer/data/mysql/en/optional/sample_holidays.sql
@@ -1,4 +1,4 @@
-INSERT INTO `repeatable_holidays` VALUES
-(2,'MPL',0,NULL,NULL,'','Sundays'),
-(3,'MPL',NULL,1,1,'','New Year\'s Day'),
-(4,'MPL',NULL,25,12,'','Christmas');
+INSERT INTO `calendar_repeats` VALUES
+(2,'MPL',0,NULL,NULL,'','Sundays',0,0,0,0),
+(3,'MPL',NULL,1,1,'','New Year\'s Day',0,0,0,0),
+(4,'MPL',NULL,12,25,'','Christmas',0,0,0,0);
--- a/installer/data/mysql/es-ES/optional/sample_holidays.sql
+++ a/installer/data/mysql/es-ES/optional/sample_holidays.sql
@@ -1,4 +1,4 @@
-INSERT INTO `repeatable_holidays` VALUES
-(2,'',0,NULL,NULL,'','Sundays'),
-(3,'',NULL,1,1,'','New Year\'s Day'),
-(4,'',NULL,25,12,'','Christmas');
+INSERT INTO `calendar_repeats` VALUES
+(2,'',0,NULL,NULL,'','Sundays',0,0,0,0),
+(3,'',NULL,1,1,'','New Year\'s Day',0,0,0,0),
+(4,'',NULL,12,25,'','Christmas',0,0,0,0);
--- a/installer/data/mysql/it-IT/necessari/sample_holidays.sql
+++ a/installer/data/mysql/it-IT/necessari/sample_holidays.sql
@@ -1,8 +1,8 @@
SET FOREIGN_KEY_CHECKS=0;
-INSERT INTO `repeatable_holidays` VALUES
-(2,'',0,NULL,NULL,'','Domenica'),
-(3,'',NULL,1,1,'','Nuovo anno'),
-(4,'',NULL,25,12,'','Natale');
+INSERT INTO `calendar_repeats` VALUES
+(2,'',0,NULL,NULL,'','Domenica',0,0,0,0),
+(3,'',NULL,1,1,'','Nuovo anno',0,0,0,0),
+(4,'',NULL,12,25,'','Natale',0,0,0,0);
-SET FOREIGN_KEY_CHECKS=1;
+SET FOREIGN_KEY_CHECKS=1;
--- a/installer/data/mysql/kohastructure.sql
+++ a/installer/data/mysql/kohastructure.sql
@@ -640,6 +640,43 @@ CREATE TABLE `default_circ_rules` (
PRIMARY KEY (`singleton`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `calendar_events`
+--
+DROP TABLE IF EXISTS `calendar_events`;
+CREATE TABLE `calendar_events` (
+ `branchcode` varchar(10) NOT NULL DEFAULT '',
+ `event_date` date NOT NULL,
+ `title` varchar(50) NOT NULL DEFAULT '',
+ `description` text NOT NULL,
+ `open_hour` smallint(6) NOT NULL,
+ `open_minute` smallint(6) NOT NULL,
+ `close_hour` smallint(6) NOT NULL,
+ `close_minute` smallint(6) NOT NULL,
+ PRIMARY KEY (`branchcode`,`event_date`),
+ CONSTRAINT `calendar_events_ibfk_1` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `calendar_repeats`
+--
+DROP TABLE IF EXISTS `calendar_repeats`;
+CREATE TABLE `calendar_repeats` (
+ `branchcode` varchar(10) NOT NULL DEFAULT '',
+ `weekday` smallint(6) DEFAULT NULL,
+ `month` smallint(6) DEFAULT NULL,
+ `day` smallint(6) DEFAULT NULL,
+ `title` varchar(50) NOT NULL DEFAULT '',
+ `description` text NOT NULL,
+ `open_hour` smallint(6) NOT NULL,
+ `open_minute` smallint(6) NOT NULL,
+ `close_hour` smallint(6) NOT NULL,
+ `close_minute` smallint(6) NOT NULL,
+ UNIQUE KEY `branchcode` (`branchcode`,`weekday`),
+ UNIQUE KEY `branchcode_2` (`branchcode`,`month`,`day`),
+ CONSTRAINT `calendar_repeats_ibfk_1` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `cities`
--
@@ -1719,22 +1756,6 @@ CREATE TABLE `printers_profile` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
--- 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` text NOT NULL, -- description for this closing
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
-- Table structure for table `reports_dictionary`
--
@@ -1917,23 +1938,6 @@ CREATE TABLE sessions (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
--- 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` text NOT NULL, -- description of this closing
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
-- Table structure for table `statistics`
--
--- a/installer/data/mysql/nb-NO/2-Valgfritt/sample_holidays.sql
+++ a/installer/data/mysql/nb-NO/2-Valgfritt/sample_holidays.sql
@@ -19,10 +19,10 @@
-- with Koha; if not, write to the Free Software Foundation, Inc.,
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-INSERT INTO `repeatable_holidays` VALUES
-(2,'',0,NULL,NULL,'','Søndager'),
-(3,'',NULL,1,1,'','1. nyttårsdag'),
-(4,'',NULL,1,5,'','1. mai'),
-(5,'',NULL,17,5,'','17. mai'),
-(6,'',NULL,25,12,'','1. juledag'),
-(7,'',NULL,26,12,'','2. juledag');
+INSERT INTO `calendar_repeats` VALUES
+(2,'',0,NULL,NULL,'','Søndager',0,0,0,0),
+(3,'',NULL,1,1,'','1. nyttårsdag',0,0,0,0),
+(4,'',NULL,5,1,'','1. mai',0,0,0,0),
+(5,'',NULL,5,17,'','17. mai',0,0,0,0),
+(6,'',NULL,12,25,'','1. juledag',0,0,0,0),
+(7,'',NULL,12,26,'','2. juledag',0,0,0,0);
--- a/installer/data/mysql/pl-PL/optional/sample_holidays.sql
+++ a/installer/data/mysql/pl-PL/optional/sample_holidays.sql
@@ -1,4 +1,4 @@
-INSERT INTO `repeatable_holidays` VALUES
-(2,'',0,NULL,NULL,'','Niedziele'),
-(3,'',NULL,1,1,'','Nowy Rok'),
-(4,'',NULL,25,12,'','Boże Narodzenie');
+INSERT INTO `calendar_repeats` VALUES
+(2,'',0,NULL,NULL,'','Niedziele',0,0,0,0),
+(3,'',NULL,1,1,'','Nowy Rok',0,0,0,0),
+(4,'',NULL,12,25,'','Boże Narodzenie',0,0,0,0);
--- a/installer/data/mysql/ru-RU/optional/holidays.sql
+++ a/installer/data/mysql/ru-RU/optional/holidays.sql
@@ -1,23 +1,23 @@
-TRUNCATE repeatable_holidays;
+TRUNCATE calendar_repeats;
-INSERT INTO `repeatable_holidays` (`id`, `branchcode`, `weekday`, `day`, `month`, `title`, `description`)
-VALUES (2, '',0,NULL,NULL,'','Воскресенья');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute)
+VALUES ('',0,NULL,NULL,'','Воскресенья', 0, 0, 0, 0);
-INSERT INTO `repeatable_holidays` (`id`, `branchcode`, `weekday`, `day`, `month`, `title`, `description`)
-VALUES (3, '',NULL,1,1,'','Новый год');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute)
+VALUES ('',NULL,1,1,'','Новый год', 0, 0, 0, 0);
-INSERT INTO `repeatable_holidays` (`id`, `branchcode`, `weekday`, `day`, `month`, `title`, `description`)
-VALUES (4, '',NULL,7,1,'','Рождество');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute)
+VALUES ('',NULL,7,1,'','Рождество', 0, 0, 0, 0);
-INSERT INTO `repeatable_holidays` (`id`, `branchcode`, `weekday`, `day`, `month`, `title`, `description`)
-VALUES (5, '',NULL,8,3,'','Международный женский день');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute)
+VALUES ('',NULL,8,3,'','Международный женский день', 0, 0, 0, 0);
-INSERT INTO `repeatable_holidays` (`id`, `branchcode`, `weekday`, `day`, `month`, `title`, `description`)
-VALUES (6, '',NULL,1,5,'','День Труда');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute)
+VALUES ('',NULL,1,5,'','День Труда', 0, 0, 0, 0);
-INSERT INTO `repeatable_holidays` (`id`, `branchcode`, `weekday`, `day`, `month`, `title`, `description`)
-VALUES (7, '',NULL,2,5,'','День Труда');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute)
+VALUES ('',NULL,2,5,'','День Труда', 0, 0, 0, 0);
-INSERT INTO `repeatable_holidays` (`id`, `branchcode`, `weekday`, `day`, `month`, `title`, `description`)
-VALUES (8, '',NULL,9,5,'','День Победы');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute)
+VALUES ('',NULL,9,5,'','День Победы', 0, 0, 0, 0);
--- a/installer/data/mysql/uk-UA/optional/holidays.sql
+++ a/installer/data/mysql/uk-UA/optional/holidays.sql
@@ -1,24 +1,24 @@
-TRUNCATE repeatable_holidays;
+TRUNCATE calendar_repeats;
-INSERT INTO `repeatable_holidays` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`) VALUES
-('STL', 0, NULL, NULL,'', 'Неділі'),
-('STL', NULL, 1, 1, '', 'Новий рік'),
-('STL', NULL, 7, 1, '', 'Різдво'),
-('STL', NULL, 8, 3, '', 'Міжнародний жіночий день'),
-('STL', NULL, 1, 5, '', 'День Праці'),
-('STL', NULL, 2, 5, '', 'День Праці'),
-('STL', NULL, 9, 5, '', 'День Перемоги'),
-('STL', NULL, 28, 6, '', 'День Конституції'),
-('STL', NULL, 24, 8, '', 'День Незалежності');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute) VALUES
+('STL', 0, NULL, NULL,'', 'Неділі', 0, 0, 0, 0),
+('STL', NULL, 1, 1, '', 'Новий рік', 0, 0, 0, 0),
+('STL', NULL, 7, 1, '', 'Різдво', 0, 0, 0, 0),
+('STL', NULL, 8, 3, '', 'Міжнародний жіночий день', 0, 0, 0, 0),
+('STL', NULL, 1, 5, '', 'День Праці', 0, 0, 0, 0),
+('STL', NULL, 2, 5, '', 'День Праці', 0, 0, 0, 0),
+('STL', NULL, 9, 5, '', 'День Перемоги', 0, 0, 0, 0),
+('STL', NULL, 28, 6, '', 'День Конституції', 0, 0, 0, 0),
+('STL', NULL, 24, 8, '', 'День Незалежності', 0, 0, 0, 0);
-INSERT INTO `repeatable_holidays` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`) VALUES
-('LNSL', 0, NULL, NULL,'', 'Неділі'),
-('LNSL', NULL, 1, 1, '', 'Новий рік'),
-('LNSL', NULL, 7, 1, '', 'Різдво'),
-('LNSL', NULL, 8, 3, '', 'Міжнародний жіночий день'),
-('LNSL', NULL, 1, 5, '', 'День Праці'),
-('LNSL', NULL, 2, 5, '', 'День Праці'),
-('LNSL', NULL, 9, 5, '', 'День Перемоги'),
-('LNSL', NULL, 28, 6, '', 'День Конституції'),
-('LNSL', NULL, 24, 8, '', 'День Незалежності');
+INSERT INTO `calendar_repeats` (`branchcode`, `weekday`, `day`, `month`, `title`, `description`, open_hour, open_minute, close_hour, close_minute) VALUES
+('LNSL', 0, NULL, NULL,'', 'Неділі', 0, 0, 0, 0),
+('LNSL', NULL, 1, 1, '', 'Новий рік', 0, 0, 0, 0),
+('LNSL', NULL, 7, 1, '', 'Різдво', 0, 0, 0, 0),
+('LNSL', NULL, 8, 3, '', 'Міжнародний жіночий день', 0, 0, 0, 0),
+('LNSL', NULL, 1, 5, '', 'День Праці', 0, 0, 0, 0),
+('LNSL', NULL, 2, 5, '', 'День Праці', 0, 0, 0, 0),
+('LNSL', NULL, 9, 5, '', 'День Перемоги', 0, 0, 0, 0),
+('LNSL', NULL, 28, 6, '', 'День Конституції', 0, 0, 0, 0),
+('LNSL', NULL, 24, 8, '', 'День Незалежності', 0, 0, 0, 0);
--- a/installer/data/mysql/updatedatabase.pl
+++ a/installer/data/mysql/updatedatabase.pl
@@ -7010,6 +7010,81 @@ CREATE TABLE IF NOT EXISTS borrower_files (
SetVersion($DBversion);
}
+$DBversion = "3.13.00.XXX";
+if ( CheckVersion($DBversion) ) {
+ print "Upgrade to $DBversion done (Bug 8133: create tables, migrate data to calendar_*)\n";
+
+ $dbh->do( q{
+ CREATE TABLE `calendar_events` (
+ `branchcode` varchar(10) NOT NULL DEFAULT '',
+ `event_date` date NOT NULL,
+ `title` varchar(50) NOT NULL DEFAULT '',
+ `description` text NOT NULL,
+ `open_hour` smallint(6) NOT NULL,
+ `open_minute` smallint(6) NOT NULL,
+ `close_hour` smallint(6) NOT NULL,
+ `close_minute` smallint(6) NOT NULL,
+ PRIMARY KEY (`branchcode`,`event_date`),
+ CONSTRAINT `calendar_events_ibfk_1` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ } );
+
+ $dbh->do( q{
+ CREATE TABLE `calendar_repeats` (
+ `branchcode` varchar(10) NOT NULL DEFAULT '',
+ `weekday` smallint(6) DEFAULT NULL,
+ `month` smallint(6) DEFAULT NULL,
+ `day` smallint(6) DEFAULT NULL,
+ `title` varchar(50) NOT NULL DEFAULT '',
+ `description` text NOT NULL,
+ `open_hour` smallint(6) NOT NULL,
+ `open_minute` smallint(6) NOT NULL,
+ `close_hour` smallint(6) NOT NULL,
+ `close_minute` smallint(6) NOT NULL,
+ UNIQUE KEY `branchcode` (`branchcode`,`weekday`),
+ UNIQUE KEY `branchcode_2` (`branchcode`,`month`,`day`),
+ CONSTRAINT `calendar_repeats_ibfk_1` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ } );
+
+ $dbh->do( q{
+ INSERT INTO
+ calendar_events(branchcode, event_date, title, description, open_hour, open_minute, close_hour, close_minute)
+ SELECT
+ branchcode, CONCAT_WS('-', year, month, day), title, description, 0, 0, 0, 0
+ FROM special_holidays
+ WHERE isexception = 0
+ } );
+
+ $dbh->do( q{
+ INSERT INTO
+ calendar_events(branchcode, event_date, title, description, open_hour, open_minute, close_hour, close_minute)
+ SELECT
+ branchcode, CONCAT_WS('-', year, month, day), title, description, 0, 0, 24, 0
+ FROM special_holidays
+ WHERE isexception = 1
+ } );
+
+ $dbh->do( q{
+ INSERT INTO
+ calendar_repeats(branchcode, weekday, month, day, title, description, open_hour, open_minute, close_hour, close_minute)
+ SELECT
+ branchcode, weekday, month, day, title, description, 0, 0, 0, 0
+ FROM repeatable_holidays
+ WHERE weekday IS NULL
+ } );
+
+ $dbh->do( q{
+ DROP TABLE repeatable_holidays;
+ } );
+
+ $dbh->do( q{
+ DROP TABLE special_holidays;
+ } );
+
+ SetVersion($DBversion);
+}
+
=head1 FUNCTIONS
=head2 TableExists($table)
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc
+++ a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc
@@ -81,7 +81,7 @@
Additional tools