From f50ee2803f516c3d11a899c3a78f29db9a6ec994 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Mon, 8 Jun 2015 08:14:20 -0400 Subject: [PATCH] Bug 14364 - Allow automatically canceled expired waiting holds to fill the next hold Right now, if a library automatically cancels expired waiting holds, a librarian must still re-checkin an item to trap the next available hold for that item. It would be better if the next hold was automatically trapped and the librarians receive an email notification so they can make any changes to the item if need be ( hold area, hold slip in item, etc ). Test Plan: 1) Apply this patch 2) Run updatedatabase.pl 3) Create a record with one item 4) Place two holds on that record 5) Check in the item and set it to waiting for the first patron 6) Set ReservesMaxPickUpDelay to 1 7) Enable ExpireReservesMaxPickUpDelay 8) Enable ExpireReservesAutoFill 9) Set an email address in ExpireReservesAutoFillEmail 10) Modify the holds waitingdate to be in the past 11) Run misc/cronjobs/holds/cancel_expired_holds.pl 12) Note the hold is now waiting for the next patron 12) Note a waiting hold notification email was sent to that patron 13) Note a hold changed notification email was sent to the library Signed-off-by: Gene Miller --- C4/Reserves.pm | 143 +++++++++++++++++---- C4/SIP/ILS/Transaction/Checkin.pm | 18 ++- circ/branchtransfers.pl | 2 +- circ/returns.pl | 5 +- installer/data/mysql/atomicupdate/bug_14364.sql | 13 ++ .../data/mysql/de-DE/mandatory/sample_notices.sql | 9 ++ .../data/mysql/en/mandatory/sample_notices.sql | 9 ++ .../data/mysql/es-ES/mandatory/sample_notices.sql | 9 ++ .../mysql/fr-FR/1-Obligatoire/sample_notices.sql | 9 ++ .../mysql/nb-NO/1-Obligatorisk/sample_notices.sql | 9 ++ .../data/mysql/pl-PL/mandatory/sample_notices.sql | 9 ++ .../data/mysql/ru-RU/mandatory/sample_notices.sql | 9 ++ installer/data/mysql/sysprefs.sql | 2 + .../data/mysql/uk-UA/mandatory/sample_notices.sql | 9 ++ .../en/modules/admin/preferences/circulation.pref | 10 ++ t/db_dependent/Holds/RevertWaitingStatus.t | 2 +- t/db_dependent/Reserves.t | 14 +- 17 files changed, 239 insertions(+), 42 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_14364.sql diff --git a/C4/Reserves.pm b/C4/Reserves.pm index fbeca06..11900fc 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -452,7 +452,7 @@ sub CanItemBeReserved{ my $dbh = C4::Context->dbh; my $ruleitemtype; # itemtype of the matching issuing rule my $allowedreserves = 0; - + # we retrieve borrowers and items informations # # item->{itype} will come for biblioitems if necessery my $item = GetItem($itemnumber); @@ -488,8 +488,8 @@ sub CanItemBeReserved{ LEFT JOIN borrowers USING (borrowernumber) WHERE borrowernumber = ? "; - - + + my $branchcode = ""; my $branchfield = "reserves.branchcode"; @@ -500,12 +500,12 @@ sub CanItemBeReserved{ $branchfield = "borrowers.branchcode"; $branchcode = $borrower->{branchcode}; } - - # we retrieve rights + + # we retrieve rights $sth->execute($borrower->{'categorycode'}, $item->{'itype'}, $branchcode); if(my $rights = $sth->fetchrow_hashref()){ $ruleitemtype = $rights->{itemtype}; - $allowedreserves = $rights->{reservesallowed}; + $allowedreserves = $rights->{reservesallowed}; }else{ $ruleitemtype = '*'; } @@ -513,7 +513,7 @@ sub CanItemBeReserved{ # we retrieve count $querycount .= "AND $branchfield = ?"; - + # If using item-level itypes, fall back to the record # level itemtype if the hold has no associated item $querycount .= @@ -523,7 +523,7 @@ sub CanItemBeReserved{ if ( $ruleitemtype ne "*" ); my $sthcount = $dbh->prepare($querycount); - + if($ruleitemtype eq "*"){ $sthcount->execute($borrowernumber, $branchcode); }else{ @@ -737,8 +737,8 @@ sub GetReservesToBranch { my $dbh = C4::Context->dbh; my $sth = $dbh->prepare( "SELECT reserve_id,borrowernumber,reservedate,itemnumber,timestamp - FROM reserves - WHERE priority='0' + FROM reserves + WHERE priority='0' AND branchcode=?" ); $sth->execute( $frombranch ); @@ -763,7 +763,7 @@ sub GetReservesForBranch { my $query = " SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate - FROM reserves + FROM reserves WHERE priority='0' AND found='W' "; @@ -1016,7 +1016,13 @@ sub CancelExpiredReserves { } if ( $do_cancel ) { - CancelReserve({ reserve_id => $res->{'reserve_id'}, charge_cancel_fee => 1 }); + CancelReserve( + { + reserve_id => $res->{'reserve_id'}, + autofill => C4::Context->preference('ExpireReservesAutoFill'), + charge_cancel_fee => 1, + } + ); } } } @@ -1041,7 +1047,7 @@ sub AutoUnsuspendReserves { =head2 CancelReserve - CancelReserve({ reserve_id => $reserve_id, [ biblionumber => $biblionumber, borrowernumber => $borrrowernumber, itemnumber => $itemnumber, ] [ charge_cancel_fee => 1 ] }); + CancelReserve({ reserve_id => $reserve_id, [ biblionumber => $biblionumber, borrowernumber => $borrrowernumber, itemnumber => $itemnumber, charge_cancel_fee => 1, autofill => $autofill ] }); Cancels a reserve. If C is passed and the C syspref is set, charge that fee to the patron's account. @@ -1051,10 +1057,13 @@ sub CancelReserve { my ( $params ) = @_; my $reserve_id = $params->{'reserve_id'}; + my $autofill = $params->{autofill}; + # Filter out only the desired keys; this will insert undefined values for elements missing in # \%params, but GetReserveId filters them out anyway. $reserve_id = GetReserveId( { biblionumber => $params->{'biblionumber'}, borrowernumber => $params->{'borrowernumber'}, itemnumber => $params->{'itemnumber'} } ) unless ( $reserve_id ); + return unless ( $reserve_id ); my $dbh = C4::Context->dbh; @@ -1094,6 +1103,26 @@ sub CancelReserve { if ( $charge && $params->{'charge_cancel_fee'} ) { manualinvoice($reserve->{'borrowernumber'}, $reserve->{'itemnumber'}, 'Hold waiting too long', 'F', $charge); } + + # only attempt to autofill canceled holds that were found and waiting + if ( $autofill && $reserve->{itemnumber} && $reserve->{found} && $reserve->{found} eq 'W' ) { + my ( undef, $next_hold ) = CheckReserves( $reserve->{'itemnumber'} ); + if ($next_hold) { + my $is_transfer = $reserve->{branchcode} ne $next_hold->{branchcode}; + + ModReserveAffect( + { + itemnumber => $reserve->{itemnumber}, + borrowernumber => $next_hold->{borrowernumber}, + is_transfer => $is_transfer, + notify_library => 1, + } + ); + + ModItemTransfer( $reserve->{itemnumber}, $reserve->{branchcode}, $next_hold->{branchcode} ) + if $is_transfer; + } + } } return $reserve; @@ -1294,7 +1323,13 @@ take care of the waiting status =cut sub ModReserveAffect { - my ( $itemnumber, $borrowernumber,$transferToDo ) = @_; + my ( $params ) = @_; + + my $itemnumber = $params->{itemnumber}; + my $borrowernumber = $params->{borrowernumber}; + my $transferToDo = $params->{is_transfer}; + my $notify_library = $params->{notify_library}; + my $dbh = C4::Context->dbh; # we want to attach $itemnumber to $borrowernumber, find the biblionumber @@ -1339,8 +1374,18 @@ sub ModReserveAffect { } $sth = $dbh->prepare($query); $sth->execute( $itemnumber, $borrowernumber,$biblionumber); - _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ) if ( !$transferToDo && !$already_on_shelf ); + + _koha_notify_reserve( + { + itemnumber => $itemnumber, + borrowernumber => $borrowernumber, + biblionumber => $biblionumber, + notify_library => $notify_library, + } + ) if ( !$transferToDo && !$already_on_shelf ); + _FixPriority( { biblionumber => $biblionumber } ); + if ( C4::Context->preference("ReturnToShelvingCart") ) { CartToShelf( $itemnumber ); } @@ -1385,7 +1430,7 @@ sub ModReserveMinusPriority { my $dbh = C4::Context->dbh; my $query = " UPDATE reserves - SET priority = 0 , itemnumber = ? + SET priority = 0 , itemnumber = ? WHERE reserve_id = ? "; my $sth_upd = $dbh->prepare($query); @@ -1600,7 +1645,7 @@ sub ToggleLowestPriority { my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?"); $sth->execute( $reserve_id ); - + _FixPriority({ reserve_id => $reserve_id, rank => '999999' }); } @@ -1784,7 +1829,7 @@ sub _FixPriority { $priority[$j]->{'reserve_id'} ); } - + $sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); $sth->execute(); @@ -1919,7 +1964,14 @@ sub _Findgroupreserve { =head2 _koha_notify_reserve - _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ); +_koha_notify_reserve( + { + itemnumber => $itemnumber, + borrowernumber => $borrowernumber, + biblionumber => $biblionumber, + notify_library => $notify_library + } +); Sends a notification to the patron that their hold has been filled (through ModReserveAffect, _not_ ModReserveFill) @@ -1946,7 +1998,12 @@ The following tables are availalbe witin the notice: =cut sub _koha_notify_reserve { - my ($itemnumber, $borrowernumber, $biblionumber) = @_; + my ( $params ) = @_; + + my $itemnumber = $params->{itemnumber}; + my $borrowernumber = $params->{borrowernumber}; + my $biblionumber = $params->{biblionumber}; + my $notify_library = $params->{notify_library}; my $dbh = C4::Context->dbh; my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); @@ -1997,12 +2054,14 @@ sub _koha_notify_reserve { return; } - C4::Letters::EnqueueLetter( { - letter => $letter, - borrowernumber => $borrowernumber, - from_address => $admin_email_address, - message_transport_type => $mtt, - } ); + C4::Letters::EnqueueLetter( + { + letter => $letter, + borrowernumber => $borrowernumber, + from_address => $admin_email_address, + message_transport_type => $mtt, + } + ); }; while ( my ( $mtt, $letter_code ) = each %{ $messagingprefs->{transports} } ) { @@ -2019,7 +2078,37 @@ sub _koha_notify_reserve { if (! $notification_sent) { &$send_notification('print', 'HOLD'); } - + + if ($notify_library) { + my $letter = C4::Letters::GetPreparedLetter( + module => 'reserves', + letter_code => 'HOLD_CHANGED', + branchcode => $reserve->{branchcode}, + substitute => { today => C4::Dates->new()->output() }, + tables => { + 'branches' => $branch_details, + 'borrowers' => $borrower, + 'biblio' => $biblionumber, + 'reserves' => $reserve, + 'items' => $reserve->{'itemnumber'}, + }, + ); + + my $email = + C4::Context->preference('ExpireReservesAutoFillEmail') + || $branch_details->{'branchemail'} + || C4::Context->preference('KohaAdminEmailAddress'); + + C4::Letters::EnqueueLetter( + { + letter => $letter, + borrowernumber => $borrowernumber, + message_transport_type => 'email', + from_address => $email, + to_address => $email, + } + ); + } } =head2 _ShiftPriorityByDateAndPriority diff --git a/C4/SIP/ILS/Transaction/Checkin.pm b/C4/SIP/ILS/Transaction/Checkin.pm index bc1c433..6cd860a 100644 --- a/C4/SIP/ILS/Transaction/Checkin.pm +++ b/C4/SIP/ILS/Transaction/Checkin.pm @@ -99,13 +99,23 @@ sub do_checkin { $self->hold($messages->{ResFound}); if ($branch eq $messages->{ResFound}->{branchcode}) { $self->alert_type('01'); - ModReserveAffect( $messages->{ResFound}->{itemnumber}, - $messages->{ResFound}->{borrowernumber}, 0); + ModReserveAffect( + { + itemnumber => $messages->{ResFound}->{itemnumber}, + borrowernumber => $messages->{ResFound}->{borrowernumber}, + is_transfer => 0, + } + ); } else { $self->alert_type('02'); - ModReserveAffect( $messages->{ResFound}->{itemnumber}, - $messages->{ResFound}->{borrowernumber}, 1); + ModReserveAffect( + { + itemnumber => $messages->{ResFound}->{itemnumber}, + borrowernumber => $messages->{ResFound}->{borrowernumber}, + is_transfer => 1, + } + ); ModItemTransfer( $messages->{ResFound}->{itemnumber}, $branch, $messages->{ResFound}->{branchcode} diff --git a/circ/branchtransfers.pl b/circ/branchtransfers.pl index a826289..d70f602 100755 --- a/circ/branchtransfers.pl +++ b/circ/branchtransfers.pl @@ -89,7 +89,7 @@ if ( $request eq "KillWaiting" ) { } elsif ( $request eq "SetWaiting" ) { my $item = $query->param('itemnumber'); - ModReserveAffect( $item, $borrowernumber ); + ModReserveAffect( { itemnumber => $item, borrowernumber => $borrowernumber } ); $ignoreRs = 1; $setwaiting = 1; $reqmessage = 1; diff --git a/circ/returns.pl b/circ/returns.pl index 2f09b80..3a8fbaf 100755 --- a/circ/returns.pl +++ b/circ/returns.pl @@ -158,9 +158,10 @@ if ( $query->param('resbarcode') ) { my $diffBranchSend = ($userenv_branch ne $diffBranchReturned) ? $diffBranchReturned : undef; # diffBranchSend tells ModReserveAffect whether document is expected in this library or not, # i.e., whether to apply waiting status - ModReserveAffect( $item, $borrowernumber, $diffBranchSend); + ModReserveAffect( { itemnumber => $item, borrowernumber => $borrowernumber, is_transfer => $diffBranchSend } ); } -# check if we have other reserves for this document, if we have a return send the message of transfer + + # check if we have other reserves for this document, if we have a return send the message of transfer my ( $messages, $nextreservinfo ) = GetOtherReserves($item); my $borr = GetMember( borrowernumber => $nextreservinfo ); diff --git a/installer/data/mysql/atomicupdate/bug_14364.sql b/installer/data/mysql/atomicupdate/bug_14364.sql new file mode 100644 index 0000000..4f3e21e --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_14364.sql @@ -0,0 +1,13 @@ +INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES +('ExpireReservesAutoFill','0',NULL,'Automatically fill the next hold with a automatically canceled expired waiting hold.','YesNo'), +('ExpireReservesAutoFillEmail','', NULL,'If ExpireReservesAutoFill and an email is defined here, the email notification for the change in the hold will be sent to this address.','Free'); + +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) +VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + +Please update the hold information for this item. + +Title: <> +Author: <> +Copy: <> +Pickup location: <>', 'email'); diff --git a/installer/data/mysql/de-DE/mandatory/sample_notices.sql b/installer/data/mysql/de-DE/mandatory/sample_notices.sql index 3ce7226..d723a54 100644 --- a/installer/data/mysql/de-DE/mandatory/sample_notices.sql +++ b/installer/data/mysql/de-DE/mandatory/sample_notices.sql @@ -147,3 +147,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Überfälligkeiten (Quittung)', '0 INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) + VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + + Please update the hold information for this item. + + Title: <> + Author: <> + Copy: <> + Pickup location: <>', 'email'); diff --git a/installer/data/mysql/en/mandatory/sample_notices.sql b/installer/data/mysql/en/mandatory/sample_notices.sql index d8f8e6b..9bbe604 100644 --- a/installer/data/mysql/en/mandatory/sample_notices.sql +++ b/installer/data/mysql/en/mandatory/sample_notices.sql @@ -166,3 +166,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) + VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + + Please update the hold information for this item. + + Title: <> + Author: <> + Copy: <> + Pickup location: <>', 'email'); diff --git a/installer/data/mysql/es-ES/mandatory/sample_notices.sql b/installer/data/mysql/es-ES/mandatory/sample_notices.sql index 68da0e7..dea0326 100644 --- a/installer/data/mysql/es-ES/mandatory/sample_notices.sql +++ b/installer/data/mysql/es-ES/mandatory/sample_notices.sql @@ -161,3 +161,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) + VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + +Please update the hold information for this item. + +Title: <> +Author: <> +Copy: <> +Pickup location: <>', 'email'); diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql b/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql index a960b74..0ab8640 100644 --- a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql +++ b/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql @@ -162,3 +162,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) + VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + +Please update the hold information for this item. + +Title: <> +Author: <> +Copy: <> +Pickup location: <>', 'email'); diff --git a/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql b/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql index 95d864c..8813291 100644 --- a/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql +++ b/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql @@ -181,3 +181,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) + VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + +Please update the hold information for this item. + +Title: <> +Author: <> +Copy: <> +Pickup location: <>', 'email'); diff --git a/installer/data/mysql/pl-PL/mandatory/sample_notices.sql b/installer/data/mysql/pl-PL/mandatory/sample_notices.sql index ae03389..6575583 100644 --- a/installer/data/mysql/pl-PL/mandatory/sample_notices.sql +++ b/installer/data/mysql/pl-PL/mandatory/sample_notices.sql @@ -159,3 +159,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) +VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + +Please update the hold information for this item. + +Title: <> +Author: <> +Copy: <> +Pickup location: <>', 'email'); diff --git a/installer/data/mysql/ru-RU/mandatory/sample_notices.sql b/installer/data/mysql/ru-RU/mandatory/sample_notices.sql index 2e2056b..327dbf7 100644 --- a/installer/data/mysql/ru-RU/mandatory/sample_notices.sql +++ b/installer/data/mysql/ru-RU/mandatory/sample_notices.sql @@ -161,3 +161,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) +VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + +Please update the hold information for this item. + +Title: <> +Author: <> +Copy: <> +Pickup location: <>', 'email'); diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index e2e3ad2..8985f48 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -138,6 +138,8 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('EnableSearchHistory','0','','Enable or disable search history','YesNo'), ('EnhancedMessagingPreferences','0','','If ON, allows patrons to select to receive additional messages about items due or nearly due.','YesNo'), ('expandedSearchOption','0',NULL,'If ON, set advanced search to be expanded by default','YesNo'), +('ExpireReservesAutoFill','0',NULL,'Automatically fill the next hold with a automatically canceled expired waiting hold.','YesNo'), +('ExpireReservesAutoFillEmail','', NULL,'If ExpireReservesAutoFill and an email is defined here, the email notification for the change in the hold will be sent to this address.','Free'), ('ExpireReservesMaxPickUpDelay','0','','Enabling this allows holds to expire automatically if they have not been picked by within the time period specified in ReservesMaxPickUpDelay','YesNo'), ('ExpireReservesMaxPickUpDelayCharge','0',NULL,'If ExpireReservesMaxPickUpDelay is enabled, and this field has a non-zero value, than a borrower whose waiting hold has expired will be charged this amount.','free'), ('ExpireReservesOnHolidays', '1', NULL, 'If false, reserves at a library will not be canceled on days the library is not open.', 'YesNo'), diff --git a/installer/data/mysql/uk-UA/mandatory/sample_notices.sql b/installer/data/mysql/uk-UA/mandatory/sample_notices.sql index a1e0bd3..db8db5c 100644 --- a/installer/data/mysql/uk-UA/mandatory/sample_notices.sql +++ b/installer/data/mysql/uk-UA/mandatory/sample_notices.sql @@ -160,3 +160,12 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','\r\n

This email has been sent in response to your password recovery request for the account <>.\r\n

\r\n

\r\nYou can now create your new password using the following link:\r\n
>\"><>\r\n

\r\n

This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.

\r\n

Thank you.

\r\n\r\n','email' ); +INSERT INTO letter(module,code,branchcode,name,is_html,title,content,message_transport_type) +VALUES ( 'reserves', 'HOLD_CHANGED', '', 'Canceled Hold Available for Different Patron', '0', 'Canceled Hold Available for Different Patron', 'The patron picking up <> (<>) has changed to <> <> (<>). + +Please update the hold information for this item. + +Title: <> +Author: <> +Copy: <> +Pickup location: <>', 'email'); 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 8cdba08..2c674f0 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 @@ -497,6 +497,16 @@ Circulation: no: "Don't allow" - "holds to expire automatically if they have not been picked by within the time period specified in ReservesMaxPickUpDelay" - + - pref: ExpireReservesAutoFill + choices: + yes: "Do" + no: "Don't" + - automatically fill the next hold using the item. If enabled, an email notification will be sent to either the email address defined in ExpireReservesAutoFillEmail, the item's holding library's email address, or the email address defined in KohaAdminEmailAddress in that order. + - + - Send email notification of the new hold filled with a canceled item to + - pref: ExpireReservesAutoFillEmail + - . If no address is defined here, the email will be sent to either the item's holding library or the email address defined in KohaAdminEmailAddress in that order. + - - If using ExpireReservesMaxPickUpDelay, charge a borrower who allows his or her waiting hold to expire a fee of - pref: ExpireReservesMaxPickUpDelayCharge class: currency diff --git a/t/db_dependent/Holds/RevertWaitingStatus.t b/t/db_dependent/Holds/RevertWaitingStatus.t index 513eb52..c76326b 100755 --- a/t/db_dependent/Holds/RevertWaitingStatus.t +++ b/t/db_dependent/Holds/RevertWaitingStatus.t @@ -81,7 +81,7 @@ foreach my $borrowernumber (@borrowernumbers) { ); } -ModReserveAffect( $itemnumber, $borrowernumbers[0] ); +ModReserveAffect( { itemnumber => $itemnumber, borrowernumber => $borrowernumbers[0] } ); C4::Circulation::AddIssue( GetMember( borrowernumber => $borrowernumbers[1] ), $item_barcode, my $datedue, my $cancelreserve = 'revert' ); diff --git a/t/db_dependent/Reserves.t b/t/db_dependent/Reserves.t index cfc6eee..96d013c 100755 --- a/t/db_dependent/Reserves.t +++ b/t/db_dependent/Reserves.t @@ -239,7 +239,7 @@ AddReserve('FPL', $requesters{'FPL'}, $bibnum2, AddReserve('CPL', $requesters{'CPL'}, $bibnum2, $bibitems, 3, $resdate, $expdate, $notes, $title, $checkitem, $found); -ModReserveAffect($itemnum_cpl, $requesters{'RPL'}, 0); +ModReserveAffect( { itemnumber => $itemnum_cpl, borrowernumber => $requesters{'RPL'}, is_transfer => 0 } ); # Now it should have different priorities. my $title_reserves = GetReservesFromBiblionumber({biblionumber => $bibnum2}); @@ -359,12 +359,12 @@ is(exists $messages->{ResFound}?1:0, 1, 'AddReturn considers future reserve with # test marking a hold as captured my $hold_notice_count = count_hold_print_messages(); -ModReserveAffect($itemnumber, $requesters{'CPL'}, 0); +ModReserveAffect( { itemnumber => $itemnumber, borrowernumber => $requesters{'CPL'}, is_transfer => 0 } ); my $new_count = count_hold_print_messages(); is($new_count, $hold_notice_count + 1, 'patron notified when item set to waiting'); # test that duplicate notices aren't generated -ModReserveAffect($itemnumber, $requesters{'CPL'}, 0); +ModReserveAffect( { itemnumber => $itemnumber, borrowernumber => $requesters{'CPL'}, is_transfer => 0 } ); $new_count = count_hold_print_messages(); is($new_count, $hold_notice_count + 1, 'patron not notified a second time (bug 11445)'); @@ -400,7 +400,7 @@ AddReserve('CPL', $requesters{'CPL'}, $bibnum, @results= GetReservesFromItemnumber($itemnumber); is(defined $results[3]?1:0, 0, 'GetReservesFromItemnumber does not return a future item level hold'); # 9788c: GetReservesFromItemnumber returns future wait (confirmed future hold) -ModReserveAffect( $itemnumber, $requesters{'CPL'} , 0); #confirm hold +ModReserveAffect( { itemnumber => $itemnumber, borrowernumber => $requesters{'CPL'}, is_transfer => 0 } ); #confirm hold @results= GetReservesFromItemnumber($itemnumber); is(defined $results[3]?1:0, 1, 'GetReservesFromItemnumber returns a future wait (confirmed future hold)'); # End of tests for bug 9788 @@ -425,7 +425,7 @@ AddReserve('CPL', $requesters{'CPL'}, $bibnum, $title, $itemnumber, $found); $p = C4::Reserves::CalculatePriority($bibnum); is($p, 2, 'CalculatePriority should now return priority 2'); -ModReserveAffect( $itemnumber, $requesters{'CPL'} , 0); +ModReserveAffect( { itemnumber => $itemnumber, borrowernumber => $requesters{'CPL'}, is_transfer => 0 } ); $p = C4::Reserves::CalculatePriority($bibnum); is($p, 1, 'CalculatePriority should now return priority 1'); #add another biblio hold, no resdate @@ -483,7 +483,7 @@ is($cancancel, 1, 'Can user cancel its own reserve'); $cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{'FPL'}); is($cancancel, 0, 'Other user cant cancel reserve'); -ModReserveAffect($itemnumber, $requesters{'CPL'}, 1); +ModReserveAffect( { itemnumber => $itemnumber, borrowernumber => $requesters{'CPL'}, is_transfer => 1 } ); $cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{'CPL'}); is($cancancel, 0, 'Reserve in transfer status cant be canceled'); @@ -493,7 +493,7 @@ AddReserve('CPL', $requesters{'CPL'}, $item_bibnum, $title, $checkitem, ''); (undef, $canres, undef) = CheckReserves($itemnumber); -ModReserveAffect($itemnumber, $requesters{'CPL'}, 0); +ModReserveAffect( { itemnumber => $itemnumber, borrowernumber => $requesters{'CPL'}, is_transfer => 0 } ); $cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{'CPL'}); is($cancancel, 0, 'Reserve in waiting status cant be canceled'); -- 2.1.4