From 7556efa2e7add4ff0415db0ac1e7e2b3184306bb Mon Sep 17 00:00:00 2001 From: Llewellyn Marshall Date: Wed, 18 Aug 2021 13:13:47 -0400 Subject: [PATCH] log username of retargeter add hold notes better notes for hold update (cherry picked from commit 5672d9d70fd7122073f7bbf6ba7415339cf42d10) json format in hold reset hold notes, added cancel cause & cancel note added API call for create hold reset note, it is used within the hold targeter when not called against a specific hold. added a hold reset note for better hold overwriting old hold. --- Open-ILS/examples/fm_IDL.xml | 29 ++++++ .../lib/OpenILS/Application/Circ/Circulate.pm | 11 ++- .../perlmods/lib/OpenILS/Application/Circ/Holds.pm | 105 ++++++++++++++++++--- .../lib/OpenILS/Application/HoldTargeter.pm | 19 +++- Open-ILS/src/perlmods/lib/OpenILS/Const.pm | 13 +++ 5 files changed, 158 insertions(+), 19 deletions(-) diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 609a596628..0f22734acd 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -15428,6 +15428,35 @@ SELECT usr, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm index 0e417c593f..29dec0901e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm @@ -1875,7 +1875,8 @@ sub handle_checkout_holds { $hold->clear_shelf_time; $hold->clear_shelf_expire_time; $hold->clear_current_shelf_lib; - + $U->simplereq('open-ils.circ', + 'open-ils.circ.hold_reset_reason_entry.create',$e->authtoken,$hold->id,OILS_HOLD_CHECK_OUT,"Checked out to patron #".$patron->id); return $self->bail_on_event($e->event) unless $e->update_action_hold_request($hold); @@ -2650,6 +2651,8 @@ sub checkin_retarget { next if ($_->{hold_type} eq 'P'); } # So much for easy stuff, attempt a retarget! + $U->simplereq('open-ils.circ', + 'open-ils.circ.hold_reset_reason_entry.create',$self->editor->authtoken, $_->{id},OILS_HOLD_BETTER_HOLD); my $tresult = $U->simplereq( 'open-ils.hold-targeter', 'open-ils.hold-targeter.target', @@ -3302,7 +3305,9 @@ sub attempt_checkin_hold_capture { $hold->clear_expire_time; $hold->clear_cancel_time; $hold->clear_prev_check_time unless $hold->prev_check_time; - + + $U->simplereq('open-ils.circ', + 'open-ils.circ.hold_reset_reason_entry.create',$self->editor->authtoken, $hold->id, OILS_HOLD_CHECK_IN); $self->bail_on_events($self->editor->event) unless $self->editor->update_action_hold_request($hold); $self->hold($hold); @@ -3446,6 +3451,8 @@ sub retarget_holds { my $self = shift; $logger->info("circulator: retargeting holds @{$self->retarget} after opportunistic capture"); my $ses = OpenSRF::AppSession->create('open-ils.hold-targeter'); + my $cses = OpenSRF::AppSession->create('open-ils.circ'); + $cses->request('open-ils.circ.hold_reset_reason_entry.create',$self->editor->authtoken, $self->retarget,OILS_HOLD_BETTER_HOLD); $ses->request('open-ils.hold-targeter.target', {hold => $self->retarget}); # no reason to wait for the return value return; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm index a11d0abfe7..0dd2ad4f20 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm @@ -1024,13 +1024,12 @@ sub uncancel_hold { $hold->clear_prev_check_time; $hold->clear_shelf_expire_time; $hold->clear_current_shelf_lib; - + _create_reset_reason_entry($e,$hold,OILS_HOLD_UNCANCELED); $e->update_action_hold_request($hold) or return $e->die_event; $e->commit; - + $U->simplereq('open-ils.hold-targeter', 'open-ils.hold-targeter.target', {hold => $hold_id}); - return 1; } @@ -1058,11 +1057,13 @@ sub cancel_hold { my $e = new_editor(authtoken=>$auth, xact=>1); return $e->die_event unless $e->checkauth; - + + my $req = $e->requestor->id; + my $hold = $e->retrieve_action_hold_request($holdid) or return $e->die_event; - if( $e->requestor->id ne $hold->usr ) { + if( $req ne $hold->usr ) { return $e->die_event unless $e->allowed('CANCEL_HOLDS'); } @@ -1106,6 +1107,21 @@ sub cancel_hold { $hold->cancel_time('now'); $hold->cancel_cause($cause); $hold->cancel_note($note); + my $note_body = ""; + if($cause){ + my $cancel_reason = "ID $cause"; + my $cancel_cause = $e->retrieve_action_hold_request_cancel_cause($cause); + if($cancel_cause){ + $cancel_reason = $cancel_cause->label; + } + $note_body .= "Cancel Cause: $cancel_reason"; + } + else{ + $note_body .= "Cancel reason unknown"; + } + $note_body .= "," unless $note_body eq "" || $note eq ""; + $note_body .= " Cancel Note: \"$note\"" unless $note eq ""; + _create_reset_reason_entry($e,$hold,OILS_HOLD_CANCELED,$note_body); $e->update_action_hold_request($hold) or return $e->die_event; @@ -1206,6 +1222,8 @@ sub update_hold_impl { my($self, $e, $hold, $values) = @_; my $hold_status; my $need_retarget = 0; + my $reset_reason = OILS_HOLD_UPDATED; + my $note_body = ""; unless($hold) { $hold = $e->retrieve_action_hold_request($values->{id}) @@ -1217,9 +1235,13 @@ sub update_hold_impl { if (defined $values->{$k} && defined $hold->$k() && $values->{$k} ne $hold->$k()) { # Value changed? RETARGET! $need_retarget = 1; + $reset_reason = OILS_HOLD_UPDATED; + $note_body .= "$k value changed." } elsif (defined $hold->$k() != defined $values->{$k}) { # Value being set or cleared? RETARGET! $need_retarget = 1; + $reset_reason = OILS_HOLD_UPDATED; + $note_body .= "$k value cleared." } } if (defined $values->{$k}) { @@ -1325,9 +1347,10 @@ sub update_hold_impl { $hold->clear_current_copy; } } - + if($U->is_true($hold->frozen)) { $logger->info("clearing current_copy and check_time for frozen hold ".$hold->id); + _create_reset_reason_entry($e,$hold,OILS_HOLD_FROZEN,$note_body) unless $U->is_true($orig_hold->frozen); $hold->clear_current_copy; $hold->clear_prev_check_time; # Clear expire_time to prevent frozen holds from expiring. @@ -1349,10 +1372,13 @@ sub update_hold_impl { } $e->update_action_hold_request($hold) or return $e->die_event; + _create_reset_reason_entry($e,$hold,$reset_reason,$note_body) if $need_retarget; $e->commit; - + if(!$U->is_true($hold->frozen) && $U->is_true($orig_hold->frozen)) { $logger->info("Running targeter on activated hold ".$hold->id); + $U->simplereq('open-ils.circ', + 'open-ils.circ.hold_reset_reason_entry.create',$e->authtoken,$hold->id,OILS_HOLD_UNFROZEN); $U->simplereq('open-ils.hold-targeter', 'open-ils.hold-targeter.target', {hold => $hold->id}); } @@ -1360,11 +1386,13 @@ sub update_hold_impl { # a change to mint-condition changes the set of potential copies, so retarget the hold; if($U->is_true($hold->mint_condition) and !$U->is_true($orig_hold->mint_condition)) { _reset_hold($self, $e->requestor, $hold) - } elsif($need_retarget && !defined $hold->capture_time()) { # If needed, retarget the hold due to changes + } elsif($need_retarget && !defined $hold->capture_time()) { # If needed, retarget the hold due to changes $U->simplereq('open-ils.hold-targeter', 'open-ils.hold-targeter.target', {hold => $hold->id}); } - + + + return $hold->id; } @@ -1450,6 +1478,7 @@ sub update_hold_if_frozen { } else { if($U->is_true($orig_hold->frozen)) { $logger->info("Running targeter on activated hold ".$hold->id); + _create_reset_reason_entry($e,$hold,OILS_HOLD_UNFROZEN,"Running targeter on activated hold"); $U->simplereq('open-ils.hold-targeter', 'open-ils.hold-targeter.target', {hold => $hold->id}); } @@ -2209,6 +2238,51 @@ sub reset_hold { return 1; } +__PACKAGE__->register_method( + method => 'create_reset_reason_entry', + api_name => 'open-ils.circ.hold_reset_reason_entry.create' +); + +sub create_reset_reason_entry +{ + my($self, $conn, $auth, $hold, $reset_reason, $note) = @_; + my $e = new_editor(authtoken => $auth, xact => 1); + #checkauth to set the requestor (if available) + $e->checkauth; + my @holds; + if(ref $hold eq 'ARRAY'){ + @holds = @{$hold}; + } + else{ + @holds = ($hold); + } + for my $holdid (@holds){ + my ($hold, $evt) = $U->fetch_hold($holdid); + return $evt if $evt; + _create_reset_reason_entry($e, $hold, $reset_reason, $note); + } + $e->commit; + return 1; +} + +sub _create_reset_reason_entry +{ + my($e, $hold, $reset_reason,$note) = @_; + my $ts = DateTime->now; + my $entry = Fieldmapper::action::hold_request_reset_reason_entry->new; + $logger->info("Creating reset reason entry for hold #" . $hold->id); + my $last_copy = $hold->current_copy; + $entry->hold($hold->id); + $entry->reset_reason($reset_reason); + $entry->reset_time('now'); + $entry->requestor($e->requestor->id) if defined $e->requestor; + $entry->requestor_workstation($e->requestor->wsid) if defined $e->requestor; + $entry->previous_copy($last_copy); + $entry->note($note); + $e->create_action_hold_request_reset_reason_entry($entry) or return $e->die_event; + return 1; +} + __PACKAGE__->register_method( method => 'reset_hold_batch', @@ -2239,11 +2313,9 @@ sub _reset_hold { my ($self, $reqr, $hold) = @_; my $e = new_editor(xact =>1, requestor => $reqr); - - $logger->info("reseting hold ".$hold->id); - my $hid = $hold->id; - + $logger->info("reseting hold ".$hid." requestor was ".$reqr->usrname." (ID ".$reqr->id.")"); + my $note_body = ""; if( $hold->capture_time and $hold->current_copy ) { my $copy = $e->retrieve_asset_copy($hold->current_copy) @@ -2251,6 +2323,7 @@ sub _reset_hold { if( $copy->status == OILS_COPY_STATUS_ON_HOLDS_SHELF ) { $logger->info("setting copy to status 'reshelving' on hold retarget"); + $note_body.=" set copy to status 'reshelving'."; $copy->status(OILS_COPY_STATUS_RESHELVING); $copy->editor($e->requestor->id); $copy->edit_date('now'); @@ -2267,6 +2340,7 @@ sub _reset_hold { $logger->info("Aborting transit [$transid] on hold [$hid] reset..."); my $evt = OpenILS::Application::Circ::Transit::__abort_transit($e, $trans, $copy, 1, 1); $logger->info("Transit abort completed with result $evt"); + $note_body.=" Transit abort completed with result $evt."; unless ("$evt" eq 1) { $e->rollback; return $evt; @@ -2276,6 +2350,7 @@ sub _reset_hold { } } + _create_reset_reason_entry($e,$hold,OILS_HOLD_MANUAL_RESET,$note_body); $hold->clear_capture_time; $hold->clear_current_copy; $hold->clear_shelf_time; @@ -2283,8 +2358,9 @@ sub _reset_hold { $hold->clear_current_shelf_lib; $e->update_action_hold_request($hold) or return $e->die_event; + $e->commit; - + $U->simplereq('open-ils.hold-targeter', 'open-ils.hold-targeter.target', {hold => $hold->id}); @@ -3495,6 +3571,7 @@ sub find_nearest_permitted_hold { next if $old_hold->id eq $best_hold->id; # don't re-target the hold we want $logger->info("circulator: clearing current_copy and prev_check_time on hold ". $old_hold->id." after a better hold [".$best_hold->id."] was found"); + _create_reset_reason_entry($editor,$old_hold,OILS_HOLD_BETTER_HOLD,"Old hold was reset. Last check time was ".$old_hold->prev_check_time.". a better hold [".$best_hold->id."] was found"); $old_hold->clear_current_copy; $old_hold->clear_prev_check_time; $editor->update_action_hold_request($old_hold) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/HoldTargeter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/HoldTargeter.pm index afca2fcc9e..7b54b39c74 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/HoldTargeter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/HoldTargeter.pm @@ -4,6 +4,7 @@ use warnings; use OpenILS::Application; use base qw/OpenILS::Application/; use OpenILS::Utils::HoldTargeter; +use OpenILS::Const qw/:const/; use OpenSRF::Utils::Logger qw(:logger); __PACKAGE__->register_method( @@ -80,13 +81,24 @@ sub hold_targeter { my $total = scalar(@hold_ids); $logger->info("targeter processing $total holds"); - + my $hold_ses = create OpenSRF::AppSession("open-ils.circ"); + for my $hold_id (@hold_ids) { $count++; my $single = OpenILS::Utils::HoldTargeter::Single->new(parent => $targeter); + # If targeter is issued without a hold + # it will retarget all of the holds that need it + # so we shoot off a RRE for all them. + $hold_ses->request( + "open-ils.circ.hold_reset_reason_entry.create", + $single->editor()->authtoken, + $hold_id, + OILS_HOLD_TIMED_OUT) + unless defined $args->{hold}; + # Don't let an explosion on a single hold stop processing eval { $single->target($hold_id) }; @@ -105,9 +117,10 @@ sub hold_targeter { $client->respond($res); $logger->info("targeted $count of $total holds"); - } + } } - + $hold_ses->disconnect; + return undef; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Const.pm b/Open-ILS/src/perlmods/lib/OpenILS/Const.pm index 0ff488090f..093f1a67ea 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Const.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Const.pm @@ -133,6 +133,19 @@ econst OILS_PENALTY_INVALID_PATRON_ADDRESS => 29; econst OILS_BILLING_TYPE_NOTIFICATION_FEE => 9; +# --------------------------------------------------------------------- +# Hold reset reasons +# --------------------------------------------------------------------- +econst OILS_HOLD_TIMED_OUT => 1; +econst OILS_HOLD_MANUAL_RESET => 2; +econst OILS_HOLD_BETTER_HOLD => 3; +econst OILS_HOLD_FROZEN => 4; +econst OILS_HOLD_UNFROZEN => 5; +econst OILS_HOLD_CANCELED => 6; +econst OILS_HOLD_UNCANCELED => 7; +econst OILS_HOLD_UPDATED => 8; +econst OILS_HOLD_CHECK_OUT => 9; +econst OILS_HOLD_CHECK_IN => 10; # --------------------------------------------------------------------- # Non Evergreen-specific constants -- 2.11.0