From 41988817f14ba1f9043f08bc58f8a93629259d5f Mon Sep 17 00:00:00 2001 From: Aleisha Amohia Date: Thu, 26 Mar 2020 14:33:04 +0000 Subject: [PATCH] Bug 20844: Revert or cancel lost holds This patch introduces the RevertLostBibLevelHolds syspref. When an item is marked as lost, if there is a bib-level hold on it waiting, the hold is reverted. If there is an item-level hold on it waiting, there is an alert box asking if the library would like to revert the hold or cancel it. Test: 1) Update database and restart memcached/plack 2) Place a hold on Biblio A 3) Check in Item A from Biblio A and set the hold as waiting 4) Edit Item A and give it a lost status (952$1, you may need to edit your MARC frameworks to have this visible in the Editor) 5) Look at your hold. Notice it is still waiting. 6) Go to Administration -> System preferences. Find the RevertLostBibLevelHolds system preference and enable it. 7) Cancel your hold and remove Item A's lost status. Place another biblio-level hold on the same biblio 8) Check in Item A from Biblio A and set the hold as waiting 9) Go to the Items tab for Biblio A (catalogue/moredetail.pl) 10) Edit Item A and give it a lost status 11) Once the page reloads, go to view your hold. It should no longer be waiting and have no item allocated. 12) Cancel your hold and remove Item A's lost status. Place an item-level hold on Item A 13) Check in Item A and set the hold as waiting 14) Go to the catalogue detail page for Biblio A (catalogue/detail.pl) and click 'Edit' for Item A (end up on cataloguing/additem.pl) 15) Give Item A a lost status and save changes 16) Once the page reloads, confirm there is an alert box asking you to revert or cancel the hold. Click Revert 17) Confirm your hold is no longer waiting, but the item is still allocated 18) Remove Item A's lost status 19) Check in Item A and set the hold as waiting 20) Go to the catalogue detail page for Biblio A (catalogue/detail.pl) and click 'Edit' for Item A (end up on cataloguing/additem.pl) 21) Give Item A a lost status and save changes 22) Once the page reloads, confirm there is an alert box asking you to revert or cancel the hold. Click Cancel 23) Confirm the hold is now cancelled 24) Remove Item A's lost status 25) Place an item-level hold on Item A 26) Check in Item A and set the hold as waiting 27) Go to the Items tab for Biblio A (catalogue/moredetail.pl) 28) Give Item A a lost status and save changes 29) Once the page reloads, confirm there is an alert box asking you to revert or cancel the hold. Click Revert 30) Confirm your hold is no longer waiting, but the item is still allocated 31) Remove Item A's lost status 32) Check in Item A and set the hold as waiting 33) Go to the Items tab for Biblio A (catalogue/moredetail.pl) 34) Give Item A a lost status and save changes 35) Once the page reloads, confirm there is an alert box asking you to revert or cancel the hold. Click Cancel 36) Confirm the hold is now cancelled 37) Remove Item A's lost status 38) Place an item-level hold on Item A. Check in Item A and set the hold as waiting 39) Place an item-level hold on Item B (same biblio) for another borrower. Check in Item B and set the hold as waiting. 40) Give both Items A and B lost statuses. 41) Confirm that both Items are included in the alert box on page when editing items (cataloguing/additem.pl) 42) Confirm that both Items have individual alert boxes on the Items tab (catalogue/moredetail.pl) 43) Confirm tests pass t/db_dependent/Reserves.t Test SendLostHoldNotices Test: 1) Update database and restart memcached 2) Enable the SendLostHoldNotices system preference 3) Place a hold on an item 4) Check in the item and set the hold to waiting 5) Go to edit the item and set an item lost status 6) Check the borrower's notices and confirm the notice has been enqueued 7) Confirm the notice is not sent twice when reverting or cancelling the hold 8) Confirm notice enqueues as expected for a bib-level hold Test with transferred holds To test: 1) Change branch to Branch B 2) Place a biblio-level hold at Branch B 3) Change branch to Branch A 4) Check in item at Branch A and set waiting and trigger transfer 5) Go to edit item and set item as lost 6) Check borrower's notices tab and confirm the lost_waiting_hold notice was enqueued 7) Follow test plan again with item-level hold Sponsored-by: Catalyst IT --- C4/Circulation.pm | 36 ++++ catalogue/moredetail.pl | 5 + catalogue/updateitem.pl | 35 ++-- cataloguing/additem.pl | 13 ++ ...ug_20844-add_LOST_WAITING_HOLD_notice.perl | 6 + ...4-add_RevertLostBibLevelHolds_syspref.perl | 6 + ...20844-add_SendLostHoldNotices_syspref.perl | 6 + .../mysql/en/mandatory/sample_notices.yml | 19 +++ installer/data/mysql/mandatory/sysprefs.sql | 2 + .../admin/preferences/circulation.pref | 12 ++ .../prog/en/modules/catalogue/moredetail.tt | 12 ++ .../prog/en/modules/cataloguing/additem.tt | 19 +++ t/db_dependent/Reserves.t | 157 +++++++++++++++++- 13 files changed, 317 insertions(+), 11 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_20844-add_LOST_WAITING_HOLD_notice.perl create mode 100644 installer/data/mysql/atomicupdate/bug_20844-add_RevertLostBibLevelHolds_syspref.perl create mode 100644 installer/data/mysql/atomicupdate/bug_20844-add_SendLostHoldNotices_syspref.perl diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 70ccd7fb54d..2168f9f8763 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -4222,6 +4222,42 @@ sub LostItem{ while (my $transfer = $transfers->next) { $transfer->cancel({ reason => 'ItemLost', force => 1 }); } + + # RevertLostBibLevelHolds + my $hold = Koha::Holds->find( { itemnumber => $itemnumber, found => { '!=' => undef } } ); + if ( C4::Context->preference('RevertLostBibLevelHolds') && defined $hold ) { + + # syspref is enabled and there is a waiting hold for this item + if ( $hold->item_level_hold && defined $params->{cancel_reserve} ) { + if ( $params->{cancel_reserve} ) { + + # cancel item-level hold + $hold->cancel; + } else { # eq 'revert' + # revert item-level hold's waiting status + $hold = C4::Reserves::RevertWaitingStatus( { itemnumber => $itemnumber } ); + } + } + if ( !$hold->item_level_hold ) { + + # revert biblio-level hold's waiting status + $hold = C4::Reserves::RevertWaitingStatus( { itemnumber => $itemnumber } ); + } + } + + # SendLostHoldNotices + if ( C4::Context->preference('SendLostHoldNotices') && defined $hold && $item->itemlost ) { + my $letter = C4::Letters::GetPreparedLetter( + module => 'reserves', + letter_code => 'LOST_WAITING_HOLD', + branchcode => $hold->branchcode, + tables => { + borrowers => $hold->borrowernumber, + branches => $hold->branchcode, + }, + ); + C4::Message->enqueue( $letter, $hold->borrower, 'email' ); + } } sub GetOfflineOperations { diff --git a/catalogue/moredetail.pl b/catalogue/moredetail.pl index 5e122011efb..0db48af0715 100755 --- a/catalogue/moredetail.pl +++ b/catalogue/moredetail.pl @@ -249,6 +249,11 @@ foreach my $item (@items){ $item_info->{nomod} = !$patron->can_edit_items_from( $item->homebranch ); + if ( C4::Context->preference('RevertLostBibLevelHolds') ) { + $item_info->{waiting_holds} = + $item->holds( { found => [ 'W', 'T' ], item_level_hold => { '!=' => 0 } } )->count; + } + push @item_data, $item_info; } diff --git a/catalogue/updateitem.pl b/catalogue/updateitem.pl index 5b092763dfa..e99b7550bc0 100755 --- a/catalogue/updateitem.pl +++ b/catalogue/updateitem.pl @@ -29,17 +29,32 @@ my $cgi= CGI->new; checkauth($cgi, 0, {circulate => 'circulate_remaining_permissions'}, 'intranet'); -my $op = $cgi->param('op') || ""; -my $biblionumber=$cgi->param('biblionumber'); -my $itemnumber=$cgi->param('itemnumber'); -my $biblioitemnumber=$cgi->param('biblioitemnumber'); -my $itemlost=$cgi->param('itemlost'); -my $itemnotes=$cgi->param('itemnotes'); -my $itemnotes_nonpublic=$cgi->param('itemnotes_nonpublic'); -my $withdrawn=$cgi->param('withdrawn'); -my $damaged=$cgi->param('damaged'); +my $op = $cgi->param('op') || ""; +my $biblionumber = $cgi->param('biblionumber'); +my $itemnumber = $cgi->param('itemnumber'); +my $biblioitemnumber = $cgi->param('biblioitemnumber'); +my $itemlost = $cgi->param('itemlost'); +my $itemnotes = $cgi->param('itemnotes'); +my $itemnotes_nonpublic = $cgi->param('itemnotes_nonpublic'); +my $withdrawn = $cgi->param('withdrawn'); +my $damaged = $cgi->param('damaged'); my $exclude_from_local_holds_priority = $cgi->param('exclude_from_local_holds_priority'); -my $bookable = $cgi->param('bookable'); +my $bookable = $cgi->param('bookable'); +my $cancelhold = $cgi->param('cancelhold'); +my $reverthold = $cgi->param('reverthold'); +my $redirecturl = $cgi->param('redirecturl'); + +if ( defined $cancelhold ) { + LostItem( $itemnumber, 'moredetail', 0, { cancel_reserve => $cancelhold } ); +} elsif ( defined $reverthold ) { + $cancelhold = 0; + LostItem( $itemnumber, 'moredetail', 0, { cancel_reserve => $cancelhold } ); +} else { + $cancelhold = undef; +} +if ( defined $redirecturl ) { + print $cgi->redirect( $redirecturl . $biblionumber ); +} my $confirm=$cgi->param('confirm'); my $dbh = C4::Context->dbh; diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl index 3d361ec1e63..4e6dacb0449 100755 --- a/cataloguing/additem.pl +++ b/cataloguing/additem.pl @@ -796,6 +796,19 @@ my @ig = Koha::Biblio::ItemGroups->search( { biblio_id => $biblionumber } )->as_ #sort by display order my @sorted_ig = sort { $a->display_order <=> $b->display_order } @ig; +if ( C4::Context->preference('RevertLostBibLevelHolds') ) { + my @lostitems = Koha::Items->search( { biblionumber => $biblionumber, itemlost => { '!=' => 0 } } )->as_list; + + # find if any of these lost items have waiting holds + my @waitinglostitems; + foreach my $lostitem (@lostitems) { + if ( $lostitem->holds( { found => [ 'W', 'T' ], item_level_hold => 1 } )->count > 0 ) { + push( @waitinglostitems, $lostitem ); + } + } + $template->param( waitinglostitems => \@waitinglostitems ); +} + # what's the next op ? it's what we are not in : an add if we're editing, otherwise, and edit. $template->param( biblio => $biblio, diff --git a/installer/data/mysql/atomicupdate/bug_20844-add_LOST_WAITING_HOLD_notice.perl b/installer/data/mysql/atomicupdate/bug_20844-add_LOST_WAITING_HOLD_notice.perl new file mode 100644 index 00000000000..4dc14f9606f --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_20844-add_LOST_WAITING_HOLD_notice.perl @@ -0,0 +1,6 @@ +$DBversion = 'XXX'; +if( CheckVersion( $DBversion ) ) { + $dbh->do(q{INSERT IGNORE INTO letter (module, code, branchcode, name, is_html, title, message_transport_type, content) VALUES ('reserves','LOST_WAITING_HOLD','','Waiting hold marked lost','0','Your waiting hold has been marked lost','email',"Dear [% borrower.firstname %] [% borrowers.surname %],

Your hold awaiting pickup is no longer available. The item is lost.

Please contact the library for more information.

Thank you,

[% branch.branchname %]") }); + + NewVersion( $DBversion, 20844, "Add LOST_WAITING_HOLD notice"); +} diff --git a/installer/data/mysql/atomicupdate/bug_20844-add_RevertLostBibLevelHolds_syspref.perl b/installer/data/mysql/atomicupdate/bug_20844-add_RevertLostBibLevelHolds_syspref.perl new file mode 100644 index 00000000000..93b91b018f1 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_20844-add_RevertLostBibLevelHolds_syspref.perl @@ -0,0 +1,6 @@ +$DBversion = 'XXX'; +if( CheckVersion( $DBversion ) ) { + $dbh->do(q{INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type) VALUES ('RevertLostBibLevelHolds', '0', NULL, 'If an item is marked as lost after being allocated for a biblio-level hold, revert the hold from its waiting status', 'YesNo') }); + + NewVersion( $DBversion, 20844, "Add RevertLostBibLevelHolds system preference"); +} diff --git a/installer/data/mysql/atomicupdate/bug_20844-add_SendLostHoldNotices_syspref.perl b/installer/data/mysql/atomicupdate/bug_20844-add_SendLostHoldNotices_syspref.perl new file mode 100644 index 00000000000..46b5f69da47 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_20844-add_SendLostHoldNotices_syspref.perl @@ -0,0 +1,6 @@ +$DBversion = 'XXX'; +if( CheckVersion( $DBversion ) ) { + $dbh->do(q{INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type) VALUES ('SendLostHoldNotices', '0', NULL, 'Send a notice to a borrower if their reserved and waiting item is marked as lost', 'YesNo') }); + + NewVersion( $DBversion, 20844, "Add SendLostHoldNotices system preference"); +} diff --git a/installer/data/mysql/en/mandatory/sample_notices.yml b/installer/data/mysql/en/mandatory/sample_notices.yml index 7e63d16241f..ac17a017739 100644 --- a/installer/data/mysql/en/mandatory/sample_notices.yml +++ b/installer/data/mysql/en/mandatory/sample_notices.yml @@ -2512,3 +2512,22 @@ tables: - "Your hold on [% hold.biblio.title %] ([% hold.biblio.id %]) has been confirmed." - "You will be notified by the library when your item is available for pickup." - "Thank you!" + + - module: reserves + code: LOST_WAITING_HOLD + branchcode: "" + name: "Waiting hold marked lost" + is_html: 0 + title: "Your waiting hold has been marked lost" + message_transport_type: email + lang: default + content: + - "Dear [% borrower.firstname %] [% borrowers.surname %]," + - "" + - "Your hold awaiting pickup is no longer available. The item is lost." + - "" + - "Please contact the library for more information." + - "" + - "Thank you," + - "" + - "[% branch.branchname %]" diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql index 1a7cd033e90..2dc7cb0b27d 100644 --- a/installer/data/mysql/mandatory/sysprefs.sql +++ b/installer/data/mysql/mandatory/sysprefs.sql @@ -677,6 +677,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('ReturnBeforeExpiry','0',NULL,'If ON, checkout will be prevented if returndate is after patron card expiry','YesNo'), ('ReturnLog','1',NULL,'If ON, enables the circulation (returns) log','YesNo'), ('ReturnpathDefault','',NULL,'Use this email address as return path or bounce address for undeliverable emails','Free'), +('RevertLostBibLevelHolds', '0', NULL, 'If an item is marked as lost after being allocated for a biblio-level hold, revert the hold from its waiting status', 'YesNo'), ('RisExportAdditionalFields', '', NULL , 'Define additional RIS tags to export from MARC records in YAML format as an associative array with either a marc tag/subfield combination as the value, or a list of tag/subfield combinations.', 'textarea'), ('RoundFinesAtPayment','0', NULL,'If enabled any fines with fractions of a cent will be rounded to the nearest cent when payments are coll ected. e.g. 1.004 will be paid off by a 1.00 payment','YesNo'), ('RoutingListAddReserves','0','','If ON the patrons on routing lists are automatically added to holds on the issue.','YesNo'), @@ -702,6 +703,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('SelfCheckReceiptPrompt','1','NULL','If ON, print receipt dialog pops up when self checkout is finished','YesNo'), ('SelfCheckTimeout','120','','Define the number of seconds before the Web-based Self Checkout times out a patron','Integer'), ('SendAllEmailsTo','',NULL,'All emails will be redirected to this email if it is not empty','free'), +('SendLostHoldNotices', '0', NULL, 'Send a notice to a borrower if their reserved and waiting item is marked as lost', 'YesNo'), ('SeparateHoldings','0',NULL,'Separate current branch holdings from other holdings','YesNo'), ('SeparateHoldingsBranch','homebranch','homebranch|holdingbranch','Branch used to separate holdings','Choice'), ('SerialsDefaultEmailAddress', '', NULL, 'Default email address used as reply-to for notices sent by the serials module.', 'Free'), 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 76983576a6a..63cbf98397d 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 @@ -745,6 +745,18 @@ Circulation: - pref: HoldRatioDefault class: integer - "." + - + - pref: RevertLostBibLevelHolds + choices: + 1: Revert + 0: "Don't revert" + - waiting status of a hold if the allocated item is marked as Lost. + - + - pref: SendLostHoldNotices + choices: + yes: Send + no: "Don't send" + - a notice to a borrower if their reserved and waiting item is marked as Lost. - - In the staff interface, split the holds queue into separate tables by - pref: HoldsSplitQueue diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt index 6ef020cecbd..e28b04d88f6 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt @@ -119,6 +119,18 @@ Barcode [% ITEM_DAT.barcode | html %] [% IF not_for_loan %][% not_for_loan_description | html %] [% END %] + [% IF ITEM_DAT.itemlost and ITEM_DAT.waiting_holds > 0 %] +
+ This item has a waiting item-level hold on it, and has been marked as lost.
+
+ + + + +
+
+ [% END %] +

Item information [% UNLESS ( ITEM_DAT.nomod ) %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt index 57e8b731735..7f64c07defe 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt @@ -87,6 +87,25 @@ [% IF last_item_for_hold %]
Cannot delete: Last item for bibliographic record with biblio-level hold on it.
[% END %] [% IF item_not_found %]
Cannot delete: Item not found.
[% END %] +[% IF waitinglostitems %] +
+ The following item(s) have a waiting item-level hold and have been marked as lost. +
    + [% FOREACH i IN waitinglostitems %] +
    +
  • Item ([% i.barcode | html %]) +
    + + + + +
  • + + [% END %] +
+
+[% END %] +
[% IF items %] [% SET date_fields = [ 'dateaccessioned', 'onloan', 'datelastseen', 'datelastborrowed', 'replacementpricedate' ] %] diff --git a/t/db_dependent/Reserves.t b/t/db_dependent/Reserves.t index 14fb88d5cbf..4075c369064 100755 --- a/t/db_dependent/Reserves.t +++ b/t/db_dependent/Reserves.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 77; +use Test::More tests => 78; use Test::MockModule; use Test::Warn; @@ -1419,6 +1419,161 @@ subtest 'ModReserveAffect logging' => sub { like( $log->info, qr{$expected}, 'Timestamp logged is the current one' ); }; +subtest 'Waiting item is marked as lost' => sub { + + plan tests => 17; + + # Set up data + my $biblio = $builder->build_sample_biblio(); + my $item = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } ); + my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); + t::lib::Mocks::mock_preference( 'SendLostHoldNotices', 0 ); + my $original_notice_count = Koha::Notice::Messages->search( { letter_code => "LOST_WAITING_HOLD" } )->count; + ## TEST 1: BIBLIO-LEVEL HOLD + + # place biblio-level hold + my $reserve_id = AddReserve( + { + branchcode => $item->homebranch, + borrowernumber => $patron->borrowernumber, + biblionumber => $biblio->biblionumber, + } + ); + my $hold = Koha::Holds->find($reserve_id); + + $dbh->do( + q{INSERT IGNORE INTO letter (module, code, branchcode, name, is_html, title, message_transport_type, content) VALUES ('reserves','LOST_WAITING_HOLD','','Waiting hold marked lost','0','Your waiting hold has been marked lost','email',"Dear [% borrower.firstname %] [% borrowers.surname %],

Your hold awaiting pickup is no longer available. The item is lost.

Please contact the library for more information.

Thank you,

[% branch.branchname %]") } + ); + + is( $hold->item_level_hold, 0, 'Biblio-level hold placed' ); + + # set hold as waiting and assign item + $hold->set( { itemnumber => $item->itemnumber } )->store; + $hold->set_waiting; + + # mark item in biblio as lost + $item->itemlost(1)->store; + is( $item->itemlost, 1, 'Item assigned to waiting hold has been marked lost' ); + + # do test + t::lib::Mocks::mock_preference( 'RevertLostBibLevelHolds', 0 ); + C4::Circulation::LostItem( $item->itemnumber, 'test', 0, { cancel_reserve => 0 } ); + is( + $hold->found, 'W', + 'Hold is still waiting even though the item is lost because RevertLostBibLevelHolds is disabled' + ); + + # enable preference + t::lib::Mocks::mock_preference( 'RevertLostBibLevelHolds', 1 ); + + # try again + is( $item->itemlost, 1, 'Item assigned to waiting hold has been marked lost' ); + C4::Circulation::LostItem( $item->itemnumber, 'test', 0, { cancel_reserve => 0 } ); + $hold = Koha::Holds->find($reserve_id); + is( $hold->found, undef, 'Hold waiting status has been reverted because RevertLostBibLevelHolds is enabled' ); + + # clean up + $hold->cancel; + $item->itemlost(0); + + ## TEST 2: ITEM-LEVEL HOLD, REVERT + + # place item-level hold + $reserve_id = AddReserve( + { + branchcode => $item->homebranch, + borrowernumber => $patron->borrowernumber, + biblionumber => $biblio->biblionumber, + itemnumber => $item->itemnumber + } + ); + $hold = Koha::Holds->find($reserve_id); + + is( $hold->item_level_hold, 1, 'Item-level hold placed' ); + + # set hold as waiting and assign item + $hold->set_waiting; + $hold->set( { itemnumber => $item->itemnumber, priority => 0 } )->store; + + # mark item in biblio as lost + $item->itemlost(1); + is( $item->itemlost, 1, 'Item assigned to waiting hold has been marked lost' ); + + # do test + t::lib::Mocks::mock_preference( 'RevertLostBibLevelHolds', 0 ); + C4::Circulation::LostItem( $item->itemnumber, 'test', 0, { cancel_reserve => 0 } ); + is( + $hold->found, 'W', + 'Hold is still waiting even though the item is lost because RevertLostBibLevelHolds is disabled' + ); + + # enable preference + t::lib::Mocks::mock_preference( 'RevertLostBibLevelHolds', 1 ); + + # try again + is( $item->itemlost, 1, 'Item assigned to waiting hold has been marked lost' ); + C4::Circulation::LostItem( $item->itemnumber, 'test', 0, { cancel_reserve => 0 } ); + $hold = Koha::Holds->find($reserve_id); + is( + $hold->found, undef, + 'Hold waiting status has been reverted because RevertLostBibLevelHolds is enabled, and we chose not to cancel' + ); + + # clean up + $hold->cancel; + $item->itemlost(0); + + my $current_notice_count = Koha::Notice::Messages->search( { letter_code => "LOST_WAITING_HOLD" } )->count; + is( $current_notice_count, $original_notice_count, 'No notices enqueued because SendLostHoldNotices disabled' ); + + # TEST 3: ITEM-LEVEL HOLD, CANCEL + t::lib::Mocks::mock_preference( 'SendLostHoldNotices', 1 ); + + # place item-level hold + $reserve_id = AddReserve( + { + branchcode => $item->homebranch, + borrowernumber => $patron->borrowernumber, + biblionumber => $biblio->biblionumber, + itemnumber => $item->itemnumber + } + ); + $hold = Koha::Holds->find($reserve_id); + + is( $hold->item_level_hold, 1, 'Item-level hold placed' ); + + # set hold as waiting and assign item + $hold->set_waiting; + $hold->set( { itemnumber => $item->itemnumber, priority => 0 } )->store; + + # mark item in biblio as lost + $item->itemlost(1); + is( $item->itemlost, 1, 'Item assigned to waiting hold has been marked lost' ); + + # do test + t::lib::Mocks::mock_preference( 'RevertLostBibLevelHolds', 0 ); + C4::Circulation::LostItem( $item->itemnumber, 'test', 0, { cancel_reserve => 1 } ); + is( + $hold->found, 'W', + 'Hold is still waiting even though the item is lost because RevertLostBibLevelHolds is disabled' + ); + + # enable preference + t::lib::Mocks::mock_preference( 'RevertLostBibLevelHolds', 1 ); + + # try again + is( $item->itemlost, 1, 'Item assigned to waiting hold has been marked lost' ); + C4::Circulation::LostItem( $item->itemnumber, 'test', 0, { cancel_reserve => 1 } ); + $hold = Koha::Holds->find($reserve_id); + is( Koha::Holds->find($reserve_id), undef, 'Hold has been cancelled with RevertLostBibLevelHolds enabled' ); + + $current_notice_count = Koha::Notice::Messages->search( { letter_code => "LOST_WAITING_HOLD" } )->count; + is( + $current_notice_count, $original_notice_count + 2, + 'LOST_WAITING_HOLD notice enqueued with each call to LostItem' + ); +}; + sub count_hold_print_messages { my $message_count = $dbh->selectall_arrayref(q{ SELECT COUNT(*) -- 2.39.2