lp1712861 Notices Column Picker in Patron Holds
authorKyle Huckins <khuckins@catalyte.io>
Tue, 11 Jun 2019 23:04:42 +0000 (23:04 +0000)
committerKyle Huckins <khuckins@catalyte.io>
Wed, 10 Jul 2019 17:20:12 +0000 (17:20 +0000)
- Migrate Patorn Holds UI to utilize wide_holds API introduced in
lp1712854
- Expand wide_holds API to support multiple conditional restrictions
at a time, including greater_than and less_than

Signed-off-by: Kyle Huckins <khuckins@catalyte.io>
 Changes to be committed:
modified:   Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
modified:   Open-ILS/src/templates/staff/circ/patron/t_holds_list.tt2
modified:   Open-ILS/web/js/ui/default/staff/circ/patron/holds.js
modified:   Open-ILS/web/js/ui/default/staff/services/patron_search.js

Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
Open-ILS/src/templates/staff/circ/patron/t_holds_list.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/holds.js
Open-ILS/web/js/ui/default/staff/services/patron_search.js

index 4a49804..3a5f665 100644 (file)
@@ -2389,19 +2389,14 @@ SELECT  h.id, h.request_time, h.capture_time, h.fulfillment_time, h.checkin_time
         my $real = $field_map{$r} || $r;
         next if ($r =~ /[^a-z_.]/); # skip obvious bad inputs
 
-        my $not = '';
+        my $sel_str = '';
         if (ref($$restrictions{$r}) and ref($$restrictions{$r}) =~ /HASH/) {
-            $not = 'NOT';
-            $$restrictions{$r} = $$restrictions{$r}{not};
-        }
-
-        if (!defined($$restrictions{$r})) { 
-            $select .= " AND $real IS $not NULL ";
-        } elsif (ref($$restrictions{$r})) { 
-            $select .= " AND $real $not IN (\$_$$\$" . join("\$_$$\$,\$_$$\$", @{$$restrictions{$r}}) . "\$_$$\$)";
+            for my $rkey (keys %$restrictions{$r}) {
+                $sel_str .= handle_wide_hold_restrictions($$restrictions{$r}{$rkey}, $real, $rkey);
+            }
+            $select .= $sel_str;
         } else {
-            $not = '!' if $not;
-            $select .= " AND $real $not= \$_$$\$$$restrictions{$r}\$_$$\$";
+            $select .= handle_wide_hold_restrictions($$restrictions{$r}, $real, '');
         }
 
         $restricted++;
@@ -2434,6 +2429,27 @@ SELECT  h.id, h.request_time, h.capture_time, h.fulfillment_time, h.checkin_time
 
     $client->respond_complete;
 }
+
+sub handle_wide_hold_restrictions {
+    my $restriction = shift;
+    my $real = shift;
+    my $rkey = shift;
+    my $rkey_str = '';
+
+    $rkey_str = $rkey if $rkey eq 'not';
+
+    if (!defined($restriction)) {
+        return " AND $real IS $rkey_str NULL ";
+    } elsif (ref($restriction)) {
+        return " AND $real $rkey_str IN (\$_$$\$" . join("\$_$$\$,\$_$$\$", @{$restriction}) . "\$_$$\$)";
+    } else {
+        $rkey_str = '!' if $rkey eq 'not';
+        $rkey_str = '>' if $rkey eq 'greater_than';
+        $rkey_str = '<' if $rkey eq 'less_than';
+        return " AND $real $rkey_str= \$_$$\$$restriction\$_$$\$";
+    }
+}
+
 __PACKAGE__->register_method(
     api_name        => 'open-ils.storage.action.live_holds.wide_hash',
     api_level       => 1,
index 14a6569..4d955d6 100644 (file)
@@ -2,7 +2,7 @@
   id-field="id"
   features="clientsort,allowAll"
   items-provider="gridDataProvider"
-  persist-key="circ.patron.holds"
+  persist-key="circ.patron.wide_holds"
   dateformat="{{$root.egDateAndTimeFormat}}">
 
   <eg-grid-menu-item handler="place_hold" 
   <eg-grid-menu-item handler="detail_view" 
     label="[% l('Detail View') %]"></eg-grid-menu-item>
 
-  <eg-grid-action handler="grid_actions.show_recent_circs"
+  <eg-grid-action handler="grid_actions.show_recent_circs_wide"
     label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.show_holds_for_title"
+  <eg-grid-action handler="grid_actions.show_holds_for_title_wide"
     label="[% l('Show Holds for Title') %]"></eg-grid-action>
   <eg-grid-action divider="true"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.set_copy_quality"
+  <eg-grid-action handler="grid_actions.set_copy_quality_wide"
     label="[% l('Set Desired Item Quality') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.edit_pickup_lib"
+  <eg-grid-action handler="grid_actions.edit_pickup_lib_wide"
     label="[% l('Edit Pickup Library') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.edit_notify_prefs"
+  <eg-grid-action handler="grid_actions.edit_notify_prefs_wide"
     label="[% l('Edit Notification Settings') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.edit_dates"
+  <eg-grid-action handler="grid_actions.edit_dates_wide"
     label="[% l('Edit Hold Dates') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.activate"
+  <eg-grid-action handler="grid_actions.activate_wide"
     label="[% l('Activate') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.suspend"
+  <eg-grid-action handler="grid_actions.suspend_wide"
     label="[% l('Suspend') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.set_top_of_queue"
+  <eg-grid-action handler="grid_actions.set_top_of_queue_wide"
     label="[% l('Set Top of Queue') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.clear_top_of_queue"
+  <eg-grid-action handler="grid_actions.clear_top_of_queue_wide"
     label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.transfer_to_marked_title"
+  <eg-grid-action handler="grid_actions.transfer_to_marked_title_wide"
     label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.mark_damaged"
+  <eg-grid-action handler="grid_actions.mark_damaged_wide"
     label="[% l('Mark Item Damaged') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.mark_missing"
+  <eg-grid-action handler="grid_actions.mark_missing_wide"
     label="[% l('Mark Item Missing') %]"></eg-grid-action>
   <eg-grid-action divider="true"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.retarget"
+  <eg-grid-action handler="grid_actions.retarget_wide"
     label="[% l('Find Another Target') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.cancel_hold" hide="hide_cancel_hold"
+  <eg-grid-action handler="grid_actions.cancel_wide_hold" hide="hide_cancel_hold"
     label="[% l('Cancel Hold') %]"></eg-grid-action>
-  <eg-grid-action handler="grid_actions.uncancel_hold" hide="hide_uncancel_hold"
+  <eg-grid-action handler="grid_actions.uncancel_wide_hold" hide="hide_uncancel_hold"
     label="[% l('Uncancel Hold') %]"></eg-grid-action>
 
   <eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
   <eg-grid-field label="[% l('Current Item') %]" 
     path='hold.current_copy.barcode'>
-    <a href="./cat/item/{{item.hold.current_copy().id()}}/summary" target="_self">
-      {{item.hold.current_copy().barcode()}}
+    <a href="./cat/item/{{item.hold.cp_id}}/summary" target="_self">
+      {{item.hold.cp_barcode}}
     </a>
   </eg-grid-field>
 
-  <eg-grid-field label="[% l('Circulation Modifier') %]" path="copy.circ_modifier" hidden></eg-grid-field>
-  <eg-grid-field label="[% l('Circulation Library') %]" path="copy.circ_lib.shortname" hidden></eg-grid-field>
-  <eg-grid-field label="[% l('Patron Barcode') %]" path="patron_barcode" hidden>{{item.patron_barcode}}</eg-grid-field>
-  <eg-grid-field label="[% l('Patron alias') %]" path="patron_alias" hidden>{{item.patron_alias}}</eg-grid-field>
+  <eg-grid-field label="[% l('Circulation Modifier') %]" path="hold.cp_circ_modifier" hidden></eg-grid-field>
+  <!--eg-grid-field label="[% l('Circulation Library') %]" path="hold.cp_circ_lib.shortname" hidden></eg-grid-field -->
+  <eg-grid-field label="[% l('Patron Barcode') %]" path="hold.usr_barcode" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Patron alias') %]" path="hold.usr_alias" hidden></eg-grid-field>
   <eg-grid-field label="[% l('Request Date') %]" path='hold.request_time' datatype="timestamp"></eg-grid-field>
   <eg-grid-field label="[% l('Capture Date') %]" path='hold.capture_time' datatype="timestamp"></eg-grid-field>
   <eg-grid-field label="[% l('Available Date') %]" path='hold.shelf_time' datatype="timestamp"></eg-grid-field>
   <eg-grid-field label="[% l('Hold Type') %]" path='hold.hold_type'></eg-grid-field>
-  <eg-grid-field label="[% l('Pickup Library') %]" path='hold.pickup_lib.shortname'></eg-grid-field>
+  <eg-grid-field label="[% l('Pickup Library') %]" path='hold.pl_shortname'></eg-grid-field>
 
-  <eg-grid-field label="[% l('Title') %]" path='mvr.title'>
-    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.mvr.doc_id()}}">
-      {{item.mvr.title()}}
+  <eg-grid-field label="[% l('Title') %]" path='hold.title'>
+    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.hold.record_id}}">
+      {{item.hold.title}}
     </a>
   </eg-grid-field>
 
-  <eg-grid-field label="[% l('Author') %]" path='mvr.author'></eg-grid-field>
-  <eg-grid-field label="[% l('Potential Items') %]" path='potential_copies'></eg-grid-field>
+  <eg-grid-field label="[% l('Author') %]" path='hold.author'></eg-grid-field>
+  <eg-grid-field label="[% l('Potential Items') %]" path='hold.potentials'></eg-grid-field>
   <eg-grid-field label="[% l('Status') %]" path='status_string'></eg-grid-field>
 
-  <eg-grid-field label="[% l('Queue Position') %]" path='queue_position' hidden></eg-grid-field>
-  <eg-grid-field label="[% l('Cancel Cause') %]" path='hold.cancel_cause.label' hidden></eg-grid-field>
-  <eg-grid-field path='hold.*' parent-idl-class="ahr" ignore="current_copy" hidden></eg-grid-field>
-  <eg-grid-field path='copy.*' parent-idl-class="acp" hidden></eg-grid-field>
-
-  <eg-grid-field path='hold.usr.id' parent-idl-class="ahr" label="[% l('User ID') %]" hidden></eg-grid-field>
-  <eg-grid-field path='hold.usr.usrname' parent-idl-class="ahr" label="[% l('Username') %]" hidden></eg-grid-field>
-  <eg-grid-field path='hold.usr.first_given_name' parent-idl-class="ahr" label="[% l('First Name') %]" hidden></eg-grid-field>
-  <eg-grid-field path='hold.usr.family_name' parent-idl-class="ahr" label="[% l('Last Name') %]" hidden></eg-grid-field>
-  <eg-grid-field path='hold.requestor.id' parent-idl-class="ahr" label="[% l('Requestor ID') %]" hidden></eg-grid-field>
-  <eg-grid-field path='hold.requestor.usrname' parent-idl-class="ahr" label="[% l('Requestor Username') %]" hidden></eg-grid-field>
-  <eg-grid-field path='hold.sms_carrier.name' parent-idl-class="ahr" label="[% l('Notifications SMS Carrier') %]" hidden></eg-grid-field>
-
-  <eg-grid-field path='part.label' parent-idl-class="bmp" label="[% l('Part') %]" hidden></eg-grid-field>
-  <eg-grid-field path='volume.*' parent-idl-class="acn" hidden></eg-grid-field>
-  <eg-grid-field path='mvr.*' parent-idl-class="mvr" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Queue Position') %]" path='hold.relative_queue_position' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Cancel Cause') %]" path='hold.cc_label' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('User ID') %]" path='hold.usr' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Username') %]" path='hold.usr_usrname' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('First Name') %]" path='hold.usr_first_given_name' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Last Name') %]" path='hold.usr_last_given_name' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Requestor ID') %]" path='hold.requestor' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Requestor Username') %]" path='hold.rusr_usrname' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Notifications SMS Carrier') %]" path='hold.sms_carrier' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Part') %]" path='hold.p_label' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Call Number Label') %]" path='hold.cn_label' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Call Number Sort Key') %]" path='hold.cn_label_sortkey' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Call Number/Volume ID') %]" path='hold.cn_id' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Create Date/Time') %]" path='hold.cn_create_date' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Is Deleted') %]" path='hold.cn_deleted' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Last Edit Date/Time') %]" path='hold.cn_edit_date' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Activation Date') %]" path='hold.thaw_datye' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Behind Desk') %]" path='hold.behind_desk' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Cancelation Note') %]" path='hold.cancel_note'hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Currently Frozen') %]" path='hold.frozen' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Fulfilling Staff') %]" path='hold.fulfillment_staff' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Fulfillment Date/Time') %]" path='hold.fulfillment_time' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Hold Cancel Date/Time') %]" path='hold.cancel_time' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Hold Expire Date/Time') %]" path='hold.expire_time' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Holdable Formats (for M-type hold)') %]" path='hold.holdable_formats' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Is Mint Condition') %]" path='hold.mint_condition' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Item Selection Depth') %]" path='hold.selection_depth' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Last Targeting Date/Time') %]" path='hold.prev_check_time' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Notifications Phone Number') %]" path='hold.phone_notify' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Notifications SMS Number') %]" path='hold.sms_notify' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Notify by Email?') %]" path='hold.email_notify' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Shelf Expire Time') %]" path='hold.shelf_expire_time' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Top of Queue') %]" path='hold.cut_in_line' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Active Date') %]" path='hold.cp_active_date' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Alert Message (deprecated)') %]" path='hold.cp_alert_message' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Barcode') %]" path='hold.cp_barcode' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Can Circulate') %]" path='hold.cp_circulate' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy ID') %]" path='hold.cp_id' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Number on Volume') %]" path='hold.cp_copy_number' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Status Change Time') %]" path='hold.cp_status_change_time' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Cost') %]" path='hold.cp_cost' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Creation Date/Time') %]" path='hold.cp_create_date' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Deposit Amount') %]" path='hold.cp_deposit_amount' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Dummy ISBN') %]" path='hold.cp_dummy_isbn' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Fine Level') %]" path='hold.cp_fine_level' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Deleted') %]" path='hold.cp_deleted' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Is Deposit Required') %]" path='hold.cp_deposit' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Is Holdable') %]" path='hold.cp_holdable' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Is Mint Condition') %]" path='hold.cp_mint_condition' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Is Reference') %]" path='hold.cp_ref' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Last Edit Date/Time') %]" path='hold.cp_edit_date' datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Loan Duration') %]" path='hold.cp_loan_duration' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Copy OPAC Visible') %]" path='hold.cp_opac_visible' datatype="bool" hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Precat Dummy Author') %]" path='hold.cp_dummy_author' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Precat Dummy Title') %]" path='hold.cp_dummy_title' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Price') %]" path='hold.cp_price' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Notify Count') %]" path='hold.notification_count' hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Last Notify Time') %]" path='hold.last_notification_time' datatype="timestamp" hidden></eg-grid-field>
 </eg-grid>
 
 <div class="flex-row pad-vert">
index c3ce75b..85b66b4 100644 (file)
@@ -4,9 +4,9 @@
 
 angular.module('egPatronApp').controller('PatronHoldsCtrl',
 
-       ['$scope','$q','$routeParams','egCore','egUser','patronSvc',
+       ['$scope','$q','$routeParams','egCore','egUser','patronSvc','egProgressDialog',
         'egGridDataProvider','egHolds','$window','$location','egCirc','egHoldGridActions',
-function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,  
+function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc, egProgressDialog,
         egGridDataProvider , egHolds , $window , $location , egCirc, egHoldGridActions) {
 
     $scope.initTab('holds', $routeParams.id);
@@ -18,6 +18,7 @@ function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,
         patronSvc.refreshPrimary();
         patronSvc.holds = [];
         patronSvc.hold_ids = [];
+        patronSvc.hold_count = 0;
         provider.refresh() 
     }
     $scope.grid_actions.refresh = refresh_all;
@@ -27,6 +28,7 @@ function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,
         $scope.holds_display = 'main';
         patronSvc.holds = [];
         patronSvc.hold_ids = [];
+        patronSvc.hold_count = 0;
         provider.refresh();
     }
 
@@ -35,6 +37,7 @@ function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,
         $scope.holds_display = 'alt';
         patronSvc.holds = [];
         patronSvc.hold_ids = [];
+        patronSvc.hold_count = 0;
         provider.refresh();
     }
 
@@ -49,22 +52,20 @@ function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,
     var provider = egGridDataProvider.instance({});
     $scope.gridDataProvider = provider;
 
-    function fetchHolds(offset, count) {
-        // TODO: LP#1697954 Fetch all holds on grid render to support
-        // client-side sorting.  Migrate to server-side sorting to avoid
-        // the need for fetching all items.
-
-        // we're going to just fetch all the holds up front
-        //var ids = patronSvc.hold_ids.slice(offset, offset + count); 
-        return egHolds.fetch_holds(patronSvc.hold_ids).then(null, null,
-            function(hold_data) { 
-                egCirc.flesh_copy_circ_library(hold_data.copy);
-                patronSvc.holds.push(hold_data);
-                return hold_data;
-            }
-        );
-    }
+    egCore.org.settings(['circ.holds.canceled.display_count']).then(function(set) {
+        if (set && set['circ.holds.canceled.display_count'])
+            $scope.canceled_display_count = set['circ.holds.canceled.display_count'];
+    });
+    egCore.org.settings(['circ.holds.canceled.display_age']).then(function(set) {
+        if (set && set['circ.holds.canceled.display_age'])
+            var d = new Date();
+        console.log(set['circ.holds.canceled.display_age']);
+            d.setSeconds(d.getSeconds() - egCore.date.intervalToSeconds(set['circ.holds.canceled.display_age']));
+            $scope.canceled_display_age = d.toISOString();
+    });
 
+    patronSvc.hold_ids = [];
+    var hold_count = 0;
     provider.get = function(offset, count) {
 
         // see if we have the requested range cached
@@ -72,71 +73,101 @@ function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,
             return provider.arrayNotifier(patronSvc.holds, offset, count);
         }
 
-        // see if we have the holds IDs for this range already loaded
-        if (patronSvc.hold_ids[offset]) {
-            return fetchHolds(offset, count);
+        patronSvc.hold_count = 0;
+        patronSvc.holds = [];
+        var restrictions = {
+            usr_id: $scope.patron_id,
+            fulfillment_time : null
+        };
+        var order_by = [];
+        var limit;
+
+        if ($scope.holds_display == 'alt') {
+            restrictions.cancel_time = {
+                not: null,
+                greater_than: $scope.canceled_display_age
+            };
+            order_by = [{cancel_time : {not: null}}];
+            limit = parseInt($scope.canceled_display_count);
+        } else {
+            restrictions.cancel_time = null;
+            order_by = [
+                {pickup_lib: {not: 'current_shelf_lib'}},
+                {shelf_time: {not: null}},
+                {frozen: {not: null}},
+                {request_time: {not : null}}],
+            limit = null;
         }
 
-        var deferred = $q.defer();
-        patronSvc.hold_ids = [];
-
-        var method = 'open-ils.circ.holds.id_list.retrieve.authoritative';
-        if ($scope.holds_display == 'alt')
-            method = 'open-ils.circ.holds.canceled.id_list.retrieve.authoritative';
-
-        var current = 0;
-        egCore.net.request(
-            'open-ils.circ', method,
-            egCore.auth.token(), $scope.patron_id
-
-        ).then(function(hold_ids) {
-            
-            if (!hold_ids.length || hold_ids.length < offset + 1)
-            {
-                deferred.resolve();
-                return;
+        egProgressDialog.open({max : 1, value : 0});
+        var first = true;
+        return egHolds.fetch_wide_holds(
+            restrictions,
+            order_by,
+            limit
+        ).then(function () {
+            return provider.arrayNotifier(patronSvc.holds, offset, count);
+        },
+        null,
+        function(hold_data) {
+            if (first) {
+                hold_count = hold_data;
+                first = false;
+                egProgressDialog.update({max:patronSvc.hold_count});
+            } else {
+                egProgressDialog.increment();
+                var new_item = { id : hold_data.id, hold : hold_data };
+                new_item.status_string =
+                    egCore.strings['HOLD_STATUS_' + hold_data.hold_status]
+                    || hold_data.hold_status;
+
+                patronSvc.holds.push(new_item);
             }
+        }).finally(egProgressDialog.close);
+    }
 
-            $scope.gridDataProvider.grid.totalCount = hold_ids.length;
-
-            patronSvc.hold_ids = hold_ids;
-            fetchHolds(offset, count)
-            .then(deferred.resolve, null, function (data) {
-                if (data) {
-                    if (current >= offset && current < count) {
-                        deferred.notify(data);
-                    }
-                    current++;
-                }
-            });
+    function map_prefix_to_subhash (h,pf) {
+        var newhash = {};
+        angular.forEach(Object.keys(h), function(k) {
+            if (k.startsWith(pf)) {
+                var nk = k.substr(pf.length);
+                newhash[nk] = h[k];
+            }
         });
-
-        return deferred.promise;
+        return newhash;
     }
 
     $scope.print = function() {
-        var holds = [];
-        angular.forEach(patronSvc.holds, function(item) {
-            holds.push({
-                hold : egCore.idl.toHash(item.hold),
-                copy : egCore.idl.toHash(item.copy),
-                volume : egCore.idl.toHash(item.volume),
-                title : item.mvr.title(),
-                author : item.mvr.author()
-            });
+        var print_holds = [];
+        angular.forEach(patronSvc.holds, function(hold_data) {
+            var phold = {};
+            print_holds.push(phold);
+            phold.status_string = hold_data.status_string;
+            phold.patron_first = hold_data.hold.usr.first_given_name;
+            phold.patron_last = hold_data.hold.usr_family_name;
+            phold.patron_alias = hold_data.hold.usr_alias;
+            phold.patron_barcode = hold_data.hold.ucard_barcode;
+
+            phold.title = hold_data.hold.title;
+            phold.author = hold_data.hold.author;
+
+            phold.hold = hold_data.hold;
+            phold.copy = map_prefix_to_subhash(hold_data.hold, 'cp_');
+            phold.volume = map_prefix_to_subhash(hold_data.hold, 'cn_');
+            phold.part = map_prefix_to_subhash(hold_data.hold, 'p_');
         });
 
         egCore.print.print({
             context : 'receipt', 
             template : 'holds_for_patron', 
-            scope : {holds : holds}
+            scope : {holds : print_holds}
         });
     }
 
     $scope.detail_view = function(action, user_data, items) {
         if (h = items[0]) {
             $location.path('/circ/patron/' + 
-                $scope.patron_id + '/holds/' + h.hold.id());
+                $scope.patron_id + '/holds/' + h.hold.id);
         }
     }
 
@@ -151,7 +182,7 @@ function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,
     // when the detail hold is fetched (and updated), update the bib
     // record summary display record id.
     $scope.set_hold = function(hold_data) {
-        $scope.detail_hold_record_id = hold_data.mvr.doc_id();
+        $scope.detail_hold_record_id = hold_data.hold.record_id;
     }
 
 }])
index 07e961e..5d1bdc0 100644 (file)
@@ -38,6 +38,7 @@ function($q , $timeout , $location , egCore,  egUser , egConfirmDialog , $locale
         service.items_out_ids = [];
         service.holds = [];
         service.hold_ids = [];
+        service.hold_count = 0;
         service.checkout_overrides = {};
         service.patron_stats = null;
         service.noncat_ids = [];