payments UI repairs; adding menus
authorBill Erickson <berick@esilibrary.com>
Wed, 21 May 2014 19:33:25 +0000 (15:33 -0400)
committerBill Erickson <berick@esilibrary.com>
Wed, 21 May 2014 19:33:25 +0000 (15:33 -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_bills_list.tt2
Open-ILS/src/templates/staff/circ/patron/t_summary.tt2
Open-ILS/src/templates/staff/share/t_autogrid.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
Open-ILS/web/js/ui/default/staff/services/grid.js

index f4d2fab..12c07e3 100644 (file)
@@ -40,7 +40,7 @@ angular.module('egCoreMod').run(['egStrings', function(s) {
       <h4 title="{{patron().id()}}">
         <div class="flex-row">
           <div class="flex-cell">
-            [% l('[_1], [_2], [_3]', 
+            [% l('[_1], [_2] [_3]', 
                 '{{patron().family_name()}}',
                 '{{patron().first_given_name()}}',
                 '{{patron().second_given_name()}}') %]
index 2f59fde..68307dd 100644 (file)
@@ -3,7 +3,7 @@
   idl-class="mobts"
   query="gridQuery"
   on-item-retrieved="gridItemRetrieved"
-  on-item-selected="gridItemSelected"
+  on-selection-change="gridSelectionChanged"
   revision="gridRevision"
   persist-key="circ.patron.bills">
 
   <eg-grid-menu-item label="[% l('Check All Refunds') %]" 
     handler="selectRefunds"></eg-grid-menu-item>
 
-  <eg-grid-menu-item label="[% l('Print Bills') %]" 
-    handler="printBills"></eg-grid-menu-item>
+  <eg-grid-action label="[% l('Print Bills') %]" 
+    handler="printBills"></eg-grid-action>
 
+  <!--
+  need to decide if these are necessary here w/ inline links
+  to record and copy details (though they could be hidden).
+  it's misleading to allow the user to select multiple bills
+  but only open the link to one
+
+  <eg-grid-action label="[% l('Show in Catalog') %]" 
+    handler=""></eg-grid-action>
+
+  <eg-grid-action label="[% l('Show Item Details') %]" 
+    handler=""></eg-grid-action>
+  -->
+
+  <eg-grid-action label="[% l('Void All Billings') %]" 
+    handler=""></eg-grid-action>
+
+  <eg-grid-action label="[% l('Refund') %]" 
+    handler=""></eg-grid-action>
+
+  <eg-grid-action label="[% l('Add Billing') %]" 
+    handler=""></eg-grid-action>
+
+  <eg-grid-action label="[% l('Full Details') %]" 
+    handler=""></eg-grid-action>
 
   <eg-grid-field label="[% ('Balance Owed') %]" path='balance_owed'></eg-grid-field>
   <eg-grid-field label="[% ('Bill #') %]" path='id'></eg-grid-field>
   <eg-grid-field label="[% ('Total Billed') %]" path='total_owed'></eg-grid-field>
   <eg-grid-field label="[% ('Total Paid') %]" path='total_paid'></eg-grid-field>
   <eg-grid-field label="[% ('Type') %]" path='xact_type'></eg-grid-field>
-  <eg-grid-field label="[% ('Title') %]" name='title' 
+
+  <eg-grid-field label="[% l('Title') %]" name="title"
     path='circulation.target_copy.call_number.record.simple_record.title'>
+    <a href="[% ctx.base_path %]/opac/record/{{item.record_id}}">{{item.title}}</a>
+  </eg-grid-field>
+  <!-- fetch the record ID so we can link to it.  hide it by default -->
+  <eg-grid-field path="circulation.target_copy.call_number.record.id" 
+    label="[% l('Record ID') %]" name="record_id" required hidden>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Barcode') %]" 
+    path='circulation.target_copy.barcode' name="copy_barcode">
+    <a href="./cat/item/{{item.copy_id}}" target="_self">
+      {{item.copy_barcode}}
+    </a>
+  </eg-grid-field>
+  <!-- fetch the copy ID so we can link to it.  hide it by default -->
+  <eg-grid-field path="circulation.target_copy.id" 
+    label="[% l('Copy ID') %]" name="copy_id" required hidden>
   </eg-grid-field>
+
   <!-- virtual field -->
-  <eg-grid-field label="[% ('Payment Pending') %]" name="payment_pending"></eg-grid-field>
+  <eg-grid-field datatype="money" label="[% ('Payment Pending') %]" 
+    name="payment_pending"></eg-grid-field>
+  
 </eg-grid>
  
index 251bc5e..6f23d45 100644 (file)
@@ -1,20 +1,5 @@
 
 <div ng-cloak>
-  <!--
-  <div class="row" ng-show="!patron()">
-    <div class="col-md-12">
-      <i>[% l('Patron Summary') %]</i>
-    </div>
-  </div>
-  <div ng-show="patron()" id="patron-summary-grid">
-    <div class="row">
-      <div class="col-md-12">
-        <h4 title="{{patron().id()}}">
-[% l('{{patron().first_given_name()}} {{patron().second_given_name()}} {{patron().family_name()}}') %]
-        </h4>
-      </div>
-    </div>
-    -->
   <div ng-show="patron()" id="patron-summary-grid">
     <div class="row" 
       ng-class="{'patron-summary-divider' : !$index}"
index 237a5fc..018d6de 100644 (file)
     <div class="eg-grid-cell eg-grid-cell-stock">
       <div>
         <input title="[% l('Row Selector Column') %]"
-          type='checkbox' ng-click="toggleSelectAllItems()"/>
+          type='checkbox' ng-model="selectAll"/> 
       </div>
     </div>
     <div class="eg-grid-cell"
index bc74f52..6e44de7 100644 (file)
@@ -64,16 +64,14 @@ function($scope,  $q , $routeParams,  $locale , egCore , egGridDataProvider , bi
     // given a payment amount, determines how much of that is applied
     // to selected transactions and how much is left over (change).
     function pending_payment_info() {
-        if ($scope.payment_amount >= $scope.owed_selected()) {
+        var amt = $scope.payment_amount || 0;
+        if (amt >= $scope.owed_selected()) {
             return {
                 payment : $scope.owed_selected(),
-                change : $scope.payment_amount - $scope.owed_selected()
+                change : amt - $scope.owed_selected()
             }
         } 
-        return {
-            payment : $scope.payment_amount,
-            change : 0
-        };
+        return {payment : amt, change : 0};
     }
 
     // calculates amount owed, billed, and paid for selected items
@@ -113,15 +111,37 @@ function($scope,  $q , $routeParams,  $locale , egCore , egGridDataProvider , bi
 
     var query = {usr : billSvc.userId, balance_owed : {'<>' : 0}};
     $scope.gridQuery = function() {return query};
+
+    var allItems = [];
     $scope.gridItemRetrieved = function(item) {
         item.payment_pending = 0;
+        allItems.push(item);
     }
 
     var selectedItems = [];
-    $scope.gridItemSelected = function(sel, desel, all) {
-        // keep a local cache of the selected items so we can 
-        // calculate payment info from them.
+    $scope.gridSelectionChanged = function(all) {
+        // update the item.payment_pending value each time the user
+        // selects different transactions to pay against.
         selectedItems = all;
+        updatePendingColumn();
+    }
+
+    // update the item.payment_pending for each (selected) 
+    // transaction any time the user-entered payment amount is modified
+    $scope.$watch('payment_amount', updatePendingColumn);
+
+    function updatePendingColumn() {
+        // reset all to zero..
+        angular.forEach(allItems, function(item) {item.payment_pending = 0});
+
+        // then apply the current payment amounts
+        var payments = generatePayments();
+        angular.forEach(payments, function(payment) {
+            var item = selectedItems.filter(function(item) {
+                return (item.id == payment[0])
+            })[0];
+            item.payment_pending = payment[1];
+        });
     }
 
     function generatePayments() {
index ca2b441..7a9f147 100644 (file)
@@ -67,8 +67,9 @@ angular.module('egGridMod',
             // are absorbed by the grid.
             onItemRetrieved : '=',
 
-            // function called with (selectedItem, deSelectedItem, allSelectedItems)
-            onItemSelected : '=',
+            // function called with all selected items each time the
+            // selection set changes
+            onSelectionChange : '=',
 
             // function;  if set, row index values will be hyperlinked and
             // the onclick for an item will call activateItem with the item
@@ -126,7 +127,7 @@ angular.module('egGridMod',
 
                 // items needed only by the grid; remove from scope
                 angular.forEach( 
-                    ['idlClass','onItemRetrieved','onItemSelected','persistKey'], 
+                    ['idlClass','onItemRetrieved','onSelectionChange','persistKey'], 
                     function(field) {
                         grid[field] = $scope[field];
                         delete $scope[field];
@@ -169,6 +170,12 @@ angular.module('egGridMod',
                     delete $scope.autoFields;
                 }
 
+                if (grid.onSelectionChange) {
+                    $scope.$watch('selected', function() {
+                        grid.onSelectionChange(grid.getSelectedItems())
+                    }, true);
+                }
+
    
                 if (!grid.dataProvider) {
 
@@ -440,14 +447,13 @@ angular.module('egGridMod',
                 });
             }
 
-            // if all are selected, deselect all, otherwise select all
-            $scope.toggleSelectAllItems = function() {
-                if (Object.keys($scope.selected).length == $scope.items.length) {
-                    $scope.selected = {};
-                } else {
+            $scope.$watch('selectAll', function(newVal) {
+                if (newVal) {
                     grid.selectAllItems();
+                } else {
+                    $scope.selected = {};
                 }
-            }
+            });
 
             // returns true if item1 appears in the list before item2;
             // false otherwise.  this is slightly more efficient that
@@ -534,6 +540,7 @@ angular.module('egGridMod',
                 }
 
 
+                /*
                 if (grid.onItemSelected) {
                     // multiple items may be selected / de-selected within a
                     // single click action.  Find all that have changed state.
@@ -556,6 +563,7 @@ angular.module('egGridMod',
                             grid.onItemSelected(item, null, all);
                     });
                 }
+                */
             }
 
             // Builds a sort expression from column sort priorities.
@@ -762,6 +770,11 @@ angular.module('egGridMod',
             path  : '@', // optional; flesh path
             label : '@', // optional; display label
             flex  : '@',  // optional; default flex width
+
+            // optional: for non-IDL columns, specifying a datatype
+            // lets the caller control which display filter is used.
+            // datatype should match the standard IDL datatypes.
+            datatype : '@'
         },
         link : function(scope, element, attrs, egGridCtrl) {
 
@@ -787,6 +800,7 @@ angular.module('egGridMod',
             if (tmpl && !tmpl.match(/^\s*$/))
                 scope.template = tmpl
 
+               'datatype', // for non-IDL fields, can be used to apply filters
             egGridCtrl.columnsProvider.add(scope);
             scope.$destroy();
         }
@@ -930,7 +944,11 @@ angular.module('egGridMod',
             // lookup the matching IDL field
             var idl_field = cols.idlFieldFromPath(column.path);
 
-            if (!idl_field) return; // ad-hoc field
+            if (!idl_field) {
+                // column is not represented within the IDL
+                column.adhoc = true; 
+                return; 
+            }
 
             column.datatype = idl_field.datatype;
             
@@ -1117,7 +1135,7 @@ angular.module('egGridMod',
                     angular.forEach(provider.columnsProvider.columns, 
                         function(col) {
                             // only query IDL-tracked columns
-                            if (col.datatype && (col.required || col.visible))
+                            if (!col.adhoc && (col.required || col.visible))
                                 queryFields[col.name] = col.path;
                         }
                     );