checkin
authorBill Erickson <berick@esilibrary.com>
Tue, 24 Jun 2014 20:55:54 +0000 (16:55 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 24 Jun 2014 20:55:54 +0000 (16:55 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/share/circ_strings.tt2
Open-ILS/web/js/ui/default/staff/circ/checkin/app.js
Open-ILS/web/js/ui/default/staff/circ/services/circ.js
Open-ILS/web/js/ui/default/staff/services/idl.js

index 47d09f8..d317a48 100644 (file)
@@ -20,6 +20,9 @@ s.PERMISSION_DENIED =
   '[% l('Permission Denied : [_1]', '{{permission}}') %]';
 s.PRECAT_CHECKIN_MSG = 
   '[% l("This item needs to be routed to CATALOGING") %]';
+s.LOCATION_ALERT_MSG =
+  '[% l("Item [_1] needs to be routed to [_2]", 
+    "{{copy.barcode()}}","{{copy.location().name()}}") %]';
 }]);
 </script>
 
index 009b915..6d21dd8 100644 (file)
@@ -20,13 +20,7 @@ angular.module('egCheckinApp', ['ngRoute', 'ui.bootstrap',
        ['$scope','$q','egCore','checkinSvc','egGridDataProvider','egCirc',
 function($scope , $q , egCore , checkinSvc , egGridDataProvider , egCirc)  {
 
-    // run egCore.startup here since it's not handled via resolver
-    egCore.startup.go().then(
-        function() {
-            // handle post-startup business
-        }
-    );
-
+    var suppress_popups = false;
     var today = new Date();
     var seen_barcodes = {};
     $scope.focusMe = true;
@@ -35,6 +29,19 @@ function($scope , $q , egCore , checkinSvc , egGridDataProvider , egCirc)  {
     $scope.using_hatch = egCore.hatch.usingHatch();
     $scope.modifiers = {};
 
+    // run egCore.startup here since it's not handled via resolver
+    egCore.startup.go().then(
+        function() {
+            // handle post-startup business
+            egCore.org.settings([
+                'ui.circ.suppress_checkin_popups' // more will likely follow..
+            ])
+            .then(function(set) {
+                suppress_popups = set['ui.circ.suppress_checkin_popups'];
+            });
+        }
+    );
+
     // ensure the backdate is not in the future
     // note: input type=date max=foo not yet supported anywhere
     $scope.$watch('checkinArgs.backdate', function(newval) {
@@ -87,7 +94,8 @@ function($scope , $q , egCore , checkinSvc , egGridDataProvider , egCirc)  {
             check_barcode : $scope.strict_barcode,
             no_precat_alert : $scope.modifiers.no_precat_alert,
             auto_print_holds_transits : 
-                $scope.modifiers.auto_print_holds_transits
+                $scope.modifiers.auto_print_holds_transits,
+            suppress_popups : suppress_popups
         };
 
         return {params : params, options: options};
@@ -105,7 +113,6 @@ function($scope , $q , egCore , checkinSvc , egGridDataProvider , egCirc)  {
         if (!params.copy_barcode) return;
 
         if (seen_barcodes[params.copy_barcode]) {
-            // TODO: UI
             $scope.already_checked_in = params.copy_barcode;
             return;
         }
index 6a9e0fe..5182527 100644 (file)
@@ -12,15 +12,15 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
     var service = {
         // auto-override these events after the first override
         auto_override_checkout_events : {},
-        org_addr_cache : {}
+        org_addr_cache : {} // TODO: use egEnv
     };
 
     service.reset = function() {
         service.auto_override_checkout_events = {};
     }
 
-    // these events can be overridden by staff
-    service.overridable_events = [
+    // these events can be overridden by staff during checkout
+    service.checkout_overridable_events = [
         'PATRON_EXCEEDS_OVERDUE_COUNT',
         'PATRON_EXCEEDS_CHECKOUT_COUNT',
         'PATRON_EXCEEDS_FINES',
@@ -33,12 +33,12 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         'COPY_NOT_AVAILABLE',
         'COPY_IS_REFERENCE',
         'COPY_ALERT_MESSAGE',
-        'ITEM_ON_HOLDS_SHELF'                        
+        'ITEM_ON_HOLDS_SHELF'                 
     ]
 
     // after the first override of any of these events, 
     // auto-override them in subsequent calls.
-    service.auto_override_after_first = [
+    service.checkout_auto_override_after_first = [
         'PATRON_EXCEEDS_OVERDUE_COUNT',
         'PATRON_BARRED',
         'PATRON_EXCEEDS_LOST_COUNT',
@@ -46,6 +46,28 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         'PATRON_EXCEEDS_FINES'
     ]
 
+    // these checkin events do not produce alerts when 
+    // options.suppress_alerts is in effect.
+    service.checkin_suppress_overrides = [
+        'COPY_BAD_STATUS',
+        'PATRON_BARRED',
+        'PATRON_INACTIVE',
+        'PATRON_ACCOUNT_EXPIRED',
+        'ITEM_DEPOSIT_PAID',
+        'CIRC_CLAIMS_RETURNED',
+        'COPY_ALERT_MESSAGE',
+        'COPY_STATUS_LOST',
+        'COPY_STATUS_LONG_OVERDUE',
+        'COPY_STATUS_MISSING',
+        'PATRON_EXCEEDS_FINES'
+    ]
+
+    // these events can be overridden by staff during checkin
+    service.checkin_overridable_events = 
+        service.checkin_suppress_overrides.concat([
+        'TRANSIT_CHECKIN_INTERVAL_BLOCK'
+    ])
+
     // Performs a checkout.
     // Returns a promise resolved with the original params and options
     // and the final checkout event (e.g. in the case of override).
@@ -77,8 +99,7 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
 
                 if (angular.isArray(evt)) evt = evt[0];
 
-                return service.flesh_response_data(
-                    'checkout', evt, params, options)
+                return service.flesh_response_data('checkout', evt, params, options)
                 .then(function() {
                     return service.handle_checkout_resp(evt, params, options);
                 })
@@ -159,14 +180,14 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
             console.debug('override failed: ' + evt.textcode);
             return $q.reject();
 
-        } else {
-            if (service.auto_override_checkout_events[evt.textcode]) {
-                // user has already opted to override this type
-                // of event.  Re-run the checkout w/ override.
-                options.override = true;
-                return service.checkout(params, options);
-            } 
-        }
+        } 
+
+        if (service.auto_override_checkout_events[evt.textcode]) {
+            // user has already opted to override this type
+            // of event.  Re-run the checkout w/ override.
+            options.override = true;
+            return service.checkout(params, options);
+        } 
 
         // Ask the user if they would like to override this event.
         // Some events offer a stock override dialog, while others
@@ -182,6 +203,37 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         }
     }
 
+    service.handle_overridable_checkin_event = function(evt, params, options) {
+
+        if (options.override) {
+            // override attempt already made and failed.
+            // NOTE: I don't think we'll ever get here, since the
+            // override attempt should produce a perm failure...
+            console.debug('override failed: ' + evt.textcode);
+            return $q.reject();
+
+        } 
+
+        if (options.suppress_checkin_popups
+            && service.checkin_suppress_overrides.indexOf(evt.textcode) > -1) {
+            // Event is suppressed.  Re-run the checkin w/ override.
+            options.override = true;
+            return service.checkin(params, options);
+        } 
+
+        // Ask the user if they would like to override this event.
+        // Some events offer a stock override dialog, while others
+        // require additional context.
+
+        switch(evt.textcode) {
+            case 'COPY_ALERT_MESSAGE':
+                return service.copy_alert_dialog(evt, params, options, 'checkin');
+            default: 
+                return service.override_dialog(evt, params, options);
+        }
+    }
+
+
     service.handle_checkout_resp = function(evt, params, options) {
 
         var final_resp = {evt : evt, params : params, options : options};
@@ -190,7 +242,7 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         evt.copy_barcode = params.copy_barcode;
 
         // Overridable Events
-        if (service.overridable_events.indexOf(evt.textcode) > -1) 
+        if (service.checkout_overridable_events.indexOf(evt.textcode) > -1) 
             return service.handle_overridable_checkout_event(evt, params, options);
 
         // Other events
@@ -309,6 +361,7 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
 
 
     // fetch/cache for org unit addresses
+    // TODO: use egEnv instead
     service.get_org_addr = function(org_id, addr_type) {
         if (service.org_addr_cache[org_id]) {
             if (service.org_addr_cache[org_id][addr_type]) 
@@ -339,7 +392,7 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
                 function($scope, $modalInstance) {
                 $scope.evt = evt;
                 $scope.auto_override = 
-                    service.auto_override_after_first.indexOf(evt.textcode) > -1;
+                    service.checkout_auto_override_after_first.indexOf(evt.textcode) > -1;
                 $scope.ok = function() { $modalInstance.close() }
                 $scope.cancel = function ($event) { 
                     $modalInstance.dismiss();
@@ -348,7 +401,7 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
             }]
         }).result.then(
             function() {
-                if (service.auto_override_after_first.indexOf(evt.textcode) > -1)
+                if (service.checkout_auto_override_after_first.indexOf(evt.textcode) > -1)
                     service.auto_override_checkout_events[evt.textcode] = true;
                 options.override = true;
                 return service.checkout(params, options);
@@ -567,6 +620,23 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         );
     }
 
+
+    // alert when copy location alert_message is set.
+    // This does not affect processing, it only produces a click-through
+    service.handle_checkin_loc_alert = function(evt, params, options) {
+
+        var copy = evt && evt.payload ? evt.payload.copy : null;
+
+        if (copy && !options.suppress_checkin_popups
+            && copy.location().checkin_alert() == 't') {
+
+            return egAlertDialog.open(
+                egCore.strings.LOCATION_ALERT_MSG, {copy : copy}).result;
+        }
+
+        return $q.when();
+    }
+
     service.handle_checkin_resp = function(evt, params, options) {
 
         var final_resp = {evt : evt, params : params, options : options};
@@ -578,11 +648,14 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
             transit = evt.payload.transit;
         }
 
-        // track the barcode regardless of whether it refers to a copy
+        // track the barcode regardless of whether it's valid
         evt.copy_barcode = params.copy_barcode;
 
         console.debug('checkin event ' + evt.textcode);
 
+        if (service.checkin_overridable_events.indexOf(evt.textcode) > -1) 
+            return service.handle_overridable_checkin_event(evt, params, options);
+
         switch (evt.textcode) {
             case 'SUCCESS':
             case 'NO_CHANGE':
@@ -598,7 +671,10 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
                     ).then(function() { return final_resp });
 
                 } else {
-                    return $q.when(final_resp);
+
+                    // see if the copy location is configured to alert
+                    return service.handle_checkin_loc_alert(evt, params, options)
+                    .then(function() {return final_resp});
                 }
                 
             case 'ROUTE_ITEM':
@@ -619,10 +695,6 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
                     egCore.strings.PRECAT_CHECKIN_MSG, params)
                     .result.then(function() {return final_resp});
 
-            case 'COPY_ALERT_MESSAGE':
-                return service.copy_alert_dialog(evt, params, options, 'checkin');
-
-
             default:
                 console.warn('unhandled checkin response : ' + evt.textcode);
                 return $q.when(final_resp);
index 5d4d5af..5934063 100644 (file)
@@ -74,29 +74,39 @@ angular.module('egCoreMod')
      * e.g.  {"call_number.label" : "foo"}
      */
     service.toHash = function(obj, flatten) {
-        if (!obj) return null;
+        if (!angular.isObject(obj)) return obj; // arrays are objects
+
+        if (angular.isArray(obj)) { // NOTE: flatten arrays not supported
+            return obj.map(function(item) {return service.toHash(item)});
+        }
+
+        var field_names = obj.classname ? 
+            Object.keys(service.classes[obj.classname].field_map) :
+            Object.keys(obj);
+
         var hash = {};
         angular.forEach(
-            service.classes[obj.classname].fields, 
+            field_names,
             function(field) { 
-                var val = obj[field.name]();
-                if (val === null || val === undefined) return;
-
-                if (angular.isObject(val) && val._isfieldmapper) {
-                    if (flatten) {
-                        var subhash = service.toHash(val, true);
-                        angular.forEach(subhash, function(val, key) {
-                            var fname = field.name + '.' + key;
-                            hash[fname] = val;
-                        });
-                    } else {
-                        hash[field.name] = service.toHash(val);
-                    }
-                } else {
-                    hash[field.name] = val;
+
+                var val = service.toHash(
+                    angular.isFunction(obj[field]) ? 
+                        obj[field]() : obj[field], 
+                    flatten
+                );
+
+                if (flatten && angular.isObject(val)) {
+                    angular.forEach(val, function(sub_val, key) {
+                        var fname = field + '.' + key;
+                        hash[fname] = sub_val;
+                    });
+
+                } else if (val !== undefined) {
+                    hash[field] = val;
                 }
             }
-        )
+        );
+
         return hash;
     }