checkin cont.
authorBill Erickson <berick@esilibrary.com>
Tue, 24 Jun 2014 16:13:25 +0000 (12:13 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 24 Jun 2014 16:13:25 +0000 (12:13 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/checkin/index.tt2
Open-ILS/src/templates/staff/circ/checkin/t_checkin_table.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/env.js
Open-ILS/web/js/ui/default/staff/services/grid.js

index a63fb16..63e4773 100644 (file)
   </div>
 </div>
 
+<div ng-if="already_checked_in" class="col-md-6 alert alert-danger">
+  [% l('[_1] was already checked in.', '{{already_checked_in}}') %]
+</div>
+
 <hr/>
 
 [% INCLUDE 'staff/circ/checkin/t_checkin_table.tt2' %]
index 0016662..1d74a9c 100644 (file)
@@ -8,29 +8,55 @@
   grid-controls="gridControls"
   persist-key="circ.checkin">
 
-  <eg-grid-field label="[% l('Circ ID') %]"     
-    path='payload.circ.id'></eg-grid-field>
-
-  <eg-grid-field label="[% l('Barcode') %]" path="copy_barcode">
-    <!-- wth... ng-if / ng-disabled not working here.
-      i want to hide / disable the href when there is no copy ID -->
-      <a href="./cat/item/{{item.payload.copy.id()}}/summary" target="_self">
-        {{item.copy_barcode}}
-      </a>
+  <eg-grid-field label="[% l('Alert Msg') %]"   
+    path="acp.alert_message"></eg-grid-field>
+
+  <eg-grid-field label="[% l('Balance Owed') %]"     
+    path='circ.billable_transaction.summary.balance_owed'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Barcode') %]" path="acp_barcode">
+    <!-- FIXME: ng-if / ng-disabled not working since the contents 
+        are $interpolate'd and not $compile'd.
+        I want to hide / disable the href when there is no acp ID 
+    -->
+    <a href="./cat/item/{{item.acp.id()}}/summary" target="_self">
+      {{item.copy_barcode}}
+    </a>
   </eg-grid-field>
 
-  <eg-grid-field label="[% l('Due Date') %]"    
-    path='payload.circ.due_date' datatype="timestamp"></eg-grid-field>
-  <eg-grid-field label="[% l('Response Code') %]"    
-    path="textcode"></eg-grid-field>
+  <eg-grid-field label="[% l('Bill #') %]"     
+    path='circ.id'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Checkin Date') %]"    
+    path='circ.checkin_time'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Family Name') %]"    
+    path='au.family_name'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Finish') %]"    
+    path='circ.stop_fines_time'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Location') %]"    
+    path='acp.location.name'></eg-grid-field>
+
+  <!-- FIXME: CATALOGING, HOLDS SHELF, acp LOCATION -->
+  <eg-grid-field label="[% l('Route To') %]" path='route_to'>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Start') %]"    
+    path='circ.xact_start'></eg-grid-field>
+
   <eg-grid-field label="[% l('Title') %]"       
-    path="payload.record.title"></eg-grid-field>
+    path="mvr.title"></eg-grid-field>
+
+  <eg-grid-field label="[% l('Due Date') %]"    
+    path='circ.due_date' hidden></eg-grid-field>
+
   <eg-grid-field label="[% l('Author') %]"      
-    path="payload.record.author"></eg-grid-field>
+    path="mvr.author" hidden></eg-grid-field>
+
   <eg-grid-field label="[% l('Call Number') %]" 
-    path="payload.copy.call_number.label"></eg-grid-field>
-  <eg-grid-field label="[% l('Alert Msg') %]"   
-    path="payload.copy.alert_message"></eg-grid-field>
+    path="acn.label" hidden></eg-grid-field>
 
   <!-- TODO: add support for wildcard fields sans idl-class -->
 </eg-grid>
index fc2cee0..52b5bf0 100644 (file)
@@ -28,6 +28,7 @@ function($scope , $q , egCore , checkinSvc , egGridDataProvider , egCirc)  {
     );
 
     var today = new Date();
+    var seen_barcodes = {};
     $scope.focusMe = true;
     $scope.checkins = checkinSvc.checkins;
     $scope.checkinArgs = {backdate : today}
@@ -103,6 +104,15 @@ 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;
+        }
+
+        seen_barcodes[params.copy_barcode] = true;
+        delete $scope.already_checked_in;
+
         var row_item = {
             index : checkinSvc.checkins.length,
             copy_barcode : params.copy_barcode
@@ -115,14 +125,32 @@ function($scope , $q , egCore , checkinSvc , egGridDataProvider , egCirc)  {
         egCirc.checkin(params, options).then(
         function(final_resp) {
 
-            // copy the response event into the original grid row item
-            // note: angular.copy clobbers the destination
-            angular.forEach(final_resp.evt, function(v, k) {
-                row_item[k] = v;
-            });
+            var payload = final_resp.evt.payload;
+
+            if (payload) {
+                row_item.circ = payload.circ;
+                row_item.mbts = payload.circ ?
+                    payload.circ.billable_transaction().summary() : null;
+                row_item.mvr = payload.record;
+                row_item.acp = payload.copy;
+                row_item.acn = payload.volume ? 
+                    payload.volume : payload.copy.call_number();
+                row_item.au = payload.patron;
+                row_item.status = payload.status;
+                row_item.message = payload.message;
+            }
 
-            if (checkinSvc.checkins.length > 20)
+            // TODO
+            //row_item.route_to 
+
+            if ($scope.trim_list && checkinSvc.checkins.length > 20)
                 checkinSvc.checkins = checkinSvc.checkins.splice(0, 20);
+
+            return egCirc.flesh_copy_location(row_item.acp)
+            .then(function(copy) {
+                if (copy && !row_item.route_to) 
+                    row_item.route_to = copy.location().name();
+            });
         },
         function() {
             // Circ was rejected somewhere along the way.
@@ -148,7 +176,6 @@ function($scope , $q , egCore , checkinSvc , egGridDataProvider , egCirc)  {
 
         if (checkinSvc.checkins.length == 0) return $q.when();
 
-
         angular.forEach(checkinSvc.checkins, function(evt) {
 
             var checkin = {
index 87828cc..0db4816 100644 (file)
@@ -246,6 +246,25 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         });
     }
 
+    // there may be *many* copy locations and we may be handling items
+    // for other locations.  Fetch copy locations as-needed and cache.
+    service.flesh_copy_location = function(copy) {
+        if (!copy) return $q.when();
+        if (angular.isObject(copy.location())) return $q.when(copy);
+        if (egCore.env.acpl) {
+            if (egCore.env.acpl.map[copy.location()]) {
+                copy.location(egCore.env.acpl.map[copy.location()]);
+                return $q.when(copy);
+            }
+        } 
+        return egCore.pcrud.retrieve('acpl', copy.location())
+        .then(function(loc) {
+            egCore.env.absorbList([loc], 'acpl'); // append to cache
+            copy.location(loc);
+            return copy;
+        });
+    }
+
 
     // fetch/cache for org unit addresses
     service.get_org_addr = function(org_id, addr_type) {
index ca1d709..b8ddd7b 100644 (file)
@@ -77,8 +77,22 @@ function($q,  $window , egAuth,  egPCRUD,  egIDL) {
 
     /** caches the object list both as the list and an id => object map */
     service.absorbList = function(list, class_) {
-        var blob = {list : list, map : {}};
+        var blob;
         var pkey = egIDL.classes[class_].pkey;
+
+        if (service[class_]) {
+            // appending data to an existing class.  Useful for receiving 
+            // class elements as-needed.  Avoid adding items which are 
+            // already tracked in the list.
+            blob = service[class_];
+            angular.forEach(list, function(item) {
+                if (!service[class_].map[item[pkey]()]) 
+                    blob.list.push(item);
+            });
+        } else {
+            blob = {list : list, map : {}};
+        }
+
         angular.forEach(list, function(item) {blob.map[item[pkey]()] = item});
         service[class_] = blob;
         return blob;
index 9464df4..e5847c3 100644 (file)
@@ -1202,7 +1202,7 @@ angular.module('egGridMod',
                 if (obj === null || obj === undefined || obj === '') return '';
                 if (!column.path) return obj;
 
-                var idlField, cls, clsobj;
+                var idl_field;
                 var parts = column.path.split('.');
 
                 angular.forEach(parts, function(step, idx) {
@@ -1212,10 +1212,9 @@ angular.module('egGridMod',
                         return;
                     }
 
-                    cls = obj.classname;
-                    if (cls && (clsobj = egCore.idl.classes[cls])) {
-                        idlField = clsobj.fields.filter(
-                            function(f) { return f.name == step })[0];
+                    var cls = obj.classname;
+                    if (cls && (class_obj = egCore.idl.classes[cls])) {
+                        idl_field = class_obj.field_map[step];
                         obj = obj[step] ? obj[step]() : '';
                     } else {
                         if (angular.isFunction(obj[step])) {
@@ -1226,8 +1225,12 @@ angular.module('egGridMod',
                     }
                 });
 
+                // We found a nested IDL object which may or may not have 
+                // been configured as a top-level column.  Grab the datatype.
+                if (idl_field && !column.datatype) 
+                    column.datatype = idl_field.datatype;
+
                 if (obj === null || obj === undefined || obj === '') return '';
-                if (!idlField) return obj;
                 return obj;
             }
         }