From 7c80d398863513bb43e5fab05276df0d924e4fdc Mon Sep 17 00:00:00 2001 From: Mike Rylander Date: Mon, 28 Jun 2021 15:06:26 -0400 Subject: [PATCH] LP#1895052: Avoid foreign targets when local items exist This commit adds a new YAOUS that allows a pickup library to specify that it does not want its holds to have foreign (prox > 0) copies directly targeted if there is a local copy in an available status (on the shelf). The setting is an interval, and after the age of the hold has passed that interval, foreign direct targetting is allowed. This does not change the calculation of the potential list, so op-capture will be availalbe (all else being equal) without retargetting. This setting (circ.pickup_hold_stalling.hard) is meant to be used in concert with the other new setting in the parent commit (circ.pickup_hold_stalling.soft), and should generally have a value the same or smaller than the soft setting. Doing this allows tiered targetting, where no remote items are targeted via the hard setting for, say, 3 days, where all capture is restricted to only the pickup, and then, with a soft setting of 5 days, the next 2 days allow only direct target capture of foreign copies. After 5 days, normal, global targetting and op-capture resumes. An alternative use for this setting is to ignore the parent-commit soft setting and allow op-capture everywhere, but only direct targetting at the pickup library. The effect of this, if used globally throughout an entire Evergreen instance, would be that the pull list would only represent pickup-local holds, but serendipitous scans of items that could fill remote holds could capture for transit. Signed-off-by: Mike Rylander --- .../src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm | 54 ++++++++++++++++++++++ Open-ILS/src/sql/Pg/950.data.seed-values.sql | 9 ++++ .../sql/Pg/upgrade/XXXX.data.stalling-YAOUS.sql | 10 ++++ 3 files changed, 73 insertions(+) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm index 56e9c841a8..e5c619829e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm @@ -298,6 +298,30 @@ sub hold { return $self->{hold}; } +sub inside_hard_stall_interval { + my ($self) = @_; + if (defined $self->{inside_hard_stall_interval}) { + return $self->{inside_hard_stall_interval}; + } + + my $hard_stall_interval = + $self->parent->get_ou_setting( + $self->hold->pickup_lib, 'circ.pickup_hold_stalling.hard', $self->editor) || '0 seconds'; + + my $hold_request_time = $dt_parser->parse_datetime(clean_ISO8601($self->hold->request_time)); + my $hard_stall_time = $hold_request_time->clone->add( + seconds => OpenILS::Utils::DateTime->interval_to_seconds($hard_stall_interval) + ); + + if (DateTime->compare($hold_request_time, $hard_stall_time) < 0) { + $self->{inside_hard_stall_interval} = 1 + } else { + $self->{inside_hard_stall_interval} = 0 + } + + return $self->{inside_hard_stall_interval}; +} + # Debug message sub message { my ($self, $message) = @_; @@ -355,6 +379,12 @@ sub recall_copies { return $self->{recall_copies}; } +sub in_use_copies { + my ($self, $in_use_copies) = @_; + $self->{in_use_copies} = $in_use_copies if $in_use_copies; + return $self->{in_use_copies}; +} + # Maps copy ID's to their hold proximity sub copy_prox_map { my ($self, $copy_prox_map) = @_; @@ -720,6 +750,7 @@ sub compile_weighted_proximity_map { my %prox_map; for my $copy_hash (@{$self->copies}) { my $prox = $copy_prox_map{$copy_hash->{id}}; + $copy_hash->{proximity} = $prox; $prox_map{$prox} ||= []; my $weight = $self->parent->get_ou_setting( @@ -806,6 +837,10 @@ sub filter_copies_by_status { sub filter_copies_in_use { my $self = shift; + # Copies that are targeted, but could contribute to pickup lib + # hard (foreign) stalling. These are Available-status copies. + $self->in_use_copies([grep {$_->{current_copy}} @{$self->copies}]); + # A copy with a 'current_copy' value means it's in use by another hold. $self->copies([ grep {!$_->{current_copy}} @{$self->copies} @@ -1102,6 +1137,14 @@ sub find_nearest_copy { my $hold = $self->hold; my %seen; + # See if there are in-use (targeted) copies "here". + my $have_local_copies = 0; + if ($self->inside_hard_stall_interval) { # But only if we're inside the hard age. + if (grep { $_->{proximity} <= 0 } @{$self->in_use_copies}) { + $have_local_copies = 1; + } + } + # Pick a copy at random from each tier of the proximity map, # starting at the lowest proximity and working up, until a # copy is found that is suitable for targeting. @@ -1109,6 +1152,17 @@ sub find_nearest_copy { my @copies = @{$prox_map{$prox}}; next unless @copies; + $have_local_copies = 1 if ($prox <= 0); + + if ($prox > 0 and $have_local_copies and $self->inside_hard_stall_interval) { + # Unset valid_previous_copy if it's not local and we have local copies now + $self->{valid_previous_copy} = undef if ( + $self->{valid_previous_copy} + and $self->{valid_previous_copy}->{proximity} > 0 + ); + last; # No point in looking further "out". + } + my $rand = int(rand(scalar(@copies))); while (my ($c) = splice(@copies, $rand, 1)) { diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index a3d5085085..f9de804246 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -3581,6 +3581,15 @@ INSERT into config.org_unit_setting_type 'coust', 'description'), 'interval', null) +,( 'circ.pickup_hold_stalling.hard', 'holds', + oils_i18n_gettext('circ.pickup_hold_stalling.hard', + 'Pickup Library Hard stalling interval', + 'coust','label'), + oils_i18n_gettext('circ.pickup_hold_stalling.hard', + 'When set for the pickup library, this specifies that no items with a calculated proximity greater than 0 from the pickup library can be directly targeted for this time period if there are local available copies. Example "3 days".', + 'coust','description'), + 'interval', null) + ,( 'circ.hold_stalling_hard', 'holds', oils_i18n_gettext('circ.hold_stalling_hard', 'Hard stalling interval', diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.stalling-YAOUS.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.stalling-YAOUS.sql index 4ddcafcb26..965554d4c9 100644 --- a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.stalling-YAOUS.sql +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.stalling-YAOUS.sql @@ -16,5 +16,15 @@ INSERT into config.org_unit_setting_type null ); +INSERT into config.org_unit_setting_type +( name, grp, label, description, datatype, fm_class ) VALUES +( 'circ.pickup_hold_stalling.hard', + 'holds', + 'Pickup Library Hard stalling interval', + 'When set for the pickup library, this specifies that no items with a calculated proximity greater than 0 from the pickup library can be directly targeted for this time period if there are local available copies. Example "3 days".', + 'interval', + null +); + COMMIT; -- 2.11.0