From 8ab4190c5e130bbe12fc2a898b334fcebbc9874e Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Wed, 10 Jun 2020 16:18:01 -0300 Subject: [PATCH] Bug 19889: Make it possible to exclude items and categories from local holds priority This patch adds the ability to exclude patrons (by category) from local holds, and items, by editing the item itself or by batch item modification tool. To test: 1. apply patches 2. updatedatabase 3. Enable LocalHoldsPriority preference, and leave LocalHoldsPriorityPatronControl in pickup library, and LocalHoldsPriorityItemControl in holding library. 4. Search for a biblio with one item. 5. Place a hold with a patron (patron1) and set pickup location to a different library of the item's home library 6. Place another hold with another patron (patron2) and set pickup location to be the same as the item's home library 7. ./misc/cronjobs/holds/build_holds_queue.pl 8. Go to circulation -> holds queue 9. Search by the item's home library CHECK => only the hold for patron2 (with the pickup location the same as the item's home library) appears in the table 10. Go back to the biblio details page and click on "Items" tab CHECK => There is a new section in the item's details between "Statuses" and "History" called "Priority" 11. Set exclude to "Yes" and update 12. repeat steps 7 to 9 SUCCESS => only the hold for patron1 now appears, even the other hold had local hold priority 13. Repeat step 10 and 11 but this time set exclude to "No" 14. repeat steps 7 to 9 CHECK => the hold for patron2 is back 15. Edit patron2's category and set exclude from local holds priority to "Yes" 16. Repeat steps 7 to 9 SUCCESS => the hold for patron1 is back 17. Go to tools -> Batch item modification and in barcode list place several (existing) barcodes and press continue CHECK => There is a new section in the bottom called "Priority" 18. Set exclude to "Yes" and save SUCCESS => all items in the list now have exclude setted to "Yes" 19. Try to checkout the first item to a patron3 SUCCESS => Alert message appears saying that patron1 has a hold on that item 20. Click on Yes and then checkin that item SUCCESS => There is a modal window saying that a hold was found for patron1 21. prove t/db_dependent/HoldsQueue.t t/db_dependent/Holds/LocalHoldsPriority.t 22. Sign off Sponsored-by: Cooperative Information Network (CIN) Signed-off-by: Christopher Brannon Signed-off-by: Christopher Brannon --- C4/HoldsQueue.pm | 5 +++- C4/Reserves.pm | 24 ++++++++------- admin/categories.pl | 3 ++ catalogue/updateitem.pl | 3 ++ .../prog/en/modules/admin/categories.tt | 13 ++++++++ .../prog/en/modules/catalogue/moredetail.tt | 30 +++++++++++++++++-- .../prog/en/modules/tools/batchMod-edit.tt | 15 ++++++++++ tools/batchMod.pl | 2 ++ 8 files changed, 81 insertions(+), 14 deletions(-) diff --git a/C4/HoldsQueue.pm b/C4/HoldsQueue.pm index 5938d35d2a..cc3e540ef3 100755 --- a/C4/HoldsQueue.pm +++ b/C4/HoldsQueue.pm @@ -401,13 +401,16 @@ sub MapItemsToHoldRequests { foreach my $request (@$hold_requests) { last if $num_items_remaining == 0; + my $patron = Koha::Patrons->find($request->{borrowernumber}); + next if $patron->category->exclude_from_local_holds_priority; my $local_hold_match; foreach my $item (@$available_items) { next if ( !$item->{holdallowed} ) || ( $item->{holdallowed} == 1 - && $item->{homebranch} ne $request->{borrowerbranch} ); + && $item->{homebranch} ne $request->{borrowerbranch} + || $item->{_object}->exclude_from_local_holds_priority ); next if $request->{itemnumber} && $request->{itemnumber} != $item->{itemnumber}; diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 950d29f587..b0c9d64218 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -841,17 +841,19 @@ sub CheckReserves { $patron = Koha::Patrons->find( $res->{borrowernumber} ); $item = Koha::Items->find($itemnumber); - my $local_holds_priority_item_branchcode = - $item->$LocalHoldsPriorityItemControl; - my $local_holds_priority_patron_branchcode = - ( $LocalHoldsPriorityPatronControl eq 'PickupLibrary' ) - ? $res->{branchcode} - : ( $LocalHoldsPriorityPatronControl eq 'HomeLibrary' ) - ? $patron->branchcode - : undef; - $local_hold_match = - $local_holds_priority_item_branchcode eq - $local_holds_priority_patron_branchcode; + unless ($item->exclude_from_local_holds_priority || $patron->category->exclude_from_local_holds_priority) { + my $local_holds_priority_item_branchcode = + $item->$LocalHoldsPriorityItemControl; + my $local_holds_priority_patron_branchcode = + ( $LocalHoldsPriorityPatronControl eq 'PickupLibrary' ) + ? $res->{branchcode} + : ( $LocalHoldsPriorityPatronControl eq 'HomeLibrary' ) + ? $patron->branchcode + : undef; + $local_hold_match = + $local_holds_priority_item_branchcode eq + $local_holds_priority_patron_branchcode; + } } # See if this item is more important than what we've got so far diff --git a/admin/categories.pl b/admin/categories.pl index f9144e7ced..8fdc293cb4 100755 --- a/admin/categories.pl +++ b/admin/categories.pl @@ -94,6 +94,7 @@ elsif ( $op eq 'add_validate' ) { my $default_privacy = $input->param('default_privacy'); my $reset_password = $input->param('reset_password'); my $change_password = $input->param('change_password'); + my $exclude_from_local_holds_priority = $input->param('exclude_from_local_holds_priority'); my @branches = grep { $_ ne q{} } $input->multi_param('branches'); $reset_password = undef if $reset_password eq -1; @@ -129,6 +130,7 @@ elsif ( $op eq 'add_validate' ) { $category->default_privacy($default_privacy); $category->reset_password($reset_password); $category->change_password($change_password); + $category->exclude_from_local_holds_priority($exclude_from_local_holds_priority); eval { $category->store; $category->replace_branch_limitations( \@branches ); @@ -157,6 +159,7 @@ elsif ( $op eq 'add_validate' ) { default_privacy => $default_privacy, reset_password => $reset_password, change_password => $change_password, + exclude_from_local_holds_priority => $exclude_from_local_holds_priority, }); eval { $category->store; diff --git a/catalogue/updateitem.pl b/catalogue/updateitem.pl index f8295a0314..9d112166d4 100755 --- a/catalogue/updateitem.pl +++ b/catalogue/updateitem.pl @@ -40,6 +40,7 @@ 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 $confirm=$cgi->param('confirm'); my $dbh = C4::Context->dbh; @@ -71,6 +72,8 @@ elsif ( $op eq "set_public_note" ) { # i.e., itemnotes parameter passed from for $item->itemlost($itemlost); } elsif ( $op eq "set_withdrawn" && $withdrawn ne $item_data_hashref->{'withdrawn'}) { $item->withdrawn($withdrawn); +} elsif ( $op eq "set_exclude_priority" && $exclude_from_local_holds_priority ne $item_data_hashref->{'exclude_from_local_holds_priority'}) { + $item->exclude_from_local_holds_priority($exclude_from_local_holds_priority); } elsif ( $op eq "set_damaged" && $damaged ne $item_data_hashref->{'damaged'}) { $item->damaged($damaged); } else { diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt index 77146a78db..8f39dbfe82 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt @@ -297,6 +297,19 @@ Controls how long a patrons checkout history is kept for new patrons of this category. "Never" anonymizes checkouts on return, and "Forever" keeps a patron's checkout history indefinitely. When set to "Default", the amount of history kept is controlled by the cronjob batch_anonymise.pl which should be set up by your system administrator. +
  • + + + If Yes, holds placed by patrons of this category will not be given priority +
  • 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 16fb580bb1..6addae01e8 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt @@ -8,7 +8,7 @@ [% INCLUDE 'doc-head-open.inc' %] Koha › Catalog › Item details for [% INCLUDE 'biblio-title-head.inc' %] [% INCLUDE 'doc-head-close.inc' %] - + [% USE KohaDates %] @@ -44,7 +44,7 @@ [% IF ( volumeddesc ) %]
  • Volume: [% volumeddesc | html %]
  • [% END %]
  • Physical details: [% pages | html %] [% illus | html %] [% size | html %] 
  • [% IF ( bnotes ) %]
  • Notes: [% bnotes | html %]
  • [% END %] -
  • No. of items: [% count | html %] [% IF ( hiddencount ) %]total ([% showncount | html %] shown / [% hiddencount | html %] hidden) +
  • No. of items: [% count | html %] [% IF ( hiddencount ) %]total ([% showncount | html %] shown / [% hiddencount | html %] hidden) Show all items[% END %]
  • @@ -216,6 +216,32 @@ [% END %] + +

    Priority

    +
    +
      +
    1. + Exclude from local holds priority: +
      + + + + + +
      +
    2. +
    +
    +
    +

    History

      diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchMod-edit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchMod-edit.tt index 283ef381ef..863a3a23fd 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchMod-edit.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchMod-edit.tt @@ -335,6 +335,21 @@ $(document).ready(function(){ [% END %]
    +
    + Priority +
      +
    1. +
      + + +
      +
    2. +
    +
    Job progress:
    0%
    diff --git a/tools/batchMod.pl b/tools/batchMod.pl index fe40f84c7e..672d1d5ded 100755 --- a/tools/batchMod.pl +++ b/tools/batchMod.pl @@ -57,6 +57,7 @@ my $completedJobID = $input->param('completedJobID'); my $runinbackground = $input->param('runinbackground'); my $src = $input->param('src'); my $use_default_values = $input->param('use_default_values'); +my $exclude_from_local_holds_priority = $input->param('exclude_from_local_holds_priority'); my $template_name; my $template_flag; @@ -230,6 +231,7 @@ if ($op eq "action") { } } else { + $item->exclude_from_local_holds_priority($exclude_from_local_holds_priority)->store if defined $exclude_from_local_holds_priority; if ( $values_to_modify || $values_to_blank ) { my $localmarcitem = Item2Marc($itemdata); my $modified = 0; -- 2.25.0