checkout responses
authorBill Erickson <berick@esilibrary.com>
Tue, 17 Jun 2014 16:52:16 +0000 (12:52 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 17 Jun 2014 16:52:16 +0000 (12:52 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/index.tt2
Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
Open-ILS/src/templates/staff/circ/share/circ_strings.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_copy_not_avail_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_event_override_dialog.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js
Open-ILS/web/js/ui/default/staff/circ/services/circ.js
Open-ILS/web/js/ui/default/staff/services/ui.js

index 65dbfd7..2102e77 100644 (file)
@@ -11,6 +11,7 @@
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/services/user.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/billing.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+[% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/app.js"></script>
 
 <!-- load the rest on demand? -->
@@ -29,6 +30,7 @@
 
 <script>
 angular.module('egCoreMod').run(['egStrings', function(s) {
+  console.log('HERE index');
   s.ANNOTATE_PAYMENT_MSG = "[% l('Please annotate this payment') %]";
   s.CONFIRM_REFUND_PAYMENT = 
     "[% |l('{{xactIds}}') -%]Are you sure you would like to refund excess payment on bills [_1]?  This action will simply put the amount in the Payment Pending column as a negative value.  You must still select Apply Payment!  Certain types of payments may not be refunded.  The refund may be applied to checked transactions that follow the refunded transaction.[% END %]";
index 21b6e2b..1edcf3d 100644 (file)
@@ -6,7 +6,8 @@
       <div class="input-group">
 
         <div class="input-group-btn" dropdown>
-          <button type="button" class="btn btn-default dropdown-toggle">
+          <button type="button" class="btn btn-default dropdown-toggle"
+            ng-class="{disabled : disable_checkout()}">
             {{selectedNcType() || "[% l('Barcode') %]"}}
             <span class="caret"></span>
           </button>
               [% l('Barcode') %]</a>
             </li>
             <li class="divider"></li>
-            <li><a href='' ng-repeat='type in nonCatTypes'
-              ng-click="checkoutArgs.noncat_type=type.id()">{{type.name()}}</a>
+            <li>
+              <a href ng-repeat='type in nonCatTypes'
+               ng-click="checkoutArgs.noncat_type=type.id()">{{type.name()}}</a>
             </li>
           </ul>
         </div>
 
         <input focus-me="focusMe" class="form-control"
           ng-model="checkoutArgs.copy_barcode" 
-          ng-disabled="checkoutArgs.noncat_type != 'barcode'"
+          ng-disabled="checkoutArgs.noncat_type != 'barcode' || disable_checkout()"
           id="patron-checkout-barcode" type="text"/> 
 
-        <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+        <input class="btn btn-default" type="submit" 
+          ng-class="{disabled : disable_checkout()}" value="[% l('Submit') %]"/>
 
       </div>
     </form>
diff --git a/Open-ILS/src/templates/staff/circ/share/circ_strings.tt2 b/Open-ILS/src/templates/staff/circ/share/circ_strings.tt2
new file mode 100644 (file)
index 0000000..5b86806
--- /dev/null
@@ -0,0 +1,16 @@
+[%# Strings for circ/services/circ.js %]
+
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+s.PATRON_CARD_INACTIVE=
+"[% l('The card used to retrieve this account is inactive and may not be used to circulate items.') %]";
+s.PATRON_INACTIVE=
+"[% l('This account is inactive and may not circulate items.') %]";
+s.PATRON_ACCOUNT_EXPIRED=
+"[% l('This account has expired and may not circulate items.') %]";
+s.CHECKOUT_FAILED_GENERIC=
+"[% l('Unable to checkout copy [_1] : [_2]', '{{barcode}}', '{{textcode}}') %]"
+}]);
+</script>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_copy_not_avail_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_copy_not_avail_dialog.tt2
new file mode 100644 (file)
index 0000000..711e777
--- /dev/null
@@ -0,0 +1,20 @@
+<div>
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Copy Not Available.') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="alert alert-warning">
+      [% l('Copy Status: [_1]', '{{copyStatus.name()}}') %]
+    </div>
+  </div>
+  <div class="modal-footer">
+    <input type="submit" class="btn btn-primary" ng-click="ok()"
+        value="[% l('Force this action?') %]"/>
+    <button class="btn btn-warning" 
+      ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
index 78f33f3..219848c 100644 (file)
@@ -13,7 +13,7 @@
     </div>
   </div>
   <div class="modal-footer">
-    <i>[% |l %]If overridden, subsequent checkouts during this patron's 
+    <i ng-if="auto_override">[% |l %]If overridden, subsequent checkouts during this patron's 
  session will auto-override this event[% END %]</i>
     <br/><br/>
     <input type="submit" class="btn btn-primary" 
index 5ca9b81..593198a 100644 (file)
@@ -23,6 +23,15 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc ,
         }
     });
 
+    $scope.disable_checkout = function() {
+        return (
+            !patronSvc.current ||
+            patronSvc.current.active() == 'f' ||
+            patronSvc.current.deleted() == 't' ||
+            patronSvc.current.card().active() == 'f'
+        );
+    }
+
     // avoid multiple, in-flight attempts on the same barcode
     var pending_barcodes = {};
 
@@ -116,7 +125,13 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc ,
             function() {
                 // Circ was rejected somewhere along the way.
                 // Remove the copy from the grid since there was no action.
-                $scope.checkouts.splice(row_item.index, 1);
+                // note: since checkouts are unshifted onto the array, the
+                // index value does not (generally) match the array position.
+                var pos = -1;
+                angular.forEach($scope.checkouts, function(co, idx) {
+                    if (co.index == row_item.index) pos = idx;
+                });
+                $scope.checkouts.splice(pos, 1);
                 $scope.gridDataProvider.refresh();
             }
 
index 1134afd..2ebebab 100644 (file)
@@ -11,14 +11,41 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
 
     var service = {
         // auto-override these events after the first override
-        checkout_overrides : {},
+        auto_override_checkout_events : {},
         org_addr_cache : {}
     };
 
     service.reset = function() {
-        service.checkout_overrides = {};
+        service.auto_override_checkout_events = {};
     }
 
+    // these events can be overridden by staff
+    service.overridable_events = [
+        'PATRON_EXCEEDS_OVERDUE_COUNT',
+        'PATRON_EXCEEDS_CHECKOUT_COUNT',
+        'PATRON_EXCEEDS_FINES',
+        'PATRON_BARRED',
+        'CIRC_EXCEEDS_COPY_RANGE',
+        'ITEM_DEPOSIT_REQUIRED',
+        'ITEM_RENTAL_FEE_REQUIRED',
+        'PATRON_EXCEEDS_LOST_COUNT',
+        'COPY_CIRC_NOT_ALLOWED',
+        'COPY_NOT_AVAILABLE', // HM?
+        'COPY_IS_REFERENCE',
+        'COPY_ALERT_MESSAGE',
+        'ITEM_ON_HOLDS_SHELF'                        
+    ]
+
+    // after the first override of any of these events, 
+    // auto-override them in subsequent calls.
+    service.auto_override_after_first = [
+        'PATRON_EXCEEDS_OVERDUE_COUNT',
+        'PATRON_BARRED',
+        'PATRON_EXCEEDS_LOST_COUNT',
+        'PATRON_EXCEEDS_CHECKOUT_COUNT',
+        'PATRON_EXCEEDS_FINES'
+    ]
+
     // 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).
@@ -95,6 +122,38 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         });
     }
 
+    service.handle_overridable_checkout_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();
+
+        } 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);
+            } 
+        }
+
+        // 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_NOT_AVAILABLE':
+                return service.copy_not_avail_dialog(evt, params, options);
+            default: 
+                return service.override_dialog(evt, params, options);
+        }
+    }
+
+    //TODO: copy_alert_dialog
+
     service.handle_checkout_resp = function(evt, params, options) {
 
         var final_resp = {evt : evt, params : params, options : options};
@@ -102,6 +161,11 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         // track the barcode regardless of whether it refers to a copy
         evt.copy_barcode = params.copy_barcode;
 
+        // Overridable Events
+        if (service.overridable_events.indexOf(evt.textcode) > -1) 
+            return service.handle_overridable_checkout_event(evt, params, options);
+
+        // Other events
         switch (evt.textcode) {
             case 'SUCCESS':
                 return $q.when(final_resp);
@@ -109,57 +173,30 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
             case 'ITEM_NOT_CATALOGED':
                 return service.precat_dialog(params, options);
 
-            case 'PATRON_EXCEEDS_OVERDUE_COUNT':
-            case 'PATRON_EXCEEDS_FINES':
-            case 'PATRON_EXCEEDS_CHECKOUT_COUNT':
-            case 'PATRON_EXCEEDS_LOST_COUNT':
-                if (options.override) {
-                    // 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);
-
-                } else {
-                    if (service.checkout_overrides[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);
-                    } else {
-                        // ask the user if they would like to override this
-                        // event type.
-                        return service.override_dialog(evt, params, options);
-                    }
-                }
-                break;
-
             case 'OPEN_CIRCULATION_EXISTS':
                 return service.circ_exists_dialog(evt, params, options);
 
             case 'COPY_IN_TRANSIT':
                 return service.copy_in_transit_dialog(evt, params, options);
 
-            /* stuff to consider 
+            case 'PATRON_CARD_INACTIVE':
+            case 'PATRON_INACTIVE':
+            case 'PATRON_ACCOUNT_EXPIRED':
+                return service.exit_alert(egCore.strings[evt.textcode]);
+
+            /* stuff yet to consider 
             PERM_FAILURE
-            PATRON_BARRED
-            CIRC_EXCEEDS_COPY_RANGE
-            PATRON_ACCOUNT_EXPIRED
-            ITEM_DEPOSIT_REQUIRED
-            ITEM_RENTAL_FEE_REQUIRED
-            ITEM_DEPOSIT_PAID
-            ACTION_CIRCULATION_NOT_FOUND
-            PATRON_EXCEEDS_CHECKOUT_COUNT
-            COPY_CIRC_NOT_ALLOWED
-            COPY_NOT_AVAILABLE
-            COPY_IS_REFERENCE
-            COPY_NEEDED_FOR_HOLD
-            MAX_RENEWALS_REACHED
             CIRC_CLAIMS_RETURNED
             COPY_ALERT_MESSAGE
             */
 
             default:
-                console.warn('unhandled circ response : ' + evt.textcode);
-                return $q.when(final_resp);
+                return service.exit_alert(
+                    egCore.strings.CHECKOUT_FAILED_GENERIC, {
+                        barcode : params.copy_barcode,
+                        textcode : evt.textcode
+                    }
+                );
         }
     }
 
@@ -207,6 +244,11 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         });
     }
 
+    service.exit_alert = function(msg, scope) {
+        return egAlertDialog.open(msg, scope).result.then(
+            function() {return $q.reject()});
+    }
+
     // opens a dialog asking the user if they would like to override
     // the returned event.
     service.override_dialog = function(evt, params, options) {
@@ -216,6 +258,8 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
                 ['$scope', '$modalInstance', 
                 function($scope, $modalInstance) {
                 $scope.evt = evt;
+                $scope.auto_override = 
+                    service.auto_override_after_first.indexOf(evt.textcode) > -1;
                 $scope.ok = function() { $modalInstance.close() }
                 $scope.cancel = function ($event) { 
                     $modalInstance.dismiss();
@@ -224,7 +268,32 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
             }]
         }).result.then(
             function() {
-                service.checkout_overrides[evt.textcode] = true;
+                if (service.auto_override_after_first.indexOf(evt.textcode) > -1)
+                    service.auto_override_checkout_events[evt.textcode] = true;
+                options.override = true;
+                return service.checkout(params, options);
+            }
+        );
+    }
+
+    service.copy_not_avail_dialog = function(evt, params, options) {
+        return $modal.open({
+            templateUrl: './circ/share/t_copy_not_avail_dialog',
+            controller: 
+                       ['$scope','$modalInstance','copyStatus',
+                function($scope , $modalInstance , copyStatus) {
+                $scope.copyStatus = copyStatus;
+                $scope.ok = function() {$modalInstance.close()}
+                $scope.cancel = function() {$modalInstance.dismiss()}
+            }],
+            resolve : {
+                copyStatus : function() {
+                    return egCore.pcrud.retrieve(
+                        'ccs', evt.payload.status());
+                }
+            }
+        }).result.then(
+            function() {
                 options.override = true;
                 return service.checkout(params, options);
             }
index 6278f98..6770fdc 100644 (file)
@@ -96,7 +96,7 @@ function($modal , $interpolate) {
                 function($scope, $modalInstance) {
                     $scope.message = $interpolate(message)(msg_scope);
                     $scope.ok = function() {
-                        if (msg_scope.ok) msg_scope.ok();
+                        if (msg_scope && msg_scope.ok) msg_scope.ok();
                         $modalInstance.close()
                     }
                 }