From 35b02051fd4014ef84e35fe76412b397ada70c8f Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 28 May 2014 13:56:38 +0300 Subject: [PATCH] Bug 12353 - Everybody needs to know the last pickup date for reserves! When calculating the last date before reserve expires, skip all days marked as holidays. Add a new <> marker usable in RESERVESLIP and HOLD. Display the last pickup date in member/moremember.pl and circ/circulation.pl and circ/waitingreserves.pl opac/opac-user.pl --- C4/Reserves.pm | 49 ++++++++++++++--- Koha/Calendar.pm | 12 +++++ Koha/Reserves.pm | 55 ++++++++++++++++++++ circ/waitingreserves.pl | 19 +++---- koha-tmpl/intranet-tmpl/prog/en/js/holds.js | 1 + .../en/modules/admin/preferences/circulation.pref | 2 +- .../prog/en/modules/circ/circulation.tt | 2 + .../prog/en/modules/circ/waitingreserves.tt | 4 ++ .../prog/en/modules/members/moremember.tt | 1 + .../opac-tmpl/bootstrap/en/modules/opac-user.tt | 7 +++ opac/opac-user.pl | 4 ++ svc/holds | 8 ++- 12 files changed, 143 insertions(+), 21 deletions(-) create mode 100644 Koha/Reserves.pm diff --git a/C4/Reserves.pm b/C4/Reserves.pm index cf4211e..6483c8f 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 ); @@ -132,6 +135,8 @@ BEGIN { &ToggleSuspend &SuspendAll + &_reserve_last_pickup_date + &GetReservesControlBranch ); @EXPORT_OK = qw( MergeHolds ); @@ -719,7 +724,7 @@ sub GetReservesForBranch { my $dbh = C4::Context->dbh; my $query = " - SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate + SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate,branchcode FROM reserves WHERE priority='0' AND found='W' @@ -935,12 +940,16 @@ sub CancelExpiredReserves { $sth = $dbh->prepare( $query ); $sth->execute( $max_pickup_delay ); + my $today = DateTime->now( time_zone => C4::Context->tz() ); + while (my $res = $sth->fetchrow_hashref ) { - if ( $charge ) { - manualinvoice($res->{'borrowernumber'}, $res->{'itemnumber'}, 'Hold waiting too long', 'F', $charge); + my $expiration = _reserve_last_pickup_date( $res ); + if ( $today > $expiration ) { + if ( $charge ) { + manualinvoice($res->{'borrowernumber'}, $res->{'itemnumber'}, 'Hold waiting too long', 'F', $charge); + } + CancelReserve({ reserve_id => $res->{'reserve_id'} }); } - - CancelReserve({ reserve_id => $res->{'reserve_id'} }); } } @@ -1815,6 +1824,24 @@ 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, $reserve_id ); @@ -1851,6 +1878,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}, @@ -1861,7 +1890,10 @@ sub _koha_notify_reserve { 'reserves' => $reserve, 'items', $reserve->{'itemnumber'}, }, - substitute => { today => C4::Dates->new()->output() }, + substitute => { + 'lastpickupdate' => C4::Dates->new($expiration->ymd(), 'iso')->output() + }, + ); my $notification_sent = 0; #Keeping track if a Hold_filled message is sent. If no message can be sent, then default to a print message. @@ -2195,6 +2227,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 => $transfer ? 'TRANSFERSLIP' : 'RESERVESLIP', @@ -2206,6 +2240,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..04f655d 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; diff --git a/Koha/Reserves.pm b/Koha/Reserves.pm new file mode 100644 index 0000000..6e2c370 --- /dev/null +++ b/Koha/Reserves.pm @@ -0,0 +1,55 @@ +package Koha::Reserves; + +# Copyright (c) 2014 Vaarakirjastot.fi and everybody else! +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; +binmode STDOUT, ":encoding(UTF-8)"; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); + +BEGIN { + # set the version for version checking + $VERSION = 3.16.3; + require Exporter; + @ISA = qw(Exporter); + @EXPORT = qw( + + &GetLastpickupdate + + ); +} + +use C4::Context; +use Koha::DateUtils; + +=head2 GetLastpickupdate + + my $last_dt = GetLastpickupdate($reserve); + +@PARAM1 Koha::Schema::Result::Reserve-object received via DBIx searching +@RETURNS the DateTime for the last pickup date for the given reserve. +=cut + +sub GetLastpickupdate { + my ($reserve) = @_; + + my $waitingdate = $reserve->waitingdate(); + my $startdate = $waitingdate ? Koha::DateUtils::dt_from_string($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; +} \ No newline at end of file diff --git a/circ/waitingreserves.pl b/circ/waitingreserves.pl index fb7a3d1..f4a93f0 100755 --- a/circ/waitingreserves.pl +++ b/circ/waitingreserves.pl @@ -31,11 +31,8 @@ use C4::Members; use C4::Biblio; use C4::Items; -use Date::Calc qw( - Today - Add_Delta_Days - Date_to_Days -); +use DateTime; + use C4::Reserves; use C4::Koha; @@ -86,7 +83,7 @@ my ($reservcount, $overcount); my @getreserves = $all_branches ? GetReservesForBranch() : GetReservesForBranch($default); # get reserves for the branch we are logged into, or for all branches -my $today = Date_to_Days(&Today); +my $today = DateTime->now(); foreach my $num (@getreserves) { next unless ($num->{'waitingdate'} && $num->{'waitingdate'} ne '0000-00-00'); @@ -106,13 +103,11 @@ foreach my $num (@getreserves) { my $getborrower = GetMember(borrowernumber => $num->{'borrowernumber'}); my $itemtypeinfo = getitemtypeinfo( $gettitle->{'itemtype'} ); # using the fixed up itype/itemtype $getreserv{'waitingdate'} = $num->{'waitingdate'}; - my ( $waiting_year, $waiting_month, $waiting_day ) = split (/-/, $num->{'waitingdate'}); - ( $waiting_year, $waiting_month, $waiting_day ) = - Add_Delta_Days( $waiting_year, $waiting_month, $waiting_day, - C4::Context->preference('ReservesMaxPickUpDelay')); - my $calcDate = Date_to_Days( $waiting_year, $waiting_month, $waiting_day ); + + my $lastpickupdate = C4::Reserves::_reserve_last_pickup_date( $num ); $getreserv{'itemtype'} = $itemtypeinfo->{'description'}; + $getreserv{'lastpickupdate'} = C4::Dates->new($lastpickupdate->ymd(), 'iso')->output(); $getreserv{'title'} = $gettitle->{'title'}; $getreserv{'biblionumber'} = $gettitle->{'biblionumber'}; $getreserv{'barcode'} = $gettitle->{'barcode'}; @@ -132,7 +127,7 @@ foreach my $num (@getreserves) { $getreserv{'borrowermail'} = $getborrower->{'emailaddress'}; } - if ($today > $calcDate) { + if ( DateTime->compare( $today,$lastpickupdate ) == 1 ) { #If today is bigger than lastpickupdate, pickup time has expired if ($cancelall) { my $res = cancel( $itemnumber, $borrowernum, $holdingbranch, $homebranch, !$transfer_when_cancel_all ); push @cancel_result, $res if $res; diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js index 73807ea..c78e3ae 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js @@ -10,6 +10,7 @@ $(document).ready(function() { { "mDataProp": "reservedate_formatted" }, + { "mDataProp": "lastpickupdate_formatted" }, { "mDataProp": function ( oObj ) { title = " @@ -138,6 +140,7 @@ + @@ -148,6 +151,7 @@ [% FOREACH overloo IN overloop %] + + diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt index ec3de30..485cefb 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt @@ -493,6 +493,7 @@ + [% IF ( showpriority ) %] @@ -530,6 +531,12 @@ [% RESERVE.reservedate | $KohaDates %] +
Available sinceLast pickup date Title Patron Location

[% overloo.waitingdate | $KohaDates %]

[% overloo.lastpickupdate | $KohaDates %] [% INCLUDE 'biblio-default-view.inc' biblionumber = overloo.biblionumber %][% overloo.title |html %] [% overloo.subtitle |html %] [% UNLESS ( item_level_itypes ) %][% IF ( overloo.itemtype ) %]  ([% overloo.itemtype %])[% END %][% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt index d6b95f8..6a0cde0 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -506,6 +506,7 @@ function validate1(date) {
Hold dateLast pickup date Title Call number Barcode
Title Placed onLast pickup date Expires on Pick up location + + Last pickup date: + [% RESERVE.lastpickupdate | $KohaDates %] + + [% IF ( RESERVE.expirationdate ) %] diff --git a/opac/opac-user.pl b/opac/opac-user.pl index 667ac3d..9bf9d4e 100755 --- a/opac/opac-user.pl +++ b/opac/opac-user.pl @@ -321,6 +321,10 @@ foreach my $res (@reserves) { } # set found to 1 if reserve is waiting for patron pickup $res->{'found'} = 1 if $res->{'found'} eq 'W'; + + my $lastpickupdate = C4::Reserves::_reserve_last_pickup_date( $res ); + $res->{'lastpickupdate'} = $lastpickupdate if $lastpickupdate; + } else { my ($transfertwhen, $transfertfrom, $transfertto) = GetTransfers( $res->{'itemnumber'} ); if ($transfertwhen) { diff --git a/svc/holds b/svc/holds index 3ff704f..7a72385 100755 --- a/svc/holds +++ b/svc/holds @@ -31,6 +31,7 @@ use C4::Context; use Koha::Database; use Koha::DateUtils; +use Koha::Reserves; my $input = new CGI; @@ -53,8 +54,8 @@ my $borrowernumber = $input->param('borrowernumber'); my $offset = $input->param('iDisplayStart'); my $results_per_page = $input->param('iDisplayLength'); my $sorting_direction = $input->param('sSortDir_0') || 'desc'; -my $sorting_column = $sort_columns[ $input->param('iSortCol_0') ] - || 'reservedate'; +my $sorting_column = ( $input->param('iSortCol_0') ) ? + $sort_columns[ $input->param('iSortCol_0') ] : 'reservedate'; binmode STDOUT, ":encoding(UTF-8)"; print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); @@ -73,6 +74,7 @@ while ( my $h = $holds_rs->next() ) { my $item = $h->item(); my $biblionumber = $h->biblio()->biblionumber(); + my $lastpickupdate = Koha::Reserves::GetLastpickupdate( $h ); my $hold = { DT_RowId => $h->reserve_id(), @@ -93,6 +95,8 @@ while ( my $h = $holds_rs->next() ) { 'subtitle', GetMarcBiblio($biblionumber), GetFrameworkCode($biblionumber) ), + lastpickupdate => $lastpickupdate->ymd(), + lastpickupdate_formatted => C4::Dates->new($lastpickupdate->ymd(), 'iso')->output(), reservedate_formatted => $h->reservedate() ? output_pref( { dt => dt_from_string( $h->reservedate() ), dateonly => 1 } ) -- 1.7.9.5