items out -> claims returned
authorBill Erickson <berick@esilibrary.com>
Tue, 1 Jul 2014 18:03:50 +0000 (14:03 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 1 Jul 2014 18:03:50 +0000 (14:03 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/t_items_out.tt2
Open-ILS/src/templates/staff/circ/share/circ_strings.tt2
Open-ILS/src/templates/staff/circ/share/t_mark_claims_returned_dialog.tt2 [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/app.js
Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js
Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js
Open-ILS/web/js/ui/default/staff/circ/services/circ.js

index f23e719..c4c3fb6 100644 (file)
     handler="mark_lost"
     label="[% l('Mark Lost (By Patron)') %]">
   </eg-grid-action>
+  <eg-grid-action 
+    handler="mark_claims_returned"
+    label="[% l('Mark Claims Returned') %]">
+  </eg-grid-action>
 
   <eg-grid-field label="[% l('Circ ID') %]" path='id'></eg-grid-field>
   <eg-grid-field label="[% l('Barcode') %]" path='target_copy.barcode'>
index bccc9d4..8f77b44 100644 (file)
@@ -28,6 +28,8 @@ s.ABORT_TRANSIT_CONFIRM = '[% l("Abort {{num_transits}} transits?") %]';
 s.ROUTE_TO_HOLDS_SHELF = '[% l("Holds Shelf") %]';
 s.ROUTE_TO_CATALOGING = '[% l("Cataloging") %]';
 s.COPY_IN_TRANSIT = '[% l("Copy is In-Transit") %]';
+s.TOO_MANY_CLAIMS_RETURNED = 
+  '[% l("Patron exceeds claims returned count.  Force this action?") %]';
 }]);
 </script>
 
diff --git a/Open-ILS/src/templates/staff/circ/share/t_mark_claims_returned_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_mark_claims_returned_dialog.tt2
new file mode 100644 (file)
index 0000000..858e242
--- /dev/null
@@ -0,0 +1,25 @@
+<div class="modal-header">
+  <button type="button" class="close" 
+    ng-click="cancel()" aria-hidden="true">&times;</button>
+  <h4 class="modal-title">
+    [% l('Mark Item(s) Claims Returned') %]
+  </h4>
+</div>
+<div class="modal-body">
+  <div class="pad-vert row">
+    <div class="col-md-12">
+      [% l('Enter claims returned date for items: [_1]', 
+        '{{args.barcodes.toString()}}') %]
+    </div>
+  </div>
+  <div class="pad-vert row">
+    <div class="col-md-5">
+      <input eg-date-input required 
+        class="form-control" ng-model="args.date"/>
+    </div>
+  </div>
+</div>
+<div class="modal-footer">
+  <button class="btn btn-primary" ng-click="ok()">[% l('Submit') %]</button>
+  <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+</div>
index 86a762d..2b04291 100644 (file)
@@ -24,8 +24,15 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap',
             return egCore.org.settings([
                 'circ.obscure_dob',
                 'ui.circ.show_billing_tab_on_bills',
-                'circ.patron_expires_soon_warning'
-            ]).then(function(settings) { egCore.env.aous = settings });
+                'circ.patron_expires_soon_warning',
+                'ui.circ.items_out.lost',
+                'ui.circ.items_out.longoverdue',
+                'ui.circ.items_out.claimsreturned'
+            ]).then(function(settings) { 
+                // local settings are cached within egOrg.  Caching them
+                // again in egEnv just simplifies the syntax for access.
+                egCore.env.aous = settings;
+            });
         }
 
         // local stat cats are displayed in the summary bar on each page.
index 89e211f..5ee1bc5 100644 (file)
@@ -115,7 +115,8 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc ,
             function(co_resp) {
                 // update stats locally so we don't have to fetch them w/
                 // each checkout.
-                patronSvc.patron_stats.checkouts.out++
+                patronSvc.patron_stats.checkouts.out++;
+                patronSvc.patron_stats.checkouts.total_out++;
 
                 // copy the response event into the original grid row item
                 // note: angular.copy clobbers the destination
index ffa9d05..d790570 100644 (file)
@@ -11,19 +11,18 @@ function($scope,  $q,  $routeParams,  egCore , egUser,  patronSvc ,
 
     $scope.initTab('items_out', $routeParams.id);
 
-    var display_lost, display_lo, display_cr;
-
-    // items out display settings
-    // NOTE:  
-    egCore.org.settings([
-        'ui.circ.items_out.lost',
-        'ui.circ.items_out.longoverdue',
-        'ui.circ.items_out.claimsreturned'])
-    .then(function(set) {
-        display_lost = Number(set['ui.circ.items_out.lost']) || 2;
-        display_lo   = Number(set['ui.circ.items_out.longoverdue']) || 2;
-        display_cr   = Number(set['ui.circ.items_out.claimsreturned']) || 2;
-    });
+    patronSvc.items_out = []; 
+    patronSvc.items_out_ids = [];
+
+    // Items out display settings.  These are laoded in .configure().
+    // NOTE: UI only supports one list, so anything configured to show
+    // in the 'bottom' list will not presently display.
+    var display_lost = Number(
+        egCore.env.aous['ui.circ.items_out.lost']) || 2;
+    var display_lo = Number(
+        egCore.env.aous['ui.circ.items_out.longoverdue']) || 1;
+    var display_cr = Number(
+        egCore.env.aous['ui.circ.items_out.claimsreturned']) || 1;
 
     var provider = egGridDataProvider.instance({});
     $scope.gridDataProvider = provider;
@@ -239,5 +238,25 @@ function($scope,  $q,  $routeParams,  egCore , egUser,  patronSvc ,
         });
     }
 
+    $scope.mark_claims_returned = function(items) {
+        if (!items.length) return;
+
+        var barcodes = items.map(function(circ) {
+            return circ.target_copy().barcode()
+        });
+
+        egCirc.mark_claims_returned_dialog(barcodes)
+        .then(function() { 
+            // reload the user to pick up changes in items out, fines, etc.
+            patronSvc.refreshPrimary();
+
+            // reload circs since LOST items may no longer be applicable
+            // for display.
+            patronSvc.items_out = []; 
+            patronSvc.items_out_ids = [];
+            provider.refresh() 
+        });
+    }
+
 }]);
 
index 8998b52..5238a56 100644 (file)
@@ -858,6 +858,95 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         }).result;
     }
 
+    service.mark_claims_returned = function(barcode, date, override) {
+
+        var method = 'open-ils.circ.circulation.set_claims_returned';
+        if (override) method += '.override';
+
+        console.debug('claims returned ' + method);
+
+        return egCore.net.request(
+            'open-ils.circ', method, egCore.auth.token(),
+            {barcode : barcode, backdate : date})
+
+        .then(function(resp) {
+
+            if (resp == 1) { // success
+                console.debug('claims returned succeeded for ' + barcode);
+                return barcode;
+
+            } else if (evt = egCore.evt.parse(resp)) {
+                console.debug('claims returned failed: ' + evt.toString());
+
+                if (evt.textcode == 'PATRON_EXCEEDS_CLAIMS_RETURN_COUNT') {
+                    // TODO check perms before offering override option?
+
+                    if (override) return;// just to be safe
+
+                    return egConfirmDialog.open(
+                        egCore.strings.TOO_MANY_CLAIMS_RETURNED, '', {}
+                    ).result.then(function() {
+                        return service.mark_claims_returned(barcode, date, true);
+                    });
+                }
+
+                if (evt.textcode == 'PERM_FAILURE') {
+                    console.error('claims returned permission denied')
+                    // TODO: auth override dialog?
+                }
+            }
+        });
+    }
+
+    service.mark_claims_returned_dialog = function(copy_barcodes) {
+        if (!copy_barcodes.length) return;
+
+        return $modal.open({
+            templateUrl: './circ/share/t_mark_claims_returned_dialog',
+            controller: 
+                       ['$scope','$modalInstance',
+                function($scope , $modalInstance) {
+
+                var today = new Date();
+                $scope.args = {
+                    barcodes : copy_barcodes,
+                    date : today
+                };
+
+                $scope.$watch('args.date', function(newval) {
+                    if (newval && newval > today) 
+                        $scope.args.backdate = today;
+                });
+
+                $scope.cancel = function() {$modalInstance.dismiss()}
+                $scope.ok = function() { 
+
+                    var date = $scope.args.date.toISOString().replace(/T.*/,'');
+
+                    var deferred = $q.defer();
+
+                    // serialize the action on each barcode so that the 
+                    // caller will never see multiple alerts at the same time.
+                    function mark_one() {
+                        var bc = copy_barcodes.pop();
+                        if (!bc) {
+                            deferred.resolve();
+                            $modalInstance.close();
+                            return;
+                        }
+                        service.mark_claims_returned(bc, date)
+                        .then(function(barcode) {
+                            if (barcode) deferred.notify(barcode);
+                            mark_one();
+                        });
+                    }
+                    mark_one(); // kick it off
+                    return deferred.promise;
+                }
+            }]
+        }).result;
+    }
+
     service.mark_damaged = function(copy_ids) {
         return egConfirmDialog.open(
             egCore.strings.MARK_DAMAGED_CONFIRM, '',