From 3b788550bb56f69252e1d4e7d0951e7df5887bbe 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 | 10 ++ .../data/mysql/en/mandatory/sample_notices.sql | 10 ++ .../data/mysql/es-ES/mandatory/sample_notices.sql | 10 ++ .../mysql/fr-FR/1-Obligatoire/sample_notices.sql | 10 ++ .../mysql/nb-NO/1-Obligatorisk/sample_notices.sql | 10 ++ .../data/mysql/pl-PL/mandatory/sample_notices.sql | 10 ++ .../data/mysql/ru-RU/mandatory/sample_notices.sql | 10 ++ installer/data/mysql/sysprefs.sql | 2 + .../data/mysql/uk-UA/mandatory/sample_notices.sql | 10 ++ .../en/modules/admin/preferences/circulation.pref | 10 ++ t/db_dependent/Holds/RevertWaitingStatus.t | 2 +- t/db_dependent/Reserves.t | 14 +- 17 files changed, 247 insertions(+), 42 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_14364.sql diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 6ed1543..cada853 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -442,7 +442,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); @@ -478,8 +478,8 @@ sub CanItemBeReserved{ LEFT JOIN borrowers USING (borrowernumber) WHERE borrowernumber = ? "; - - + + my $branchcode = ""; my $branchfield = "reserves.branchcode"; @@ -490,12 +490,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 = '*'; } @@ -503,7 +503,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 .= @@ -513,7 +513,7 @@ sub CanItemBeReserved{ if ( $ruleitemtype ne "*" ); my $sthcount = $dbh->prepare($querycount); - + if($ruleitemtype eq "*"){ $sthcount->execute($borrowernumber, $branchcode); }else{ @@ -726,8 +726,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 ); @@ -752,7 +752,7 @@ sub GetReservesForBranch { my $query = " SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate - FROM reserves + FROM reserves WHERE priority='0' AND found='W' "; @@ -1005,7 +1005,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, + } + ); } } } @@ -1032,7 +1038,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. @@ -1042,10 +1048,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; @@ -1085,6 +1094,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; @@ -1278,7 +1307,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 @@ -1323,8 +1358,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 ); } @@ -1369,7 +1414,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); @@ -1584,7 +1629,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' }); } @@ -1794,7 +1839,7 @@ sub _FixPriority { $priority[$j]->{'reserve_id'} ); } - + $sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); $sth->execute(); @@ -1929,7 +1974,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) @@ -1937,7 +1989,12 @@ ModReserveAffect, _not_ ModReserveFill) =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); @@ -1987,12 +2044,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} } ) { @@ -2009,7 +2068,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 4caca05..94ff667 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 4039c75..04107b7 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) = GetMemberDetails( $nextreservinfo, 0 ); 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 b968cff..0a17380 100644 --- a/installer/data/mysql/de-DE/mandatory/sample_notices.sql +++ b/installer/data/mysql/de-DE/mandatory/sample_notices.sql @@ -143,3 +143,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Überfälligkeiten (Quittung)', '0 "<>" von <>, <>, Barcode: <> Gebühr: <> ', 'print' ); + +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 50bee6b..ffc9eb6 100644 --- a/installer/data/mysql/en/mandatory/sample_notices.sql +++ b/installer/data/mysql/en/mandatory/sample_notices.sql @@ -162,3 +162,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI "<>" by <>, <>, Barcode: <> Fine: <> ', 'print' ); + +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 6f1d6fe..4b6af41 100644 --- a/installer/data/mysql/es-ES/mandatory/sample_notices.sql +++ b/installer/data/mysql/es-ES/mandatory/sample_notices.sql @@ -157,3 +157,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI "<>" by <>, <>, Barcode: <> Fine: <> ', 'print' ); + +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 a5d3591..dd3c86c 100644 --- a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql +++ b/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql @@ -158,3 +158,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI "<>" by <>, <>, Barcode: <> Fine: <> ', 'print' ); + +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 8a1b51d..666a287 100644 --- a/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql +++ b/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql @@ -177,3 +177,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI "<>" by <>, <>, Barcode: <> Fine: <> ', 'print' ); + +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 5fef900..4f37206 100644 --- a/installer/data/mysql/pl-PL/mandatory/sample_notices.sql +++ b/installer/data/mysql/pl-PL/mandatory/sample_notices.sql @@ -155,3 +155,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI "<>" by <>, <>, Barcode: <> Fine: <> ', 'print' ); + +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 fbd53d9..5e592e6 100644 --- a/installer/data/mysql/ru-RU/mandatory/sample_notices.sql +++ b/installer/data/mysql/ru-RU/mandatory/sample_notices.sql @@ -157,3 +157,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI "<>" by <>, <>, Barcode: <> Fine: <> ', 'print' ); + +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 484b3cd..23a18b7 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -130,6 +130,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 8b0963a..908d14d 100644 --- a/installer/data/mysql/uk-UA/mandatory/sample_notices.sql +++ b/installer/data/mysql/uk-UA/mandatory/sample_notices.sql @@ -156,3 +156,13 @@ VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI "<>" by <>, <>, Barcode: <> Fine: <> ', 'print' ); + +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 6a0954d..05a9283 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 @@ -484,6 +484,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 7301757..3208bd3 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}); @@ -355,12 +355,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)'); @@ -396,7 +396,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 @@ -421,7 +421,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 @@ -479,7 +479,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'); @@ -489,7 +489,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'); -- 1.7.10.4