From 3d18a107322e5c8c8d52030c57ede3670e63d373 Mon Sep 17 00:00:00 2001 From: Llewellyn Marshall Date: Wed, 18 Aug 2021 13:13:47 -0400 Subject: [PATCH] creates "reset reason entries" whenever a hold has been reset. Records previous copy, requesting user/ws, reset time and reset reason. reset reasons are stored in their own table and referenced in the perl constants file. Hold reset reason entries can be inspected in the staff client by viewing the "hold details" within a patron's profile signed-off-by: Llewellyn Marshall --- Open-ILS/examples/fm_IDL.xml | 43 ++++++++ .../lib/OpenILS/Application/Circ/Circulate.pm | 37 ++++++- .../perlmods/lib/OpenILS/Application/Circ/Holds.pm | 121 ++++++++++++++++++--- .../lib/OpenILS/Application/HoldTargeter.pm | 31 +++++- Open-ILS/src/perlmods/lib/OpenILS/Const.pm | 13 +++ .../src/sql/Pg/upgrade/xxxx.hold_reset_reasons.sql | 68 ++++++++++++ .../templates/staff/circ/share/t_hold_details.tt2 | 75 +++++++++++++ .../web/js/ui/default/staff/circ/services/holds.js | 78 +++++++++++++ 8 files changed, 445 insertions(+), 21 deletions(-) create mode 100644 Open-ILS/src/sql/Pg/upgrade/xxxx.hold_reset_reasons.sql diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 609a596628..bd3b786b97 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -6811,6 +6811,7 @@ SELECT usr, + @@ -6846,6 +6847,7 @@ SELECT usr, + @@ -15428,6 +15430,47 @@ 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..1a8e2a90fa 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm @@ -1868,14 +1868,22 @@ sub handle_checkout_holds { $logger->info("circulator: un-targeting hold ".$hold->id. " because copy ".$copy->id." is getting checked out"); - + try { + $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); + } catch Error with { + $logger->error("circulate: create reset reason failed with ".shift()); + }; $hold->clear_prev_check_time; $hold->clear_current_copy; $hold->clear_capture_time; $hold->clear_shelf_time; $hold->clear_shelf_expire_time; $hold->clear_current_shelf_lib; - return $self->bail_on_event($e->event) unless $e->update_action_hold_request($hold); @@ -2650,6 +2658,13 @@ sub checkin_retarget { next if ($_->{hold_type} eq 'P'); } # So much for easy stuff, attempt a retarget! + try{ + $U->simplereq('open-ils.circ', + 'open-ils.circ.hold_reset_reason_entry.create',$self->editor->authtoken, $_->{id},OILS_HOLD_BETTER_HOLD); + } + catch Error with{ + $logger->error("circulate: create reset reason failed with ".shift()); + }; my $tresult = $U->simplereq( 'open-ils.hold-targeter', 'open-ils.hold-targeter.target', @@ -3302,7 +3317,14 @@ sub attempt_checkin_hold_capture { $hold->clear_expire_time; $hold->clear_cancel_time; $hold->clear_prev_check_time unless $hold->prev_check_time; - + + try{ + $U->simplereq('open-ils.circ', + 'open-ils.circ.hold_reset_reason_entry.create',$self->editor->authtoken, $hold->id, OILS_HOLD_CHECK_IN); + } + catch Error with{ + $logger->error("circulate: create reset reason failed with ".shift()); + }; $self->bail_on_events($self->editor->event) unless $self->editor->update_action_hold_request($hold); $self->hold($hold); @@ -3446,7 +3468,14 @@ 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'); - $ses->request('open-ils.hold-targeter.target', {hold => $self->retarget}); + $ses->request('open-ils.hold-targeter.target', {hold => $self->retarget}); + try{ + 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); + } + catch Error with{ + $logger->error("circulate: create reset reason failed with ".shift()); + }; # 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..9ac558a1d3 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,67 @@ 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, $previous_copy) = @_; + 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){ + try{ + my ($hold, $evt) = $U->fetch_hold($holdid); + _create_reset_reason_entry( + $e, + $hold, + $reset_reason, + $note, + $previous_copy) + unless $evt; + } + catch Error with{ + $logger->error("holds: create reset reason failed with ".shift()); + }; + } + $e->commit; + return 1; +} + +sub _create_reset_reason_entry +{ + my($e, $hold, $reset_reason,$note,$previous_copy) = @_; + return 1 unless _reset_reason_entry_flag(); + 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 = defined $previous_copy ? $previous_copy : $hold->current_copy; + $entry->hold($hold->id); + $entry->reset_reason($reset_reason); + $entry->reset_time('now'); + $entry->previous_copy($last_copy); + $entry->note($note) if defined $note; + $entry->requestor($e->requestor->id) if defined $e->requestor; + $entry->requestor_workstation($e->requestor->wsid) if defined $e->requestor; + $e->create_action_hold_request_reset_reason_entry($entry) or return $e->die_event; + return 1; +} + +sub _reset_reason_entry_flag +{ + my $do_ahrrre = $U->get_global_flag('circ.holds.create_reset_reason_entries'); + return ($do_ahrrre and $U->is_true($do_ahrrre->enabled)); +} __PACKAGE__->register_method( method => 'reset_hold_batch', @@ -2239,11 +2329,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 +2339,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 +2356,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 +2366,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 +2374,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 +3587,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..ad7ed5b88c 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/HoldTargeter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/HoldTargeter.pm @@ -4,7 +4,9 @@ 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); +use OpenSRF::EX qw(:try); __PACKAGE__->register_method( method => 'hold_targeter', @@ -80,7 +82,8 @@ 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++; @@ -96,6 +99,27 @@ sub hold_targeter { $logger->error($msg); $single->message($msg) unless $single->message; } + else{ + try{ + # create a TIMED_OUT reset reason + # other types of resets are handled + # at their sources. + $hold_ses->request( + "open-ils.circ.hold_reset_reason_entry.create", + $single->editor()->authtoken, + $hold_id, + OILS_HOLD_TIMED_OUT, + undef, + $single->{previous_copy_id} + ) unless defined + $args->{hold} || + $single->{previous_copy_id} == $single->hold->current_copy; + } catch Error with { + $logger->error( + "hold-targeter: create reset reason failed with ".shift() + ); + } + } if (($count % $throttle) == 0) { # Time to reply to the caller. Return either the number @@ -105,9 +129,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 diff --git a/Open-ILS/src/sql/Pg/upgrade/xxxx.hold_reset_reasons.sql b/Open-ILS/src/sql/Pg/upgrade/xxxx.hold_reset_reasons.sql new file mode 100644 index 0000000000..39ab13a34f --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/xxxx.hold_reset_reasons.sql @@ -0,0 +1,68 @@ +CREATE TABLE action.hold_request_reset_reason +( + id serial NOT NULL, + manual boolean, + name text, +CONSTRAINT hold_request_reset_reason_pkey PRIMARY KEY (id), +CONSTRAINT hold_request_reset_reason_name_key UNIQUE (name) +) WITH ( + OIDS=FALSE +); + +INSERT INTO action.hold_request_reset_reason (id, name, manual) VALUES +(1,'HOLD_TIMED_OUT',false), +(2,'HOLD_MANUAL_RESET',true), +(3,'HOLD_BETTER_HOLD',false), +(4,'HOLD_FROZEN',true), +(5,'HOLD_UNFROZEN',true), +(6,'HOLD_CANCELED',true), +(7,'HOLD_UNCANCELED',true), +(8,'HOLD_UPDATED',true), +(9,'HOLD_CHECKED_OUT',true), +(10,'HOLD_CHECKED_IN',true); + +CREATE TABLE action.hold_request_reset_reason_entry +( + id serial NOT NULL, + hold int, + reset_reason int, + note text, + reset_time timestamp with time zone, + previous_copy bigint, + requestor int, + requestor_workstation int, + CONSTRAINT hold_request_reset_reason_entry_pkey PRIMARY KEY (id), + CONSTRAINT action_hold_request_reset_reason_entry_reason_fkey FOREIGN KEY (reset_reason) + REFERENCES action.hold_request_reset_reason (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED, +CONSTRAINT action_hold_request_reset_reason_entry_previous_copy_fkey FOREIGN KEY (previous_copy) + REFERENCES asset.copy (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED, + CONSTRAINT action_hold_request_reset_reason_entry_requestor_fkey FOREIGN KEY (requestor) + REFERENCES actor.usr (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED, + CONSTRAINT action_hold_request_reset_reason_entry_requestor_workstation_fkey FOREIGN KEY (requestor_workstation) + REFERENCES actor.workstation (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED, + CONSTRAINT action_hold_request_reset_reason_entry_hold_fkey FOREIGN KEY (hold) + REFERENCES action.hold_request (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED +) + +WITH ( + OIDS=FALSE +); + +CREATE INDEX ahrrre_hold ON action.hold_request_reset_reason_entry (hold); + +INSERT INTO config.global_flag (name, label, enabled) + VALUES ( + 'circ.holds.create_reset_reason_entries', + oils_i18n_gettext( + 'circ.holds.create_reset_reason_entries', + 'Create reset reasons whenever a hold has been reset.', + 'cgf', + 'label' + ), + TRUE + ); diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_details.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_details.tt2 index ece4719944..7da498ac2d 100644 --- a/Open-ILS/src/templates/staff/circ/share/t_hold_details.tt2 +++ b/Open-ILS/src/templates/staff/circ/share/t_hold_details.tt2 @@ -71,6 +71,11 @@ [% l('Staff Notifications') %] +
  • + + [% l('Reset Entries') %] + +
  • @@ -152,6 +157,76 @@
    + +
    +
    + + + + + + + + + + + + +
    +
    + [% l("Search In Progress") %] +
    +
    +
    +
    Time
    +
    Reason
    +
    Requestor
    +
    Note
    +
    Previous Copy
    +
    +
    +
    {{reset.reset_time() | date:$root.egDateAndTimeFormat}}
    +
    {{reset.reset_reason().name()}}
    +
    {{reset.requestor().usrname()}}
    +
    {{reset.note()}}
    + +
    +
    +
    +
    + [%- l('No reset entries found for this hold.') -%] +
    +
    +
    diff --git a/Open-ILS/web/js/ui/default/staff/circ/services/holds.js b/Open-ILS/web/js/ui/default/staff/circ/services/holds.js index 251ceb216e..6779376526 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/services/holds.js +++ b/Open-ILS/web/js/ui/default/staff/circ/services/holds.js @@ -858,7 +858,85 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) { }); } + + $scope.resetPage = 1; + $scope.resetsPerPage = 10; + $scope.maximumPages = 25; + $scope.resetsLoaded = false; + $scope.reverseResetOrder = false; + + $scope.show_resets_tab = function() { + $scope.detail_tab = 'resets'; + egCore.pcrud.search('ahrrre', + {hold : $scope.hold.id()}, + { + flesh : 1, + flesh_fields : {ahrrre : ['reset_reason','requestor','previous_copy']}, + limit : $scope.resetsPerPage * $scope.maximumPages + }, + {atomic : true} + ).then(function(ents) { + // sort the reset notes by date + ents.sort( + function(a,b){ + return Date.parse(a.reset_time()) - Date.parse(b.reset_time()); + } + ); + $scope.hold.reset_entries(ents); + $scope.filter_resets(); + $scope.resetsLoaded = true; + }); + } + + $scope.filter_resets = function(){ + if( + typeof($scope.hold) === 'undefined' || + typeof($scope.hold.reset_entries) === 'undefined' || + $scope.hold.reset_entries() === null + ) + return; + var begin = (($scope.resetPage - 1) * $scope.resetsPerPage), + end = begin + $scope.resetsPerPage; + $scope.filteredResets = $scope.hold + .reset_entries() + .slice(begin,end); + } + + $scope.reverse_reset_order = function(){ + $scope.hold.reset_entries().reverse() + $scope.reverseResetOrder = !$scope.reverseResetOrder; + $scope.first_rs_page(); + } + + $scope.on_first_rs_page = function(){ + return $scope.resetPage == 1; + } + + $scope.has_next_rs_page = function(){ + return $scope.resetPage < $scope.max_rs_pages(); + } + + $scope.max_rs_pages = function(){ + if(typeof($scope.hold.reset_entries) === 'undefined' || $scope.hold.reset_entries() === null) + return 0; + return $scope.hold.reset_entries().length/$scope.resetsPerPage; + } + + $scope.first_rs_page = function() { + $scope.resetPage = 1; + } + + $scope.increment_rs_page = function() { + $scope.resetPage++; + } + $scope.decrement_rs_page = function() { + $scope.resetPage--; + } + + $scope.$watch('resetPage',$scope.filter_resets); + $scope.$watch('reverseResetOrder',$scope.filter_resets); + $scope.show_notify_tab = function() { $scope.detail_tab = 'notify'; egCore.pcrud.search('ahn', -- 2.11.0