LP1749502 - Holds Pull List Print Order
[evergreen-equinox.git] / Open-ILS / web / js / ui / default / staff / circ / services / holds.js
index ab0b07d..dc6f0aa 100644 (file)
@@ -11,14 +11,19 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
 
     var service = {};
 
+    service.fetch_wide_holds = function(restrictions, order_by, limit, offset) {
+        return egCore.net.request(
+            'open-ils.circ',
+            'open-ils.circ.hold.wide_hash.stream',
+            egCore.auth.token(),
+            restrictions, order_by, limit, offset
+        );
+    }
+
     service.fetch_holds = function(hold_ids) {
         var deferred = $q.defer();
 
-        // FIXME: large batches using .authoritative result in many 
-        // stranded cstore backends on the server.  Needs investigation.
-        // For now, collect holds in a series of small batches.
-        // Fetch them serially both to avoid the above problem and
-        // to maintain order.
+        // Fetch hold details in batches for better UI responsiveness.
         var batch_size = 5;
         var index = 0;
 
@@ -37,7 +42,12 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
             egCore.net.request(
                 'open-ils.circ',
                 'open-ils.circ.hold.details.batch.retrieve.authoritative',
-                egCore.auth.token(), ids
+                egCore.auth.token(), ids, {
+                    include_current_copy : true,
+                    include_usr          : true,
+                    include_cancel_cause : true,
+                    include_requestor    : true
+                }
 
             ).then(
                 one_batch,  // kick off the next batch
@@ -60,6 +70,7 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
        
         return $uibModal.open({
             templateUrl : './circ/share/t_cancel_hold_dialog',
+            backdrop: 'static',
             controller : 
                 ['$scope', '$uibModalInstance', 'cancel_reasons',
                 function($scope, $uibModalInstance, cancel_reasons) {
@@ -114,6 +125,7 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
        
         return $uibModal.open({
             templateUrl : './circ/share/t_uncancel_hold_dialog',
+            backdrop: 'static',
             controller : 
                 ['$scope', '$uibModalInstance',
                 function($scope, $uibModalInstance) {
@@ -188,6 +200,7 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
         if (!hold_ids.length) return $q.when();
         return $uibModal.open({
             templateUrl : './circ/share/t_hold_copy_quality_dialog',
+            backdrop: 'static',
             controller : 
                 ['$scope', '$uibModalInstance',
                 function($scope, $uibModalInstance) {
@@ -211,6 +224,7 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
         if (!hold_ids.length) return $q.when();
         return $uibModal.open({
             templateUrl : './circ/share/t_hold_edit_pickup_lib',
+            backdrop: 'static',
             controller : 
                 ['$scope', '$uibModalInstance',
                 function($scope, $uibModalInstance) {
@@ -243,6 +257,7 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
         if (!hold_ids.length) return $q.when();
         return $uibModal.open({
             templateUrl : './circ/share/t_hold_notification_prefs',
+            backdrop: 'static',
             controller : 
                 ['$scope', '$uibModalInstance', 'sms_carriers',
                 function($scope, $uibModalInstance, sms_carriers) {
@@ -303,6 +318,7 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
 
         return $uibModal.open({
             templateUrl : './circ/share/t_hold_dates',
+            backdrop: 'static',
             controller : 
                 ['$scope', '$uibModalInstance',
                 function($scope, $uibModalInstance) {
@@ -448,28 +464,77 @@ function($uibModal , $q , egCore , egConfirmDialog , egAlertDialog) {
             || hold_data.status;
 
         var hold = hold_data.hold;
+        var volume = hold_data.volume;
         hold.pickup_lib(egCore.org.get(hold.pickup_lib()));
         hold.current_shelf_lib(egCore.org.get(hold.current_shelf_lib()));
         hold_data.id = hold.id();
 
-        if (hold.requestor() && typeof hold.requestor() != 'object')
+        // TODO: LP#1697954 fleshing calls below are deprecated in favor
+        // of API fleshing.
+
+        if (hold.requestor() && typeof hold.requestor() != 'object') {
+            console.debug('fetching hold requestor');
             egCore.pcrud.retrieve('au',hold.requestor()).then(function(u) { hold.requestor(u) });
+        }
 
-        if (hold.cancel_cause() && typeof hold.cancel_cause() != 'object')
+        if (hold.cancel_cause() && typeof hold.cancel_cause() != 'object') {
+            console.debug('fetching hold cancel cause');
             egCore.pcrud.retrieve('ahrcc',hold.cancel_cause()).then(function(c) { hold.cancel_cause(c) });
+        }
 
-        if (hold.usr() && typeof hold.usr() != 'object')
+        if (hold.usr() && typeof hold.usr() != 'object') {
+            console.debug('fetching hold user');
             egCore.pcrud.retrieve('au',hold.usr()).then(function(u) { hold.usr(u) });
+        }
 
         // current_copy is not always fleshed in the API
         if (hold.current_copy() && typeof hold.current_copy() != 'object') {
             hold.current_copy(hold_data.copy);
-            
+        }
+
+        if (hold.current_copy()) {
             // likewise, current_copy's status isn't fleshed in the API
             if(hold.current_copy().status() !== null &&
                typeof hold.current_copy().status() != 'object')
                 egCore.pcrud.retrieve('ccs',hold.current_copy().status()
                     ).then(function(c) { hold.current_copy().status(c) });
+        
+            // current_copy's shelving location position isn't always accessible
+            if (hold.current_copy().location()) {
+                //console.debug('fetching hold copy location order');
+                var location_id;
+                if (typeof hold.current_copy().location() != 'object') {
+                    location_id = hold.current_copy().location();
+                } else {
+                    location_id = hold.current_copy().location().id();
+                }
+                egCore.pcrud.search(
+                    'acplo',
+                    {location: location_id, org: egCore.auth.user().ws_ou()},
+                    null,
+                    {atomic:true}
+                ).then(function(orders) {
+                    if(orders[0]){
+                        hold_data.hold._copy_location_position = orders[0].position();
+                    } else {
+                        hold_data.hold._copy_location_position = 999;
+                    }
+                });
+            }
+
+            //Call number affixes are not always fleshed in the API
+            if (hold_data.volume.prefix) {
+                //console.debug('fetching call number prefix');
+                //console.log(hold_data.volume.prefix());
+                egCore.pcrud.retrieve('acnp',hold_data.volume.prefix())
+                .then(function(p) {hold_data.volume.prefix = p.label(); hold_data.volume.prefix_sortkey = p.label_sortkey()});
+            }
+            if (hold_data.volume.suffix) {
+                //console.debug('fetching call number suffix');
+                //console.log(hold_data.volume.suffix());
+                egCore.pcrud.retrieve('acns',hold_data.volume.suffix())
+                .then(function(s) {hold_data.volume.suffix = s.label(); hold_data.volume.suffix_sortkey = s.label_sortkey()});
+            }
         }
     }
 
@@ -502,6 +567,14 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
         return egHolds.cancel_holds(hold_ids).then(service.refresh);
     }
 
+    service.cancel_wide_hold = function(items) {
+        var hold_ids = items.filter(function(item) {
+            return !item.hold.cancel_time;
+        }).map(function(item) {return item.hold.id});
+
+        return egHolds.cancel_holds(hold_ids).then(service.refresh);
+    }
+
     service.uncancel_hold = function(items) {
         var hold_ids = items.filter(function(item) {
             return item.hold.cancel_time();
@@ -510,6 +583,14 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
         return egHolds.uncancel_holds(hold_ids).then(service.refresh);
     }
 
+    service.uncancel_wide_hold = function(items) {
+        var hold_ids = items.filter(function(item) {
+            return item.hold.cancel_time;
+        }).map(function(item) {return item.hold.id});
+
+        return egHolds.uncancel_holds(hold_ids).then(service.refresh);
+    }
+
     // jump to circ list for either 1) the targeted copy or
     // 2) the hold target copy for copy-level holds
     service.show_recent_circs = function(items) {
@@ -525,6 +606,21 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
         });
     }
 
+    // jump to circ list for either 1) the targeted copy or
+    // 2) the hold target copy for copy-level holds
+    service.show_recent_circs_wide = function(items) {
+        var focus = items.length == 1;
+        angular.forEach(items, function(item) {
+            if (item.hold.cp_id) {
+                var url = egCore.env.basePath +
+                          '/cat/item/' +
+                          item.hold.cp_id +
+                          '/circ_list';
+                $timeout(function() { var x = $window.open(url, '_blank'); if (focus) x.focus() });
+            }
+        });
+    }
+
     service.show_patrons = function(items) {
         var focus = items.length == 1;
         angular.forEach(items, function(item) {
@@ -536,6 +632,17 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
         });
     }
 
+    service.show_patrons_wide = function(items) {
+        var focus = items.length == 1;
+        angular.forEach(items, function(item) {
+            var url = egCore.env.basePath +
+                      'circ/patron/' +
+                      item.hold.usr_id +
+                      '/holds';
+            $timeout(function() { var x = $window.open(url, '_blank'); if (focus) x.focus() });
+        });
+    }
+
     service.show_holds_for_title = function(items) {
         var focus = items.length == 1;
         angular.forEach(items, function(item) {
@@ -547,6 +654,17 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
         });
     }
 
+    service.show_holds_for_title_wide = function(items) {
+        var focus = items.length == 1;
+        angular.forEach(items, function(item) {
+            var url = egCore.env.basePath +
+                      'cat/catalog/record/' +
+                      item.hold.record_id +
+                      '/holds';
+            $timeout(function() { var x = $window.open(url, '_blank'); if (focus) x.focus() });
+        });
+    }
+
 
     function generic_update(items, action) {
         if (!items.length) return $q.when();
@@ -554,6 +672,12 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
         return egHolds[action](hold_ids).then(service.refresh);
     }
 
+    function generic_update_wide(items, action) {
+        if (!items.length) return $q.when();
+        var hold_ids = items.map(function(item) {return item.hold.id});
+        return egHolds[action](hold_ids).then(service.refresh);
+    }
+
     service.set_copy_quality = function(items) {
         generic_update(items, 'set_copy_quality'); }
     service.edit_pickup_lib = function(items) {
@@ -573,18 +697,59 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
     service.transfer_to_marked_title = function(items) {
         generic_update(items, 'transfer_to_marked_title'); }
 
+    service.set_copy_quality_wide = function(items) {
+        generic_update_wide(items, 'set_copy_quality'); }
+    service.edit_pickup_lib_wide = function(items) {
+        generic_update_wide(items, 'edit_pickup_lib'); }
+    service.edit_notify_prefs_wide = function(items) {
+        generic_update_wide(items, 'edit_notify_prefs'); }
+    service.edit_dates_wide = function(items) {
+        generic_update_wide(items, 'edit_dates'); }
+    service.suspend_wide = function(items) {
+        generic_update_wide(items, 'suspend_holds'); }
+    service.activate_wide = function(items) {
+        generic_update_wide(items, 'activate_holds'); }
+    service.set_top_of_queue_wide = function(items) {
+        generic_update_wide(items, 'set_top_of_queue'); }
+    service.clear_top_of_queue_wide = function(items) {
+        generic_update_wide(items, 'clear_top_of_queue'); }
+    service.transfer_to_marked_title_wide = function(items) {
+        generic_update_wide(items, 'transfer_to_marked_title'); }
+
     service.mark_damaged = function(items) {
+        angular.forEach(items, function(item) {
+            if (item.copy) {
+                egCirc.mark_damaged({
+                    id: item.copy.id(),
+                    barcode: item.copy.barcode()
+                }).then(service.refresh);
+            }
+        });
+    }
+
+    service.mark_damaged_wide = function(items) {
+        angular.forEach(items, function(item) {
+            if (item.copy) {
+                egCirc.mark_damaged({
+                    id: item.hold.cp_id,
+                    barcode: item.hold.cp_barcode
+                }).then(service.refresh);
+            }
+        });
+    }
+
+    service.mark_missing = function(items) {
         var copy_ids = items
             .filter(function(item) { return Boolean(item.copy) })
             .map(function(item) { return item.copy.id() });
         if (copy_ids.length) 
-            egCirc.mark_damaged(copy_ids).then(service.refresh);
+            egCirc.mark_missing(copy_ids).then(service.refresh);
     }
 
-    service.mark_missing = function(items) {
+    service.mark_missing_wide = function(items) {
         var copy_ids = items
-            .filter(function(item) { return Boolean(item.copy) })
-            .map(function(item) { return item.copy.id() });
+            .filter(function(item) { return Boolean(item.hold.cp_id) })
+            .map(function(item) { return item.hold.cp_id });
         if (copy_ids.length) 
             egCirc.mark_missing(copy_ids).then(service.refresh);
     }
@@ -594,6 +759,11 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
         egHolds.retarget(hold_ids).then(service.refresh);
     }
 
+    service.retarget_wide = function(items) {
+        var hold_ids = items.map(function(item) { return item.hold.id });
+        egHolds.retarget(hold_ids).then(service.refresh);
+    }
+
     return service;
 }])
 
@@ -621,8 +791,12 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
                     egCore.net.request(
                         'open-ils.circ',
                         'open-ils.circ.hold.details.retrieve.authoritative',
-                        egCore.auth.token(), $scope.holdId
-
+                        egCore.auth.token(), $scope.holdId, {
+                            include_current_copy : true,
+                            include_usr          : true,
+                            include_cancel_cause : true,
+                            include_requestor    : true
+                        }
                     ).then(function(hold_data) { 
                         egHolds.local_flesh(hold_data);
     
@@ -673,6 +847,7 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
                 $scope.new_note = function() {
                     return $uibModal.open({
                         templateUrl : './circ/share/t_hold_note_dialog',
+                        backdrop: 'static',
                         controller : 
                             ['$scope', '$uibModalInstance',
                             function($scope, $uibModalInstance) {
@@ -703,6 +878,7 @@ function($window , $location , $timeout , egCore , egHolds , egCirc) {
                 $scope.new_notification = function() {
                     return $uibModal.open({
                         templateUrl : './circ/share/t_hold_notification_dialog',
+                        backdrop: 'static',
                         controller : 
                             ['$scope', '$uibModalInstance',
                             function($scope, $uibModalInstance) {