From bcf9b259c5fcc1a52772efc82d4c8eec24fcf3c9 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 Signed-off-by: Nick Clemens Signed-off-by: Jonathan Druart --- 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 f1929a6c17..8d7dcbc611 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -843,17 +843,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 77f8db112f..b1f7a06c86 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 aea8dc0a16..7696a544b6 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 5bde4c7ccd..d605368d7f 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 975f7997c5..2a499796e5 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; @@ -231,6 +232,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.39.5