From: Llewellyn Marshall Date: Wed, 13 Apr 2022 20:39:33 +0000 (-0400) Subject: Created two tables for recording information about when a hold has been X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=d8bd89a5615e3aa887f241863cc18079b0a85176;p=working%2FEvergreen.git Created two tables for recording information about when a hold has been reset. One table, the action.hold_request_reset_reason stores common reasons for why a hold request has been reset. For example there's manual reset, hold canceled, pickup lib changed etc. The IDS of these are stored in the perl constants the same as your copy statuses. The second table, action.hold_request_reset_reason_entry records every time a hold has been reset for any reason, and who is responsible for the reset, including their workstation.The entries also include a "note" field which records extra information like which modified fields triggered the reset or which patron recieved the target copy. --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 674ace4fc6..9e46b71255 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -13513,6 +13513,34 @@ 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 7ac877b069..3db5c15f8e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm @@ -1887,7 +1887,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); @@ -2662,6 +2663,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', @@ -3308,7 +3311,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); @@ -3452,6 +3457,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 b9f3705664..0cace5dd86 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm @@ -1024,7 +1024,7 @@ sub uncancel_hold { $hold->clear_prev_check_time; $hold->clear_shelf_expire_time; $hold->clear_current_shelf_lib; - _create_reset_hold_note($e,$hold,"Hold Reset due to Uncancelation","Hold was reset due to Uncancelation."); + _create_reset_reason_entry($e,$hold,OILS_HOLD_UNCANCELED); $e->update_action_hold_request($hold) or return $e->die_event; $e->commit; @@ -1107,10 +1107,21 @@ sub cancel_hold { $hold->cancel_time('now'); $hold->cancel_cause($cause); $hold->cancel_note($note); - my $note_body = "Hold Cancelation."; - $note_body .= " Cancel Cause ID - $cause;"; - $note_body .= " Cancel Note - $note" unless $note eq ""; - _create_reset_hold_note($e,$hold,"Hold Reset due to Cancelation",$note_body); + 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; @@ -1211,6 +1222,7 @@ 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) { @@ -1223,10 +1235,12 @@ 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." } } @@ -1333,11 +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); - $note_body .= "Hold was Frozen."; - $note_body .= " Previous target was copy ID ".$hold->current_copy."." if defined($hold->current_copy); + _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. @@ -1356,15 +1369,16 @@ sub update_hold_impl { if(!$U->is_true($hold->frozen) && $U->is_true($orig_hold->frozen)) { $logger->info("Reset expire_time on activated hold ".$hold->id); $hold->expire_time(calculate_expire_time($hold->request_lib)); - $note_body .= "Hold was Unfrozen."; } $e->update_action_hold_request($hold) or return $e->die_event; - _create_reset_hold_note($e,$hold,"Hold Reset due to Update",$note_body) unless $note_body eq ""; + _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}); } @@ -1372,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; } @@ -1462,7 +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_hold_note($e,$hold,"Hold Reset by Unfreezing","Running targeter on activated hold"); + _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}); } @@ -2223,48 +2239,47 @@ sub reset_hold { } __PACKAGE__->register_method( - method => 'create_reset_hold_note', - api_name => 'open-ils.circ.hold_reset_note.create' + method => 'create_reset_reason_entry', + api_name => 'open-ils.circ.hold_reset_reason_entry.create' ); -sub create_reset_hold_note +sub create_reset_reason_entry { - my($self, $conn, $holdid, $title, $note_body) = @_; - my $e = new_editor(xact => 1); - $logger->info("got editor"); - #return $e->die_event unless $e->checkauth; - my ($hold, $evt) = $U->fetch_hold($holdid); - $logger->info("fetched hold"); - return $evt if $evt; - _create_reset_hold_note($e, $hold, $title, $note_body); + 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_hold_note +sub _create_reset_reason_entry { - my($e, $hold, $title, $note_body) = @_; + my($e, $hold, $reset_reason,$note) = @_; my $ts = DateTime->now; - my $note = Fieldmapper::action::hold_request_note->new; - $logger->info("Creating hold note with title: " . $title . " and body: " . $note_body . " hold id: " . $hold->id); - my $last_copy = $hold->current_copy || 0; - my $reqr = $e->requestor; - my $reqr_id = defined $reqr ? $reqr->id : 0; - my $reqr_usrname = $reqr_id ? $reqr->usrname : ""; - $title.=" ".$ts->mdy." ".$ts->hms; - my $json = "{"; - $json .= "\"Reset Reason\" : \"$note_body\","; - $json .= "\"Timestamp\" : \"".$ts->mdy." ".$ts->hms."\","; - $json .= "\"Previous Copy ID\" : \"$last_copy\"," unless $last_copy == 0; - $json .= "\"Requestor ID\" : \"".$reqr_id."\","; - $json .= "\"Requestor Usrname\" : \"".$reqr_usrname."\""; - $json .= "}"; - $note->hold($hold); - $note->staff(1); - $note->pub(0); - $note->title($title); - $note->body($json); - $e->create_action_hold_request_note($note) or return $e->die_event; + 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; } @@ -2300,9 +2315,7 @@ sub _reset_hold { my $e = new_editor(xact =>1, requestor => $reqr); my $hid = $hold->id; $logger->info("reseting hold ".$hid." requestor was ".$reqr->usrname." (ID ".$reqr->id.")"); - - my $note_body = "Manually retargetted."; - + my $note_body = ""; if( $hold->capture_time and $hold->current_copy ) { my $copy = $e->retrieve_asset_copy($hold->current_copy) @@ -2337,7 +2350,7 @@ sub _reset_hold { } } - _create_reset_hold_note($e,$hold,"Hold Reset by Staff",$note_body); + _create_reset_reason_entry($e,$hold,OILS_HOLD_MANUAL_RESET,$note_body); $hold->clear_capture_time; $hold->clear_current_copy; $hold->clear_shelf_time; @@ -3558,7 +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_hold_note($editor,$old_hold,"Hold Reset due to Age","Old hold was reset. Last check time was ".$old_hold->prev_check_time.". 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 de1553d371..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( @@ -88,11 +89,15 @@ sub hold_targeter { my $single = OpenILS::Utils::HoldTargeter::Single->new(parent => $targeter); - $hold_ses->request( - "open-ils.circ.hold_reset_note.create", + # 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, - "Hold Automatically Retargeted", - "Automatic Reset.") unless defined $args->{hold}; + OILS_HOLD_TIMED_OUT) + unless defined $args->{hold}; # Don't let an explosion on a single hold stop processing eval { $single->target($hold_id) }; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Const.pm b/Open-ILS/src/perlmods/lib/OpenILS/Const.pm index 85e8b71889..d81d3e89e3 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Const.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Const.pm @@ -130,6 +130,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; # ---------------------------------------------------------------------