LP#1902937: WIP - allow adjacent-copy capture during stalling user/miker/lp-1902937-adjacent-hold-capture-when-stalling
authorMike Rylander <mrylander@gmail.com>
Tue, 10 Nov 2020 18:14:14 +0000 (13:14 -0500)
committerMike Rylander <mrylander@gmail.com>
Tue, 10 Nov 2020 18:14:14 +0000 (13:14 -0500)
Currently, setting a stalling interval disable all opportunistic capture
except at the pickup library.  It would be helpful to allow, optionally,
a mode where holds that target a copy physically adjacent to the copy
that staff pull from the shelf to fill the hold, all else being equal.
This commit does that by:

1) confirming that hold stalling and the a new setting are both in use
2) gathering shelf-adjacent copies that are available
3) gathering holds that directly target those adjacent copies
4) filtering those hold to only those that the copy in hand could fill
5) adding that filtered list to the end of the $old_holds list for
   last-resort capture testing
6) avoiding retargetting of adjacent-copy-targetted holds, they can
   still capture

TODO: be more flexible for criteria?

Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm

index 25f2633..6fe6525 100644 (file)
@@ -3165,6 +3165,42 @@ sub find_nearest_permitted_hold {
         "open-ils.storage.action.hold_request.nearest_hold.atomic", 
         $user->ws_ou, $copy, 100, $hold_stall_interval, $fifo );
 
+    if ($hold_stall_interval) {
+        my $adjacent_target_while_stalling = $U->ou_ancestor_setting_value(
+            $user->ws_ou, 'circ.holds.adjacent_target_while_stalling'
+        );
+
+        if ($adjacent_target_while_stalling) {
+            my $my_cns = $editor->search_asset_call_number({
+                record  => $copy->call_number->record,
+                deleted => 'f'
+            });
+
+            my $other_copies = $editor->search_asset_copy({
+                call_number => [map {$_->id} @$my_cns],
+                circ_lib    => $copy->circ_lib,
+                deleted     => 'f',
+                status      => 0,
+                id          => { '<>' => $copy->id }
+            });
+
+            my $other_holds = $editor->search_action_hold_request({
+                current_copy => [ map {$_->id} @$other_copies],
+                cancel_time  => undef,
+                capture_time => undef
+            });
+
+            my $adjacent_hold_maps = $editor->search_action_hold_copy_map({
+                hold => [map {$_->id} @$other_holds],
+                target_copy => $copy->id
+            });
+
+            for my $other_hold (@$other_holds) {
+                push(@$old_holds, $other_hold) if ( grep { $other_hold->id == $_->hold } @$adjacent_hold_maps );
+            }
+        }
+    }
+
     # Add any pre-targeted holds to the list too? Unless they are already there, anyway.
     if ($old_holds) {
         for my $holdid (@$old_holds) {
@@ -3243,6 +3279,7 @@ sub find_nearest_permitted_hold {
     # re-target any other holds that already target this copy
     for my $old_hold (@$old_holds) {
         next if $old_hold->id eq $best_hold->id; # don't re-target the hold we want
+        next unless $old_hold->current_copy eq $copy->id; # don't re-target adjacent-copy holds
         $logger->info("circulator: clearing current_copy and prev_check_time on hold ".
             $old_hold->id." after a better hold [".$best_hold->id."] was found");
         $old_hold->clear_current_copy;