From cf2b64e3553f1736a6e9a819d7d36731664cd1ba Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 1 Feb 2021 10:54:18 -0500 Subject: [PATCH] LP1913811 Items out notice summary API batching Tweak the open-ils.actor.user.itemsout.notices API to accept an array of circulation IDs so the call can be batched from the client. Similarly modify the AngJS client to request the notice summaries in batch. Further improves the notices API by removing an unneeded join and a minor security fix to verify perms based on the in-database user ID instead of the ID provided by the caller (w/ the note that the API only returns numbers, not user data). Signed-off-by: Bill Erickson Signed-off-by: Jeff Davis Signed-off-by: Chris Sharp --- .../perlmods/lib/OpenILS/Application/Actor.pm | 53 ++++++++++++++++--- .../ui/default/staff/circ/patron/items_out.js | 42 +++++++++------ 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm index 5d85c7994c..bbe57e29a2 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm @@ -3766,17 +3766,50 @@ __PACKAGE__->register_method ( method => 'get_itemsout_notices', api_name => 'open-ils.actor.user.itemsout.notices', stream => 1, - argc => 3 + argc => 2, + signature => { + desc => q/Summary counts of circulat notices/, + params => [ + {desc => 'authtoken', type => 'string'}, + {desc => 'circulation identifiers', type => 'array of numbers'} + ], + return => q/Stream of summary objects/ + } ); -sub get_itemsout_notices{ - my( $self, $conn, $auth, $circId, $patronId) = @_; +sub get_itemsout_notices { + my ($self, $client, $auth, $circ_ids) = @_; my $e = new_editor(authtoken => $auth); return $e->event unless $e->checkauth; + $circ_ids = [$circ_ids] unless ref $circ_ids eq 'ARRAY'; + + for my $circ_id (@$circ_ids) { + my $resp = get_itemsout_notices_impl($e, $circ_id); + + if ($U->is_event($resp)) { + $client->respond($resp); + return; + } + + $client->respond({circ_id => $circ_id, %$resp}); + } + + return undef; +} + + + +sub get_itemsout_notices_impl { + my ($e, $circId) = @_; + my $requestorId = $e->requestor->id; + my $circ = $e->retrieve_action_circulation($circId) or return $e->event; + + my $patronId = $circ->usr; + if( $patronId ne $requestorId ){ my $user = $e->retrieve_actor_user($requestorId) or return $e->event; return $e->event unless $e->allowed('VIEW_CIRCULATIONS', $user->home_ou); @@ -3796,15 +3829,20 @@ sub get_itemsout_notices{ # my $ctx_loc = $e->requestor->ws_ou; - my $exclude_courtesy_notices = $U->ou_ancestor_setting_value($ctx_loc, 'webstaff.circ.itemsout_notice_count_excludes_courtesies'); + my $exclude_courtesy_notices = $U->ou_ancestor_setting_value( + $ctx_loc, 'webstaff.circ.itemsout_notice_count_excludes_courtesies'); + my $query = { select => { atev => ["complete_time"] }, from => { atev => { - atevdef => { field => "id",fkey => "event_def", join => { ath => { field => "key", fkey => "hook" }} } + atevdef => { field => "id",fkey => "event_def"} } }, - where => {"+ath" => { key => "checkout.due" },"+atevdef" => { active => 't' },"+atev" => { target => $circId, state => 'complete' }} + where => { + "+atevdef" => { active => 't', hook => 'checkout.due' }, + "+atev" => { target => $circId, state => 'complete' } + } }; if ($exclude_courtesy_notices){ @@ -3825,8 +3863,7 @@ sub get_itemsout_notices{ } } - $conn->respond(\%resblob); - return undef; + return \%resblob; } __PACKAGE__->register_method ( diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js b/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js index 522a08de50..ed0f0f57e5 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js @@ -140,7 +140,7 @@ function($scope , $q , $routeParams , $timeout , egCore , egUser , patronSvc , // we need an order-by to support paging order_by : {circ : ['xact_start']} - }).then(deferred.resolve, null, function(circ) { + }).then(null, null, function(circ) { circ.circ_lib(egCore.org.get(circ.circ_lib())); // local fleshing // Translate bib display field JSON blobs to JS. @@ -160,21 +160,31 @@ function($scope , $q , $routeParams , $timeout , egCore , egUser , patronSvc , return part.label() }).join(','); - // call open-ils to get overdue notice count and Last notice date - - egCore.net.request( - 'open-ils.actor', - 'open-ils.actor.user.itemsout.notices', - egCore.auth.token(), circ.id(), $scope.patron_id) - .then(function(notice){ - if (notice.numNotices){ - circ.action_trigger_event_count = notice.numNotices; - circ.action_trigger_latest_event_date = notice.lastDt; - } - patronSvc.items_out.push(circ); - }); - - if (rendered++ >= offset && rendered <= count){ deferred.notify(circ) }; + patronSvc.items_out.push(circ); + + }).then(function() { + + var circIds = patronSvc.items_out.map(function(circ) { return circ.id() }); + + egCore.net.request( + 'open-ils.actor', + 'open-ils.actor.user.itemsout.notices', + egCore.auth.token(), circIds + + ).then(deferred.resolve, null, function(notice) { + + var circ = patronSvc.items_out.filter( + function(circ) {return circ.id() == notice.circ_id})[0]; + + if (notice.numNotices) { + circ.action_trigger_event_count = notice.numNotices; + circ.action_trigger_latest_event_date = notice.lastDt; + } + + if (rendered++ >= offset && rendered <= count) { + deferred.notify(circ); + }; + }); }); return deferred.promise; -- 2.43.2