From 48d75e7366cfee100c7858055f71c06152d33ba1 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Tue, 8 Apr 2014 08:10:53 +0300 Subject: [PATCH] When calculating the last date before reserve expires, skip all days marked as holidays. Add a new <> marker usable in RESERVESLIP and HOLD. --- C4/Reserves.pm | 49 +++++++++++++++++++--- Koha/Calendar.pm | 19 +++++++++ .../en/modules/admin/preferences/circulation.pref | 2 +- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/C4/Reserves.pm b/C4/Reserves.pm index eb1ae2b..ed52bd4 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -38,6 +38,9 @@ use C4::Branch qw( GetBranchDetail ); use C4::Dates qw( format_date_in_iso ); use Koha::DateUtils; +use Koha::Calendar; + +use DateTime; use List::MoreUtils qw( firstidx ); @@ -981,15 +984,23 @@ sub CancelExpiredReserves { my $charge = C4::Context->preference("ExpireReservesMaxPickUpDelayCharge"); my $query = "SELECT * FROM reserves WHERE TO_DAYS( NOW() ) - TO_DAYS( waitingdate ) > ? AND found = 'W' AND priority = 0"; + + my $today = DateTime->now( time_zone => C4::Context->tz() ); + $sth = $dbh->prepare( $query ); $sth->execute( $max_pickup_delay ); while (my $res = $sth->fetchrow_hashref ) { - if ( $charge ) { - manualinvoice($res->{'borrowernumber'}, $res->{'itemnumber'}, 'Hold waiting too long', 'F', $charge); - } - CancelReserve({ reserve_id => $res->{'reserve_id'} }); + my $calendar = Koha::Calendar->new( branchcode => $res->{branchcode} ); + my $expiration = $calendar->days_forward( $res->{waitingdate}, $max_pickup_delay ); + + if ( $today > $expiration ) { + if ( $charge ) { + manualinvoice($res->{'borrowernumber'}, $res->{'itemnumber'}, 'Hold waiting too long', 'F', $charge); + } + CancelReserve({ reserve_id => $res->{'reserve_id'} }); + } } } @@ -1871,6 +1882,25 @@ sub _Findgroupreserve { return @results; } +=head2 _reserve_last_pickup_date + + my $last_dt = _reserve_last_pickup_date($reserve); + +Returns the DateTime for the last pickup date for reserve. + +=cut + +sub _reserve_last_pickup_date { + my ($reserve) = @_; + + my $startdate = $reserve->{waitingdate} ? dt_from_string($reserve->{waitingdate}) : DateTime->now( time_zone => C4::Context->tz() ); + my $calendar = Koha::Calendar->new( branchcode => $reserve->{branchcode} ); + my $expiration = $calendar->days_forward( $startdate, C4::Context->preference('ReservesMaxPickUpDelay') ); + + return $expiration; +} + + =head2 _koha_notify_reserve _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ); @@ -1910,6 +1940,8 @@ sub _koha_notify_reserve { my $admin_email_address = $branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress'); + my $expiration = _reserve_last_pickup_date($reserve); + my %letter_params = ( module => 'reserves', branchcode => $reserve->{branchcode}, @@ -1920,7 +1952,9 @@ sub _koha_notify_reserve { 'reserves' => $reserve, 'items', $reserve->{'itemnumber'}, }, - substitute => { today => C4::Dates->new()->output() }, + substitute => { + 'lastpickupdate' => C4::Dates->new($expiration->ymd(), 'iso')->output() + }, ); @@ -2223,6 +2257,8 @@ sub ReserveSlip { }) or return; my $reserve = GetReserveInfo($reserve_id) or return; + my $expiration = _reserve_last_pickup_date($reserve); + return C4::Letters::GetPreparedLetter ( module => 'circulation', letter_code => 'RESERVESLIP', @@ -2234,6 +2270,9 @@ sub ReserveSlip { 'biblio' => $reserve->{biblionumber}, 'items' => $reserve->{itemnumber}, }, + substitute => { + 'lastpickupdate' => C4::Dates->new($expiration->ymd(), 'iso')->output() + }, ); } diff --git a/Koha/Calendar.pm b/Koha/Calendar.pm index 276c7ce..e634010 100644 --- a/Koha/Calendar.pm +++ b/Koha/Calendar.pm @@ -267,6 +267,18 @@ sub prev_open_day { return $base_date; } +sub days_forward { + my $self = shift; + my $start_dt = shift; + my $num_days = shift; + + my $base_dt = $start_dt->clone(); + + while ($num_days--) { $base_dt = $self->next_open_day($base_dt); } + + return $base_dt; +} + sub days_between { my $self = shift; my $start_dt = shift; @@ -434,6 +446,13 @@ $yesno = $calendar->is_holiday($dt); passed a DateTime object returns 1 if it is a closed day 0 if not according to the calendar +=head2 days_forward + +$due_dt = $calendar->days_forward($start_dt, $num_days); + +Passed a DateTime object and a positive number of days, returns the DateTime when +$num_days non-holiday days (including the current day) have been skipped. + =head2 days_between $duration = $calendar->days_between($start_dt, $end_dt); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index 7d44f79..926cede 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -398,7 +398,7 @@ Circulation: - Mark a hold as problematic if it has been waiting for more than - pref: ReservesMaxPickUpDelay class: integer - - days. + - non-holiday days. - - pref: ExpireReservesMaxPickUpDelay choices: -- 1.8.3.2