Bugzilla – Attachment 32985 Details for
Bug 8133
hourly loans doesn't know when library closed
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 8133 - hourly loans doesn't know when library closed
Bug-8133---hourly-loans-doesnt-know-when-library-c.patch (text/plain), 75.35 KB, created by
Kyle M Hall (khall)
on 2014-10-30 16:30:25 UTC
(
hide
)
Description:
Bug 8133 - hourly loans doesn't know when library closed
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2014-10-30 16:30:25 UTC
Size:
75.35 KB
patch
obsolete
>From 05fd8526f0ebb8acc378ecc9c955d4411502ebab Mon Sep 17 00:00:00 2001 >From: Jesse Weaver <pianohacker@gmail.com> >Date: Thu, 20 Jun 2013 16:54:32 -0600 >Subject: [PATCH] Bug 8133 - hourly loans doesn't know when library closed > >This adds support for storing library hours in the calendar, and using >those hours to compute hourly loan duetimes. > >A large amount of cleanup was also performed to expunge duplication of >code between C4::Calendar and Koha::Calendar. > >Test plan: >1) Apply patch. >2) Update database. >3) Verify that the calendar administration interface still exists and > works as expected. >4) Run t/Calendar.t and t/db_dependent/Calendar.t. > >Signed-off-by: Chris Cormack <chris@bigballofwax.co.nz> >--- > C4/Calendar.pm | 153 ++++------- > C4/Circulation.pm | 2 + > Koha/Calendar.pm | 271 +++++++++++++------- > .../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 | 56 +++-- > misc/cronjobs/staticfines.pl | 2 +- > t/Calendar.t | 139 +++++++++-- > t/db_dependent/Calendar.t | 88 +++---- > tools/calendar.pl | 105 ++++----- > 19 files changed, 648 insertions(+), 445 deletions(-) > >diff --git a/C4/Calendar.pm b/C4/Calendar.pm >index dee183d..7131b56 100644 >--- a/C4/Calendar.pm >+++ b/C4/Calendar.pm >@@ -20,7 +20,7 @@ use vars qw($VERSION @EXPORT); > > use Carp; > >-use Koha::Database; >+use C4::Context; > > our ( @ISA, @EXPORT ); > >@@ -66,10 +66,9 @@ sub GetSingleEvents { > > return C4::Context->dbh->selectall_arrayref( q{ > SELECT >- CONCAT(LPAD(year, 4, '0'), '-', LPAD(month, 2, '0'), '-', LPAD(day, 2, '0')) as event_date, >- 0 as open_hour, 0 as open_minute, IF(isexception, 24, 0) as close_hour, >- 0 as close_minute, title, description, IF(isexception, 0, 1) as closed >- FROM special_holidays >+ 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 ); > } >@@ -87,11 +86,11 @@ sub GetWeeklyEvents { > > return C4::Context->dbh->selectall_arrayref( q{ > SELECT >- weekday, 0 as open_hour, 0 as open_minute, 0 as close_hour, >- 0 as close_minute, title, description, 1 as closed >- FROM repeatable_holidays >+ 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 ); >+ }, { Slice => {} }, $branchcode ); > } > > =head2 GetYearlyEvents >@@ -107,130 +106,91 @@ sub GetYearlyEvents { > > return C4::Context->dbh->selectall_arrayref( q{ > SELECT >- month, day, 0 as open_hour, 0 as open_minute, 0 as close_hour, >- 0 as close_minute, title, description, 1 as closed >- FROM repeatable_holidays >+ 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 ModSingleEvent > >- ModSingleEvent( $branchcode, \%info ) >+ ModSingleEvent( $branchcode, $date, \%info ) > >-Creates or updates an event for a single date. $info->{date} should be an >-ISO-formatted date string, and \%info should also contain the following keys: >-open_hour, open_minute, close_hour, close_minute, title and description. >+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 ModSingleEvent { >- my ( $branchcode, $info ) = @_; >- >- my ( $year, $month, $day ) = ( $info->{date} =~ /(\d+)-(\d+)-(\d+)/ ); >- return unless ( $year && $month && $day ); >- >- my $dbh = C4::Context->dbh; >- my @args = ( ( map { $info->{$_} } qw(title description) ), $info->{close_hour} != 0, $branchcode, $year, $month, $day ); >- >- # The code below relies on $dbh->do returning 0 when the update affects no rows >- my $affected = $dbh->do( q{ >- UPDATE special_holidays >- SET >- title = ?, description = ?, isexception = ? >- WHERE branchcode = ? AND year = ? AND month = ? AND day = ? >- }, {}, @args ); >- >- $dbh->do( q{ >- INSERT >- INTO special_holidays(title, description, isexception, branchcode, year, month, day) >- VALUES (?, ?, ?, ?, ?, ?, ?) >- }, {}, @args ) unless ( $affected > 0 ); >+ my ( $branchcode, $date, $info ) = @_; >+ >+ 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 ModRepeatingEvent > >- ModRepeatingEvent( $branchcode, \%info ) >+ ModRepeatingEvent( $branchcode, $weekday, $month, $day, \%info ) > >-Creates or updates a weekly- or yearly-repeating event. Either $info->{weekday}, >-or $info->{month} and $info->{day} should be set, for a weekly or yearly event, >-respectively. >+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 _get_compare { >- my ( $colname, $value ) = @_; >- >- return ' AND ' . $colname . ' ' . ( defined( $value ) ? '=' : 'IS' ) . ' ?'; >-} >- > sub ModRepeatingEvent { >- my ( $branchcode, $info ) = @_; >- >- my $dbh = C4::Context->dbh; >- my $open = ( $info->{close_hour} != 0 ); >- >- if ($open) { >- $dbh->do( q{ >- DELETE FROM repeatable_holidays >- WHERE branchcode = ? >- } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, $branchcode, $info->{weekday}, $info->{month}, $info->{day} ); >- } else { >- my @args = ( ( map { $info->{$_} } qw(title description) ), $branchcode, $info->{weekday}, $info->{month}, $info->{day} ); >- >- # The code below relies on $dbh->do returning 0 when the update affects no rows >- my $affected = $dbh->do( q{ >- UPDATE repeatable_holidays >- SET >- title = ?, description = ? >- WHERE branchcode = ? >- } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, @args ); >- >- $dbh->do( q{ >- INSERT >- INTO repeatable_holidays(title, description, branchcode, weekday, month, day) >- VALUES (?, ?, ?, ?, ?, ?) >- }, {}, @args ) unless ( $affected > 0 ); >- } >+ my ( $branchcode, $weekday, $month, $day, $info ) = @_; >+ >+ 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 DelSingleEvent > >- DelSingleEvent( $branchcode, \%info ) >+ DelSingleEvent( $branchcode, $date, \%info ) > >-Deletes an event for a single date. $info->{date} should be an ISO-formatted date string. >+Deletes an event for a single date. $date should be an ISO-formatted date string. > > =cut > > sub DelSingleEvent { >- my ( $branchcode, $info ) = @_; >- >- my ( $year, $month, $day ) = ( $info->{date} =~ /(\d+)-(\d+)-(\d+)/ ); >- return unless ( $year && $month && $day ); >+ my ( $branchcode, $date ) = @_; > > C4::Context->dbh->do( q{ >- DELETE FROM special_holidays >- WHERE branchcode = ? AND year = ? AND month = ? AND day = ? >- }, {}, $branchcode, $year, $month, $day ); >+ DELETE FROM calendar_events >+ WHERE branchcode = ? AND event_date = ? >+ }, {}, $branchcode, $date ); >+} >+ >+sub _get_compare { >+ my ( $colname, $value ) = @_; >+ >+ return ' AND ' . $colname . ' ' . ( defined( $value ) ? '=' : 'IS' ) . ' ?'; > } > > =head2 DelRepeatingEvent > >- DelRepeatingEvent( $branchcode, \%info ) >+ DelRepeatingEvent( $branchcode, $weekday, $month, $day ) > >-Deletes a weekly- or yearly-repeating event. Either $info->{weekday}, or >-$info->{month} and $info->{day} should be set, for a weekly or yearly event, >-respectively. >+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 DelRepeatingEvent { >- my ( $branchcode, $info ) = @_; >+ my ( $branchcode, $weekday, $month, $day ) = @_; > > C4::Context->dbh->do( q{ >- DELETE FROM repeatable_holidays >+ DELETE FROM calendar_repeats > WHERE branchcode = ? >- } . _get_compare( 'weekday', $info->{weekday} ) . _get_compare( 'month', $info->{month} ) . _get_compare( 'day', $info->{day} ), {}, $branchcode, $info->{weekday}, $info->{month}, $info->{day} ); >+ } . _get_compare( 'weekday', $weekday ) . _get_compare( 'month', $month ) . _get_compare( 'day', $day ), {}, $branchcode, $weekday, $month, $day ); > } > > =head2 CopyAllEvents >@@ -245,16 +205,16 @@ sub CopyAllEvents { > my ( $from_branchcode, $to_branchcode ) = @_; > > C4::Context->dbh->do( q{ >- INSERT IGNORE INTO special_holidays(branchcode, year, month, day, isexception, title, description) >- SELECT ?, year, month, day, isexception, title, description >- FROM special_holidays >+ 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 ); > > C4::Context->dbh->do( q{ >- INSERT IGNORE INTO repeatable_holidays(branchcode, weekday, month, day, title, description) >- SELECT ?, weekday, month, day, title, description >- FROM repeatable_holidays >+ 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 ); > } >@@ -267,6 +227,5 @@ __END__ > =head1 AUTHOR > > Koha Physics Library UNLP <matias_veleda@hotmail.com> >-Jesse Weaver <jweaver@bywatersolutions.com> > > =cut >diff --git a/C4/Circulation.pm b/C4/Circulation.pm >index 54f39ed..8b4f4de 100644 >--- a/C4/Circulation.pm >+++ b/C4/Circulation.pm >@@ -3342,6 +3342,8 @@ sub CalcDateDue { > return $datedue; > } > >+ >+ > sub CheckValidBarcode{ > my ($barcode) = @_; > my $dbh = C4::Context->dbh; >diff --git a/Koha/Calendar.pm b/Koha/Calendar.pm >index 8ba4453..2aba139 100644 >--- a/Koha/Calendar.pm >+++ b/Koha/Calendar.pm >@@ -29,25 +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; >+ >+ $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->{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; >@@ -114,6 +125,7 @@ sub _single_holidays { > $single_holidays->{$branchcode} = $self->{single_holidays}{$branchcode}; > return $single_holidays->{$branchcode}; > } >+ > sub addDate { > my ( $self, $startdate, $add_duration, $unit ) = @_; > >@@ -126,10 +138,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); >@@ -139,25 +148,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 we are using the calendar behave for now as if Datedue >- # was the chosen option (current intended behaviour) >+ 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} ne 'Days' && >- $self->is_holiday($base_date) ) { >+ if ( $self->{days_mode} eq 'Calendar' ) { >+ return $base_date; >+ } >+ } > >- if ( $hours_duration->is_negative() ) { >- $base_date = $self->prev_open_day($base_date); >- } else { >- $base_date = $self->next_open_day($base_date); >+ while ( $hours_duration->is_negative ) { >+ my $day_len = $hours->{open_time} - $base_date; >+ >+ if ( DateTime::Duration->compare( $day_len, $hours_duration, $base_date ) > 0 ) { >+ if ( $self->{days_mode} eq 'Calendar' ) { >+ return $hours->{open_time}; >+ } >+ >+ $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; >@@ -207,33 +264,25 @@ sub addDays { > > sub is_holiday { > my ( $self, $dt ) = @_; >- my $localdt = $dt->clone(); >- my $day = $localdt->day; >- my $month = $localdt->month; >+ my $day = $dt->day; >+ my $month = $dt->month; > >- $localdt->truncate( to => 'day' ); >- >- 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; > } > >@@ -241,6 +290,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(); >@@ -298,45 +401,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 set_daysmode { >- my ( $self, $mode ) = @_; >+ return $end_dt - $start_dt if ( $start_dt->ymd eq $end_dt->ymd ); > >- # if not testing this is a no op >- if ( $self->{test} ) { >- $self->{days_mode} = $mode; >+ my $duration = DateTime::Duration->new; >+ >+ $duration->add_duration( $start_hours->{close_time} - $start_dt ) if ( $start_dt < $start_hours->{close_time} ); >+ >+ 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 ); >+ >+ $duration->add_duration( $hours->{close_time}->delta_ms( $hours->{open_time} ) ); > } > >- return; >-} >+ $duration->add_duration( $end_dt - $end_hours->{open_time} ) if ( $end_dt > $start_hours->{open_time} ); >+ >+ return $duration; > >-sub clear_weekly_closed_days { >- my $self = shift; >- $self->{weekly_closed_days} = [ 0, 0, 0, 0, 0, 0, 0 ]; # Sunday only >- return; > } > > 1; >@@ -392,14 +489,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 > >@@ -446,16 +541,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 >- > =head1 DIAGNOSTICS > > Will croak if not passed a branchcode in new >diff --git a/installer/data/mysql/de-DE/optional/sample_holidays.sql b/installer/data/mysql/de-DE/optional/sample_holidays.sql >index 124fcad..7f18bf2 100644 >--- a/installer/data/mysql/de-DE/optional/sample_holidays.sql >+++ b/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); >diff --git a/installer/data/mysql/en/optional/sample_holidays.sql b/installer/data/mysql/en/optional/sample_holidays.sql >index 33b6ff6..866c14f 100644 >--- a/installer/data/mysql/en/optional/sample_holidays.sql >+++ b/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); >diff --git a/installer/data/mysql/es-ES/optional/sample_holidays.sql b/installer/data/mysql/es-ES/optional/sample_holidays.sql >index e323317..1cf78ec 100644 >--- a/installer/data/mysql/es-ES/optional/sample_holidays.sql >+++ b/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); >diff --git a/installer/data/mysql/it-IT/necessari/sample_holidays.sql b/installer/data/mysql/it-IT/necessari/sample_holidays.sql >index 67640a9..f1478de 100644 >--- a/installer/data/mysql/it-IT/necessari/sample_holidays.sql >+++ b/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; >\ No newline at end of file >+SET FOREIGN_KEY_CHECKS=1; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index b135e21..0b67085 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -669,6 +669,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` > -- >@@ -1768,22 +1805,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` > -- > >@@ -1957,23 +1978,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` > -- > >diff --git a/installer/data/mysql/nb-NO/2-Valgfritt/sample_holidays.sql b/installer/data/mysql/nb-NO/2-Valgfritt/sample_holidays.sql >index 7df9e67..d2b5ab7 100644 >--- a/installer/data/mysql/nb-NO/2-Valgfritt/sample_holidays.sql >+++ b/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); >diff --git a/installer/data/mysql/pl-PL/optional/sample_holidays.sql b/installer/data/mysql/pl-PL/optional/sample_holidays.sql >index bee37b5..6dfd59d 100644 >--- a/installer/data/mysql/pl-PL/optional/sample_holidays.sql >+++ b/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); >diff --git a/installer/data/mysql/ru-RU/optional/holidays.sql b/installer/data/mysql/ru-RU/optional/holidays.sql >index 42f3311..7d8e00b 100644 >--- a/installer/data/mysql/ru-RU/optional/holidays.sql >+++ b/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); > >diff --git a/installer/data/mysql/uk-UA/optional/holidays.sql b/installer/data/mysql/uk-UA/optional/holidays.sql >index 55f45be..f6ce5bd 100644 >--- a/installer/data/mysql/uk-UA/optional/holidays.sql >+++ b/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); > >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 7e54990..45e7bb9 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -8776,6 +8776,7 @@ if ( CheckVersion($DBversion) ) { > INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('StatisticsFields','location|itype|ccode','Define fields (from the items table) used for statistics members',NULL,'Free') > }); > print "Upgrade to $DBversion done (Bug 12728: Checked syspref StatisticsFields)\n"; >+ SetVersion($DBversion); > } > > $DBversion = "3.17.00.026"; >@@ -8952,6 +8953,80 @@ if ( CheckVersion($DBversion) ) { > SetVersion($DBversion); > } > >+$DBversion = "3.17.00.XXX"; >+if ( CheckVersion($DBversion) ) { >+ $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; >+ } ); >+ >+ print "Upgrade to $DBversion done (Bug 8133: create tables, migrate data to calendar_*)\n"; >+ SetVersion($DBversion); >+} >+ > =head1 FUNCTIONS > > =head2 TableExists($table) >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >index 13dd061..916195c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >@@ -87,7 +87,7 @@ > <h5>Additional tools</h5> > <ul> > [% IF ( CAN_user_tools_edit_calendar ) %] >- <li><a href="/cgi-bin/koha/tools/calendar.pl">Calendar</a></li> >+ <li><a href="/cgi-bin/koha/tools/calendar.pl">Calendar</a></li> > [% END %] > [% IF ( CAN_user_tools_manage_csv_profiles ) %] > <li><a href="/cgi-bin/koha/tools/csv-profiles.pl">CSV profiles</a></li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt >index b952253..4acb1cd 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/calendar.tt >@@ -5,7 +5,9 @@ > [% INCLUDE 'doc-head-close.inc' %] > [% INCLUDE 'calendar.inc' %] > <link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> >-[% INCLUDE 'datatables.inc' %] >+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.dataTables.min.js"></script> >+[% INCLUDE 'datatables-strings.inc' %] >+<script type="text/javascript" src="[% themelang %]/js/datatables.js"></script> > <script language="JavaScript" type="text/javascript"> > //<![CDATA[ > [% IF (dateformat == 'metric') %]dt_add_type_uk_date();[% END %] >@@ -87,7 +89,7 @@ > $('#showWeekday:first').val(weekDay); > $('#showTitle').val(event.title); > $('#showEventType').val(event.eventType); >- >+ > if (event.closed) { > $('#showHoursTypeClosed')[0].checked = true; > } else if (event.close_hour == 24) { >@@ -95,8 +97,8 @@ > } else { > $('#showHoursTypeOpenSet')[0].checked = true; > $('#showHoursTypeOpenSet').change(); >- $('#showOpenTime').val(event.open_hour + ':' + zeroPad(event.open_minute)); >- $('#showCloseTime').val(event.close_hour + ':' + zeroPad(event.close_minute)); >+ $('#showOpenTime').val(event.open_hour + ':' + zeroPad(event.open_minute)); >+ $('#showCloseTime').val(event.close_hour + ':' + zeroPad(event.close_minute)); > } > > $("#operationDelLabel").html(_("Delete this event.")); >@@ -215,7 +217,7 @@ > defaultDate: new Date("[% keydate %]") > }); > $(".hourssel input").change(function() { >- $(".hoursentry", this.form).toggle(this.value == 'openSet'); >+ $(".hoursentry", this.form).toggle(this.value == 'openSet'); > }).each( function() { this.checked = false } ); > }); > //]]> >@@ -261,7 +263,7 @@ li.hoursentry input { > <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> › [% branchname %] Calendar</div> > > <div id="doc3" class="yui-t1"> >- >+ > <div id="bd"> > <div id="yui-main"> > <div class="yui-b"> >@@ -278,7 +280,7 @@ li.hoursentry input { > [% END %] > [% END %] > </select> >- >+ > <!-- ******************************** FLAT PANELS ******************************************* --> > <!-- ***** Makes all the flat panel to deal with events ***** --> > <!-- **************************************************************************************** --> >@@ -297,8 +299,8 @@ li.hoursentry input { > </li> > <li> > <strong>From Date:</strong> >- <span id="showDaynameOutput"></span>, >- >+ <span id="showDaynameOutput"></span>, >+ > [% IF ( dateformat == "us" ) %]<span id="showMonthOutput"></span>/<span id="showDayOutput"></span>/<span id="showYearOutput"></span>[% ELSIF ( dateformat == "metric" ) %]<span id="showDayOutput"></span>/<span id="showMonthOutput"></span>/<span id="showYearOutput"></span>[% ELSE %]<span id="showYearOutput"></span>/<span id="showMonthOutput"></span>/<span id="showDayOutput"></span>[% END %] > > <input type="hidden" id="showWeekday" name="weekday" /> >@@ -311,7 +313,8 @@ li.hoursentry input { > <input type="text" id="datecancelrange" name="dateofrange" size="20" value="[% dateofrange %]" class="datepicker"/> > </li> > <li class="radio hourssel"> >- <input type="radio" name="hoursType" id="showHoursTypeOpen" value="open" /><label for="showHoursTypeOpen">Open (will delete repeating events)</label> >+ <input type="radio" name="hoursType" id="showHoursTypeOpen" value="open" /><label for="showHoursTypeOpen">Open</label> >+ <input type="radio" name="hoursType" id="showHoursTypeOpenSet" value="openSet" /><label for="showHoursTypeOpenSet">Open (with set hours)</label> > <input type="radio" name="hoursType" id="showHoursTypeClosed" value="closed" /><label for="showHoursTypeClosed">Closed</label> > </li> > <li class="radio hoursentry" style="display:none"> >@@ -321,9 +324,9 @@ li.hoursentry input { > <input type="time" name="closeTime" id="showCloseTime" size="3" maxlength="5" value="23:59" pattern="(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9])" /> > </li> > <li><label for="showTitle">Title: </label><input type="text" name="title" id="showTitle" size="35" /></li> >- <!-- showTitle is necessary for exception radio button to work properly --> >+ <!-- showTitle is necessary for exception radio button to work properly --> > <label for="showDescription">Description:</label> >- <textarea rows="2" cols="40" id="showDescription" name="description"></textarea> >+ <textarea rows="2" cols="40" id="showDescription" name="description"></textarea> > </li> > <li class="radio"><input type="radio" name="op" id="showOperationDel" value="delete" /> <label for="showOperationDel" id="showOperationDelLabel">Delete this event</label> > <a href="#" class="helptext">[?]</a> >@@ -351,7 +354,7 @@ li.hoursentry input { > <!-- ***************************** Panel to deal with new events ********************** --> > <div class="panel" id="newEvent"> > <form action="/cgi-bin/koha/tools/calendar.pl" method="post"> >- <input type="hidden" name="branchCodes" id="branchCodes" value="[% branchcodes %]" /> >+ <input type="hidden" name="branchCodes" id="branchCodes" value="[% branchcodes %]" /> > <input type="hidden" name="op" value="save" /> > <fieldset class="brief"> > <h3>Add new event</h3> >@@ -364,7 +367,7 @@ li.hoursentry input { > </li> > <li> > <strong>From date:</strong> >- <span id="newDaynameOutput"></span>, >+ <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>[% ELSE %]<span id="newYearOutput"></span>/<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>[% END %] > >@@ -378,7 +381,8 @@ li.hoursentry input { > <input type="text" id="dateofrange" name="dateofrange" size="20" value="[% dateofrange %]" class="datepicker" /> > </li> > <li class="radio hourssel"> >- <input type="radio" name="hoursType" id="newHoursTypeOpen" value="open" /><label for="newHoursTypeOpen">Open (will not work for repeating events)</label> >+ <input type="radio" name="hoursType" id="newHoursTypeOpen" value="open" /><label for="newHoursTypeOpen">Open</label> >+ <input type="radio" name="hoursType" id="newHoursTypeOpenSet" value="openSet" /><label for="newHoursTypeOpenSet">Open (with set hours)</label> > <input type="radio" name="hoursType" id="newHoursTypeClosed" value="closed" /><label for="newHoursTypeClosed">Closed</label> > </li> > <li class="radio hoursentry" style="display:none"> >@@ -493,21 +497,21 @@ li.hoursentry input { > <script type="text/javascript"> > document.write(weekdays[ [% event.weekday %]]); > </script> >- </td> >- <td>[% event.title %]</td> >- <td>[% event.description %]</td> >+ </td> >+ <td>[% event.title %]</td> >+ <td>[% event.description %]</td> > <td> > [% IF event.closed %] > Closed > [% ELSIF event.close_hour == 24 %] > Open > [% ELSE %] >- [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - >+ [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - > [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %] > [% END %] > </td> > </tr> >- [% END %] >+ [% END %] > </tbody> > </table> > [% END %] >@@ -531,20 +535,20 @@ li.hoursentry input { > [% FOREACH event IN yearly_events %] > <tr> > <td><span title="[% event.month_day_display %]">[% event.month_day_sort %]</span></td> >- <td>[% event.title %]</td> >- <td>[% event.description %]</td> >+ <td>[% event.title %]</td> >+ <td>[% event.description %]</td> > <td> > [% IF event.closed %] > Closed > [% ELSIF event.close_hour == 24 %] > Open > [% ELSE %] >- [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - >+ [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - > [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %] > [% END %] > </td> > </tr> >- [% END %] >+ [% END %] > </tbody> > </table> > [% END %] >@@ -572,12 +576,12 @@ li.hoursentry input { > [% ELSIF event.close_hour == 24 %] > Open > [% ELSE %] >- [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - >+ [% event.open_hour %]:[% event.open_minute > 10 ? event.open_minute : ( '0' _ event.open_minute) %] - > [% event.close_hour %]:[% event.close_minute > 10 ? event.close_minute : ( '0' _ event.close_minute) %] > [% END %] > </td> > </tr> >- [% END %] >+ [% END %] > </tbody> > </table> > [% END %] >diff --git a/misc/cronjobs/staticfines.pl b/misc/cronjobs/staticfines.pl >index 2f3d86c..779678d 100755 >--- a/misc/cronjobs/staticfines.pl >+++ b/misc/cronjobs/staticfines.pl >@@ -176,7 +176,7 @@ for ( my $i = 0 ; $i < scalar(@$data) ; $i++ ) { > $calendars{$branchcode} = Koha::Calendar->new( branchcode => $branchcode ); > } > $calendar = $calendars{$branchcode}; >- my $isHoliday = $calendar->is_holiday( DateTime->new( >+ my $isHoliday = $calendar->is_holiday( DateTime->new( > year => $tyear, > month => $tmonth, > day => $tday >diff --git a/t/Calendar.t b/t/Calendar.t >index 8c30c77..31e036a 100755 >--- a/t/Calendar.t >+++ b/t/Calendar.t >@@ -4,13 +4,15 @@ use strict; > use warnings; > use DateTime; > use DateTime::Duration; >-use Test::More tests => 34; >+use Test::More tests => 51; > use Test::MockModule; > use DBD::Mock; > use Koha::DateUtils; > > BEGIN { > use_ok('Koha::Calendar'); >+ use Carp; >+ $SIG{ __DIE__ } = sub { Carp::confess( @_ ) }; > } > > my $module_context = new Test::MockModule('C4::Context'); >@@ -38,38 +40,55 @@ SKIP: { > skip "DBD::Mock is too old", 33 > unless $DBD::Mock::VERSION >= 1.45; > >+# Apologies for strange indentation, DBD::Mock is picky > my $holidays_session = DBD::Mock::Session->new('holidays_session' => ( > { # weekly holidays >- statement => "SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL", >+ statement => 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 >+ }, > results => [ >- ['weekday'], >- [0], # sundays >- [6] # saturdays >+ ['weekday', 'open_hour', 'open_minute', 'close_hour', 'close_minute', 'closed'], >+ [0, 0, 0, 0, 0, 1], # sundays >+ [1,10, 0,19, 0, 0], # mondays >+ [2,10, 0,19, 0, 0], # tuesdays >+ [6, 0, 0, 0, 0, 1] # saturdays > ] > }, > { # day and month repeatable holidays >- statement => "SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL", >+ statement => 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 >+ }, > results => [ >- [ 'month', 'day' ], >- [ 1, 1 ], # new year's day >- [12,25] # christmas >+ [ 'month', 'day', 'open_hour', 'open_minute', 'close_hour', 'close_minute', 'closed' ], >+ [ 1, 1, 0, 0, 0, 0, 1], # new year's day >+ [ 6,26,10, 0,15, 0, 0], # wednesdays >+ [12,25, 0, 0, 0, 0, 1] # christmas > ] > }, > { # exception holidays >- statement => "SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1", >- results => [ >- [ 'day', 'month', 'year' ], >- [ 11, 11, 2012 ] # sunday exception >- ] >+ statement => 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 = ? > }, >- { # single holidays >- statement => "SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0", > results => [ >- [ 'day', 'month', 'year' ], >- [ 1, 6, 2011 ], # single holiday >- [ 4, 7, 2012 ] >+ [ 'event_date', 'open_hour', 'open_minute', 'close_hour', 'close_minute', 'closed' ], >+ [ '2012-11-11', 0, 0,24, 0, 0 ], # sunday exception >+ [ '2011-06-01', 0, 0, 0, 0, 1 ], # single holiday >+ [ '2012-07-04', 0, 0, 0, 0, 1 ], >+ [ '2014-06-26',12, 0,14, 0, 0 ] > ] >- } >+ }, > )); > > # Initialize the global $dbh variable >@@ -189,6 +208,22 @@ my $day_after_christmas = DateTime->new( > minute => 53, > ); > >+ my $same_day_dt = DateTime->new( # Monday >+ year => 2012, >+ month => 7, >+ day => 23, >+ hour => 13, >+ minute => 53, >+ ); >+ >+ my $after_close_dt = DateTime->new( # Monday >+ year => 2012, >+ month => 7, >+ day => 23, >+ hour => 22, >+ minute => 53, >+ ); >+ > my $later_dt = DateTime->new( # Monday > year => 2012, > month => 9, >@@ -232,13 +267,41 @@ my $day_after_christmas = DateTime->new( > is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-24', > 'Negative call to addDate (Datedue)' ); > >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => -10 ), 'hours' ),'eq', >+ '2012-07-20T15:53:00', >+ 'Subtract 10 hours (Datedue)' ); >+ >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => 10 ), 'hours' ),'eq', >+ '2012-07-24T12:53:00', >+ 'Add 10 hours (Datedue)' ); >+ >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => -1 ), 'hours' ),'eq', >+ '2012-07-23T10:53:00', >+ 'Subtract 1 hours (Datedue)' ); >+ >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => 1 ), 'hours' ),'eq', >+ '2012-07-23T12:53:00', >+ 'Add 1 hours (Datedue)' ); >+ > ## Note that the days_between API says closed days are not considered. > ## This tests are here as an API test. > cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'), >- '==', 40, 'days_between calculates correctly (Days)' ); >+ '==', 40, 'days_between calculates correctly (Datedue)' ); > > cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'), >- '==', 40, 'Test parameter order not relevant (Days)' ); >+ '==', 40, 'Test parameter order not relevant (Datedue)' ); >+ >+ cmp_ok( $cal->hours_between( $test_dt, $same_day_dt )->in_units('hours'), >+ '==', 2, 'hours_between calculates correctly (short period)' ); >+ >+ cmp_ok( $cal->hours_between( $test_dt, $after_close_dt )->in_units('hours'), >+ '==', 7, 'hours_between calculates correctly (after close)' ); >+ >+ cmp_ok( $cal->hours_between( $test_dt, $later_dt )->in_units('hours'), >+ '==', 725, 'hours_between calculates correctly (Datedue)' ); >+ >+ cmp_ok( $cal->hours_between( $later_dt, $test_dt )->in_units('hours'), >+ '==', 725, 'hours_between parameter order not relevant (Datedue)' ); > > > } >@@ -274,11 +337,33 @@ my $day_after_christmas = DateTime->new( > is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-24', > 'Negative call to addDate (Calendar)' ); > >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => -10 ), 'hours' ),'eq', >+ '2012-07-23T10:00:00', >+ 'Subtract 10 hours (Calendar)' ); >+ >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => 10 ), 'hours' ),'eq', >+ '2012-07-23T19:00:00', >+ 'Add 10 hours (Calendar)' ); >+ >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => -1 ), 'hours' ),'eq', >+ '2012-07-23T10:53:00', >+ 'Subtract 1 hours (Calendar)' ); >+ >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => 1 ), 'hours' ),'eq', >+ '2012-07-23T12:53:00', >+ 'Add 1 hours (Calendar)' ); >+ > cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'), > '==', 40, 'days_between calculates correctly (Calendar)' ); > > cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'), > '==', 40, 'Test parameter order not relevant (Calendar)' ); >+ >+ cmp_ok( $cal->hours_between( $test_dt, $later_dt )->in_units('hours'), >+ '==', 725, 'hours_between calculates correctly (Calendar)' ); >+ >+ cmp_ok( $cal->hours_between( $later_dt, $test_dt )->in_units('hours'), >+ '==', 725, 'hours_between parameter order not relevant (Calendar)' ); > } > > >@@ -311,6 +396,10 @@ my $day_after_christmas = DateTime->new( > is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-25', > 'Negative call to addDate (Days)' ); > >+ cmp_ok($cal->addDate( $test_dt, DateTime::Duration->new( hours => 10 ), 'hours' ),'eq', >+ '2012-07-23T21:53:00', >+ 'Add 10 hours (Days)' ); >+ > ## Note that the days_between API says closed days are not considered. > ## This tests are here as an API test. > cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'), >@@ -319,6 +408,12 @@ my $day_after_christmas = DateTime->new( > cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'), > '==', 40, 'Test parameter order not relevant (Days)' ); > >+ cmp_ok( $cal->hours_between( $test_dt, $later_dt )->in_units('hours'), >+ '==', 725, 'hours_between calculates correctly (Days)' ); >+ >+ cmp_ok( $cal->hours_between( $later_dt, $test_dt )->in_units('hours'), >+ '==', 725, 'hours_between parameter order not relevant (Days)' ); >+ > } > > } # End SKIP block >diff --git a/t/db_dependent/Calendar.t b/t/db_dependent/Calendar.t >index 162e09b..a55bb1d 100644 >--- a/t/db_dependent/Calendar.t >+++ b/t/db_dependent/Calendar.t >@@ -1,86 +1,78 @@ > use Modern::Perl; > >-use Test::More tests => 14; >+use Test::More tests => 18; > > use C4::Calendar; >-use C4::Context; > >-my $dbh = C4::Context->dbh; >- >-# Start transaction >-$dbh->{AutoCommit} = 0; >-$dbh->{RaiseError} = 1; >- >-my %new_holiday = ( open_hour => 0, >+my $new_holiday = { open_hour => 0, > open_minute => 0, > close_hour => 0, > close_minute => 0, > title => 'example week_day_holiday', >- description => 'This is an example week_day_holiday used for testing' ); >+ description => 'This is an example week_day_holiday used for testing' }; > > # Weekly events >-ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } ); >+ModRepeatingEvent( 'MPL', 1, undef, undef, $new_holiday ); > >-my $weekly_events = GetWeeklyEvents( 'UPL' ); >-is( $weekly_events->[0]->{'title'}, $new_holiday{'title'}, 'weekly title' ); >-is( $weekly_events->[0]->{'description'}, $new_holiday{'description'}, 'weekly description' ); >+my $weekly_events = GetWeeklyEvents( 'MPL' ); >+is( $weekly_events->[0]->{'title'}, $new_holiday->{'title'}, 'weekly title' ); >+is( $weekly_events->[0]->{'description'}, $new_holiday->{'description'}, 'weekly description' ); >+is( $weekly_events->[0]->{'open_hour'}, 0, 'weekly open_hour' ); > >-$new_holiday{close_hour} = 24; >+$new_holiday->{open_hour} = 7; > >-ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } ); >-$weekly_events = GetWeeklyEvents( 'UPL' ); >-is( scalar @$weekly_events, 0, 'weekly modification, not insertion' ); >+ModRepeatingEvent( 'MPL', 1, undef, undef, $new_holiday ); >+$weekly_events = GetWeeklyEvents( 'MPL' ); >+is( scalar @$weekly_events, 1, 'weekly modification, not insertion' ); >+is( $weekly_events->[0]->{'open_hour'}, 7, 'weekly open_hour modified' ); > >-$new_holiday{close_hour} = 0; >-ModRepeatingEvent( 'UPL', { weekday => 1, %new_holiday } ); > > # Yearly events > >-ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } ); >+$new_holiday->{open_hour} = 0; >+ModRepeatingEvent( 'MPL', undef, 6, 26, $new_holiday ); > >-my $yearly_events = GetYearlyEvents( 'UPL' ); >-is( $yearly_events->[0]->{'title'}, $new_holiday{'title'}, 'yearly title' ); >-is( $yearly_events->[0]->{'description'}, $new_holiday{'description'}, 'yearly description' ); >+my $yearly_events = GetYearlyEvents( 'MPL' ); >+is( $yearly_events->[0]->{'title'}, $new_holiday->{'title'}, 'yearly title' ); >+is( $yearly_events->[0]->{'description'}, $new_holiday->{'description'}, 'yearly description' ); >+is( $yearly_events->[0]->{'open_hour'}, 0, 'yearly open_hour' ); > >-$new_holiday{close_hour} = 24; >+$new_holiday->{open_hour} = 8; > >-ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } ); >-$yearly_events = GetYearlyEvents( 'UPL' ); >-is( scalar @$yearly_events, 0, 'yearly modification, not insertion' ); >- >-$new_holiday{close_hour} = 0; >-ModRepeatingEvent( 'UPL', { month => 6, day => 26, %new_holiday } ); >+ModRepeatingEvent( 'MPL', undef, 6, 26, $new_holiday ); >+$yearly_events = GetYearlyEvents( 'MPL' ); >+is( scalar @$yearly_events, 1, 'yearly modification, not insertion' ); >+is( $yearly_events->[0]->{'open_hour'}, 8, 'yearly open_hour' ); > > # Single events > >-ModSingleEvent( 'UPL', { date => '2013-03-17', %new_holiday } ); >+$new_holiday->{open_hour} = 0; >+ModSingleEvent( 'MPL', '2013-03-17', $new_holiday ); > >-my $single_events = GetSingleEvents( 'UPL' ); >-is( $single_events->[0]->{'title'}, $new_holiday{'title'}, 'single title' ); >-is( $single_events->[0]->{'description'}, $new_holiday{'description'}, 'single description' ); >-is( $single_events->[0]->{'closed'}, 1, 'single closed' ); >+my $single_events = GetSingleEvents( 'MPL' ); >+is( $single_events->[0]->{'title'}, $new_holiday->{'title'}, 'single title' ); >+is( $single_events->[0]->{'description'}, $new_holiday->{'description'}, 'single description' ); >+is( $single_events->[0]->{'open_hour'}, 0, 'single open_hour' ); > >-$new_holiday{close_hour} = 24; >+$new_holiday->{open_hour} = 11; > >-ModSingleEvent( 'UPL', { date => '2013-03-17', %new_holiday } ); >-$single_events = GetSingleEvents( 'UPL' ); >+ModSingleEvent( 'MPL', '2013-03-17', $new_holiday ); >+$single_events = GetSingleEvents( 'MPL' ); > is( scalar @$single_events, 1, 'single modification, not insertion' ); >-is( $single_events->[0]->{'closed'}, 0, 'single closed' ); >+is( $single_events->[0]->{'open_hour'}, 11, 'single open_hour' ); > > > # delete > >-DelRepeatingEvent( 'UPL', { weekday => 1 } ); >-$weekly_events = GetWeeklyEvents( 'UPL' ); >+DelRepeatingEvent( 'MPL', 1, undef, undef ); >+$weekly_events = GetWeeklyEvents( 'MPL' ); > is( scalar @$weekly_events, 0, 'weekly deleted' ); > >-DelRepeatingEvent( 'UPL', { month => 6, day => 26 } ); >-$yearly_events = GetYearlyEvents( 'UPL' ); >+DelRepeatingEvent( 'MPL', undef, 6, 26 ); >+$yearly_events = GetYearlyEvents( 'MPL' ); > is( scalar @$yearly_events, 0, 'yearly deleted' ); > >-DelSingleEvent( 'UPL', { date => '2013-03-17' } ); >+DelSingleEvent( 'MPL', '2013-03-17' ); > >-$single_events = GetSingleEvents( 'UPL' ); >+$single_events = GetSingleEvents( 'MPL' ); > is( scalar @$single_events, 0, 'single deleted' ); >- >-$dbh->rollback; >diff --git a/tools/calendar.pl b/tools/calendar.pl >index d4bcf48..0146fad 100755 >--- a/tools/calendar.pl >+++ b/tools/calendar.pl >@@ -2,22 +2,22 @@ > > # 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 free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. > # >-# Koha is distributed in the hope that it will be useful, but >-# WITHOUT ANY WARRANTY; without even the implied warranty of >-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >-# GNU General Public License for more details. >+# 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>. >+# You should have received a copy of the GNU General Public License along with >+# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, >+# Suite 330, Boston, MA 02111-1307 USA > > #####Sets holiday periods for each branch. Datedues will be extended if branch is closed -TG > >-use Modern::Perl; >+use Modern::Perl '2009'; > > use CGI; > >@@ -55,13 +55,13 @@ unless($keydate = $calendarinput->output('iso')) { > } > $keydate =~ s/-/\//g; > >-my $branch= $input->param('branchName') || $input->param('branch') || C4::Context->userenv->{'branch'}; >+my $branch= $input->param('branch') || C4::Context->userenv->{'branch'}; > # Set all the branches. > my $onlymine=(C4::Context->preference('IndependentBranches') && > C4::Context->userenv && > C4::Context->userenv->{flags} % 2 !=1 && > C4::Context->userenv->{branch}?1:0); >-if ( $onlymine ) { >+if ( $onlymine ) { > $branch = C4::Context->userenv->{'branch'}; > } > my $branchname = GetBranchName($branch); >@@ -110,7 +110,7 @@ if ( $input->param( 'allBranches' ) || !$input->param( 'branchName' ) ) { > if ( $op eq 'save' ) { > my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' ); > >- local our ( $open_hour, $open_minute, $close_hour, $close_minute ); >+ my ( $open_hour, $open_minute, $close_hour, $close_minute ); > > if ( $input->param( 'hoursType' ) eq 'open' ) { > ( $open_hour, $open_minute ) = ( 0, 0 ); >@@ -124,10 +124,9 @@ if ( $op eq 'save' ) { > } > > foreach my $branchcode ( @branches ) { >- my %event_types = ( >- 'single' => sub { >- ModSingleEvent( $branchcode, { >- date => $date, >+ given ( $input->param( 'eventType' ) ) { >+ when ( 'single' ) { >+ ModSingleEvent( $branchcode, $date, { > title => $input->param( 'title' ), > description => $input->param( 'description' ), > open_hour => $open_hour, >@@ -135,11 +134,10 @@ if ( $op eq 'save' ) { > close_hour => $close_hour, > close_minute => $close_minute > } ); >- }, >+ } > >- 'weekly' => sub { >- ModRepeatingEvent( $branchcode, { >- weekday => $input->param( 'weekday' ), >+ when ( 'weekly' ) { >+ ModRepeatingEvent( $branchcode, $input->param( 'weekday' ), undef, undef, { > title => $input->param( 'title' ), > description => $input->param( 'description' ), > open_hour => $open_hour, >@@ -147,12 +145,10 @@ if ( $op eq 'save' ) { > close_hour => $close_hour, > close_minute => $close_minute > } ); >- }, >+ } > >- 'yearly' => sub { >- ModRepeatingEvent( $branchcode, { >- month => $input->param( 'month' ), >- day => $input->param( 'day' ), >+ when ( 'yearly' ) { >+ ModRepeatingEvent( $branchcode, undef, $input->param( 'month' ), $input->param( 'day' ), { > title => $input->param( 'title' ), > description => $input->param( 'description' ), > open_hour => $open_hour, >@@ -160,12 +156,11 @@ if ( $op eq 'save' ) { > close_hour => $close_hour, > close_minute => $close_minute > } ); >- }, >+ } > >- 'singlerange' => sub { >+ when ( 'singlerange' ) { > foreach my $dt ( @ranged_dates ) { >- ModSingleEvent( $branchcode, { >- date => $dt->ymd, >+ ModSingleEvent( $branchcode, $dt->ymd, { > title => $input->param( 'title' ), > description => $input->param( 'description' ), > open_hour => $open_hour, >@@ -174,13 +169,11 @@ if ( $op eq 'save' ) { > close_minute => $close_minute > } ); > } >- }, >+ } > >- 'yearlyrange' => sub { >+ when ( 'yearlyrange' ) { > foreach my $dt ( @ranged_dates ) { >- ModRepeatingEvent( $branchcode, { >- month => $dt->month, >- day => $dt->day, >+ ModRepeatingEvent( $branchcode, undef, $dt->month, $dt->day, { > title => $input->param( 'title' ), > description => $input->param( 'description' ), > open_hour => $open_hour, >@@ -189,43 +182,37 @@ if ( $op eq 'save' ) { > close_minute => $close_minute > } ); > } >- }, >- ); >- >- # Choose from the above options >- $event_types{ $input->param( 'eventType' ) }->(); >+ } >+ } > } > } elsif ( $op eq 'delete' ) { > my $date = $input->param( 'year' ) . '-' . $input->param( 'month' ) . '-' . $input->param( 'day' ); > > foreach my $branchcode ( @branches ) { >- my %event_types = ( >- 'single' => sub { >- DelSingleEvent( $branchcode, { date => $date } ); >- }, >- >- 'weekly' => sub { >- DelRepeatingEvent( $branchcode, { weekday => $input->param( 'weekday' ) } ); >- }, >- >- 'yearly' => sub { >- DelRepeatingEvent( $branchcode, { month => $input->param( 'month' ), day => $input->param( 'day' ) } ); >- }, >- ); >- >- # Choose from the above options >- $event_types{ $input->param( 'eventType' ) }->(); >+ given ( $input->param( 'eventType' ) ) { >+ when ( 'single' ) { >+ DelSingleEvent( $branchcode, $date ); >+ } >+ >+ when ( 'weekly' ) { >+ DelRepeatingEvent( $branchcode, $input->param( 'weekday' ), undef, undef ); >+ } >+ >+ when ( 'yearly' ) { >+ DelRepeatingEvent( $branchcode, undef, $input->param( 'month' ), $input->param( 'day' ) ); >+ } >+ } > } > } elsif ( $op eq 'deleterange' ) { > foreach my $branchcode ( @branches ) { > foreach my $dt ( @ranged_dates ) { >- DelSingleEvent( $branchcode, { date => $dt->ymd } ); >+ DelSingleEvent( $branchcode, $dt->ymd ); > } > } > } elsif ( $op eq 'deleterangerepeat' ) { > foreach my $branchcode ( @branches ) { > foreach my $dt ( @ranged_dates ) { >- DelRepeatingEvent( $branchcode, { month => $dt->month, day => $dt->day } ); >+ DelRepeatingEvent( $branchcode, undef, $dt->month, $dt->day ); > } > } > } elsif ( $op eq 'copyall' ) { >-- >1.7.2.5
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 8133
:
19326
|
19494
|
19740
|
29336
|
31973
|
32176
|
32327
| 32985 |
32986
|
32990
|
32991