@@ -, +, @@ holds to fill the next hold 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 --- 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 --- a/C4/Reserves.pm +++ a/C4/Reserves.pm @@ -459,7 +459,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); @@ -495,8 +495,8 @@ sub CanItemBeReserved{ LEFT JOIN borrowers USING (borrowernumber) WHERE borrowernumber = ? "; - - + + my $branchcode = ""; my $branchfield = "reserves.branchcode"; @@ -507,12 +507,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 = '*'; } @@ -520,7 +520,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 .= @@ -530,7 +530,7 @@ sub CanItemBeReserved{ if ( $ruleitemtype ne "*" ); my $sthcount = $dbh->prepare($querycount); - + if($ruleitemtype eq "*"){ $sthcount->execute($borrowernumber, $branchcode); }else{ @@ -744,8 +744,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 ); @@ -770,7 +770,7 @@ sub GetReservesForBranch { my $query = " SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate - FROM reserves + FROM reserves WHERE priority='0' AND found='W' "; @@ -1025,7 +1025,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, + } + ); } } } @@ -1050,7 +1056,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. @@ -1060,10 +1066,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; @@ -1103,6 +1112,26 @@ sub CancelReserve { if ( $charge && $params->{'charge_cancel_fee'} ) { manualinvoice($reserve->{'borrowernumber'}, $reserve->{'itemnumber'}, '', 'HE', $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; @@ -1303,7 +1332,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 @@ -1348,8 +1383,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 ); } @@ -1394,7 +1439,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); @@ -1631,7 +1676,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' }); } @@ -1815,7 +1860,7 @@ sub _FixPriority { $priority[$j]->{'reserve_id'} ); } - + $sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); $sth->execute(); @@ -1953,7 +1998,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) @@ -1980,7 +2032,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); @@ -2031,12 +2088,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} } ) { @@ -2053,7 +2112,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 --- a/C4/SIP/ILS/Transaction/Checkin.pm +++ a/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} --- a/circ/branchtransfers.pl +++ a/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; --- a/circ/returns.pl +++ a/circ/returns.pl @@ -159,9 +159,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 ); --- a/installer/data/mysql/atomicupdate/bug_14364.sql +++ a/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'); --- a/installer/data/mysql/de-DE/mandatory/sample_notices.sql +++ a/installer/data/mysql/de-DE/mandatory/sample_notices.sql @@ -154,3 +154,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','','Neues Passwort',1,'Neues Passwort','\r\n

Liebe(r) <> <> <>,

\r\n\r\n

Diese E-Mail wurde verschickt, da Sie ein neues Passwort für Ihr Bibliotheksbenutzerkonto angefordert haben: <>.\r\n

\r\n

\r\nBitte klicken Sie auf den folgenden Link um Ihr neues Passwort zu erstellen:\r\n
>\"><>\r\n

\r\n

Dieser Link ist von dieser E-Mail an für 2 Tage gültig. Wenn Sie bis dahin Ihr Passwort nicht geändert haben, müssen Sie die E-Mail erneut anfordern.

\r\n

Vielen Dank

\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'); --- a/installer/data/mysql/en/mandatory/sample_notices.sql +++ a/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'); --- a/installer/data/mysql/es-ES/mandatory/sample_notices.sql +++ a/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'); --- a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql +++ a/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'); --- a/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql +++ a/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'); --- a/installer/data/mysql/pl-PL/mandatory/sample_notices.sql +++ a/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'); --- a/installer/data/mysql/ru-RU/mandatory/sample_notices.sql +++ a/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'); --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -140,6 +140,8 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('EnhancedMessagingPreferences','0','','If ON, allows patrons to select to receive additional messages about items due or nearly due.','YesNo'), ('EnhancedMessagingPreferencesOPAC', '1', NULL, 'If ON, show patrons messaging setting on the OPAC.', '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'), --- a/installer/data/mysql/uk-UA/mandatory/sample_notices.sql +++ a/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'); --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -508,6 +508,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 --- a/t/db_dependent/Holds/RevertWaitingStatus.t +++ a/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' ); --- a/t/db_dependent/Reserves.t +++ a/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'); --