From: Bill Erickson Date: Tue, 7 Jun 2016 22:08:23 +0000 (-0400) Subject: hold targeter reify experiment X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=2ac4809582886fcf1c0cc5d1ac9bd94ad5ce152c;p=working%2FEvergreen.git hold targeter reify experiment Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm index 792732d741..14d91e863c 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm @@ -17,10 +17,11 @@ my $dt_parser = DateTime::Format::ISO8601->new; # -- better up-front copy filtering when finding potential copies sub new { - my $class = shift; + my ($class, %args) = @_; my $self = { editor => new_editor(), - ou_setting_cache => {} + ou_setting_cache => {}, + %args, }; return bless($self, $class); } @@ -51,36 +52,37 @@ sub get_ou_setting { return $c->{$org_id}->{$setting}; } -# TODO: stream messages back to caller sub exit_targeter { my ($self, $msg) = @_; + $self->{exit} = 1; + $self->{exit_msg} = $msg; $self->{editor}->rollback; # no-op if commit already occurred. my $hold_id = $self->{hold_id}; $logger->info("targeter: exiting hold targeter for $hold_id : $msg"); return 0; } -# Cancel expired holds and kick off the A/T no-target event. -# Returns true if the hold is expired or an error occured. -# False otherwise. +# Cancel expired holds and kick off the A/T no-target event. Returns +# true (i.e. keep going) if the hold is not expired. Returns false if +# the hold is canceled or a non-recoverable error occcurred. sub handle_expired_hold { my $self = shift; my $hold = $self->{hold}; - return 0 unless $hold->expire_time; + return 1 unless $hold->expire_time; my $ex_time = $dt_parser->parse_datetime(cleanse_ISO8601($hold->expire_time)); - return 0 unless DateTime->compare($ex_time, DateTime->now) < 0; + return 1 unless DateTime->compare($ex_time, DateTime->now) < 0; - # Hold is expired + # Hold is expired -- $hold->cancel_time('now'); $hold->cancel_cause(1); # == un-targeted expiration if (!$self->{editor}->update_action_hold_request($hold)) { - $self->exit_targeter("Error canceling hold"); - return 1; # Tell the caller to exit + my $evt = $self->{editor}->die_event; + return $self->exit_targeter("Error canceling hold: ".$evt->{textcode}); } $self->{editor}->commit; @@ -92,21 +94,27 @@ sub handle_expired_hold { $hold, $hold->pickup_lib ); - return 1; + return $self->exit_targeter("Hold is expired"); } # Hold copy maps are only automatically deleted when the hold # is fulfilled or canceled. Here, they have to be manually removed. -# Returns event on error, undef on success. +# Returns true on success, false on error. sub remove_copy_maps { my $self = shift; my $e = $self->{editor}; my $prev_maps = $e->search_action_hold_copy_map({hold => $self->{hold_id}}); + for my $map (@$prev_maps) { - $e->delete_action_hold_copy_map($map) or return $e->die_event; + if (!$e->delete_action_hold_copy_map($map)) { + my $evt = $e->die_event; + return $self->exit_targeter( + "Error deleting copy maps: ".$evt->{textcode}); + } } - return undef; + + return 1; } sub get_hold_copies { @@ -245,10 +253,22 @@ sub get_hold_copies { return map {$_->{id}} @$res; } -sub handle_no_copies { - my $self = shift; +sub inspect_potential_copies { + my ($self, @copy_ids) = @_; + my $e = $self->{editor}; my $hold = $self->{hold}; + my $hold_id = $self->{hold_id}; + + $logger->info("targeter: Hold $hold_id has ". + scalar(@copy_ids)." potential copies"); + + # Let the caller know we found the copy they were interested in. + $self->{found_copy} = 1 if $self->{find_copy} + && grep {$_ eq $self->{find_copy}} @copy_ids; + + # We have copies. Nothing left to do here. + return 1 if @copy_ids; $hold->prev_check_time('now'); $hold->clear_current_copy; @@ -264,11 +284,38 @@ sub handle_no_copies { } +sub build_copy_maps { + my ($self, @copy_ids) = @_; + my $e = $self->{editor}; + + for my $copy_id (@copy_ids) { + my $map = Fieldmapper::action::hold_copy_map->new; + + $map->hold($self->{hold_id}); + $map->target_copy($copy_id); + + if (!$e->create_action_hold_copy_map($map)) { + my $evt = $e->die_event; + return $self->exit_targeter( + "Error creating hold copy map: ".$evt->{textcode}); + } + } + + # TODO: collect proximities + + return 1; +} + + # Targets a single hold request sub target_hold { my ($self, $hold_id) = @_; my $e = $self->{editor}; + + # reset hold-specific toggles + $self->{exit} = 0; $self->{hold_id} = $hold_id; + $self->{found_copy} = 0; $e->xact_begin; @@ -279,20 +326,15 @@ sub target_hold { return $self->exit_targeter("Hold is not eligible for targeting") if $hold->capture_time || $hold->cancel_time; - # Remove any existing hold copy maps so they can be replaced. - my $evt = $self->remove_copy_maps; - return $self->exit_targeter( - "Error deleting copy maps: ".$evt->{textcode}) if $evt; - - return $self->exit_targeter("Hold is expired") - if $self->handle_expired_hold; + return unless $self->remove_copy_maps; + return unless $self->handle_expired_hold; my @copy_ids = $self->get_hold_copies; + return unless $self->inspect_potential_copies(@copy_ids); - return $self->handle_no_copies unless @copy_ids; + return unless $self->build_copy_maps(@copy_ids); - $logger->info("targeter: Hold $hold_id has ". - scalar(@copy_ids)." potential copies"); + $e->commit; } diff --git a/Open-ILS/src/support-scripts/test-scripts/hold_targeter.pl b/Open-ILS/src/support-scripts/test-scripts/hold_targeter.pl index 54fa8635f2..c1b2acd45e 100755 --- a/Open-ILS/src/support-scripts/test-scripts/hold_targeter.pl +++ b/Open-ILS/src/support-scripts/test-scripts/hold_targeter.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl #---------------------------------------------------------------- -# Simple cstore example +# Simple hold targeter test script #---------------------------------------------------------------- require '../oils_header.pl';