initial xact details page
authorBill Erickson <berick@esilibrary.com>
Tue, 27 May 2014 21:19:11 +0000 (17:19 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 27 May 2014 21:19:11 +0000 (17:19 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2
Open-ILS/src/templates/staff/circ/patron/t_xact_details.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/bills.js
Open-ILS/web/js/ui/default/staff/services/grid.js

index 5827591..b88ff6e 100644 (file)
@@ -44,7 +44,7 @@
     handler="addBilling"></eg-grid-action>
 
   <eg-grid-action label="[% l('Full Details') %]" 
-    handler="showFillDetails"></eg-grid-action>
+    handler="showFullDetails"></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>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_xact_details.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_xact_details.tt2
new file mode 100644 (file)
index 0000000..79d4d50
--- /dev/null
@@ -0,0 +1,69 @@
+<h2>[% l('Transaction Details') %]</h2>
+
+<h3>[% l('Summary') %]</h3>
+
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Billing Location') %]</div>
+  <div class="col-md-2">{{xact.billing_location().shortname()}}</div>
+</div>
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Bill #') %]</div>
+  <div class="col-md-2">{{xact.id()}}</div>
+  <div class="col-md-2 strong-text">[% l('Total Billed') %]</div>
+  <div class="col-md-2">{{xact.total_owed() | currency}}</div>
+  <div class="col-md-2 strong-text">[% l('Title') %]</div>
+  <div class="col-md-2">{{xact.circulation().target_copy().call_number().record().simple_record().title()}}</div>
+</div>
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Type') %]</div>
+  <div class="col-md-2">{{xact.xact_type()}}</div>
+  <div class="col-md-2 strong-text">[% l('Total Paid') %]</div>
+  <div class="col-md-2">{{xact.total_paid() | currency}}</div>
+  <div class="col-md-2 strong-text">[% l('Checked Out') %]</div>
+  <div class="col-md-2">{{xact.circulation().xact_start() | date:'short'}}</div>
+</div>
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Start') %]</div>
+  <div class="col-md-2">{{xact.xact_start() | date:'short'}}</div>
+  <div class="col-md-2 strong-text">[% l('Total Billed') %]</div>
+  <div class="col-md-2">{{xact.balance_owed() | currency}}</div>
+  <div class="col-md-2 strong-text">[% l('Due Date') %]</div>
+  <div class="col-md-2">{{xact.circulation().due_date() | date:'short'}}</div>
+</div>
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Finish') %]</div>
+  <div class="col-md-2">{{xact.xact_finish() | date:'short'}}</div>
+  <div class="col-md-2 strong-text">[% l('Renewal?') %]</div>
+  <div class="col-md-2">
+    <span ng-if="xact.circulation.desk_renewal == 't'">[% l('Desk') %]</span>
+    <span ng-if="xact.circulation.phone_renewal == 't'">[% l('Phone') %]</span>
+    <span ng-if="xact.circulation.opac_renewal == 't'">[% l('OPAC') %]</span>
+  </div>
+  <div class="col-md-2 strong-text">[% l('Checked In') %]</div>
+  <div class="col-md-2">{{xact.circulation().checkin_time() | date:'short'}}</div>
+</div>
+
+<!-- TODO item summary -->
+
+<!-- set a lower default page size (limit) to allow for more space -->
+<br/>
+<eg-grid
+  main-label="[% l('Bills') %]"
+  idl-class="mb"
+  id-field="id"
+  auto-fields="true"
+  page-size="10"
+  items-provider="billGridProvider">
+</eg-grid>
+
+<!-- TODO: this grid may contain objects of different types.. apply manual columns, see xul -->
+<br/>
+<eg-grid
+  main-label="[% l('Payments') %]"
+  idl-class="mp"
+  id-field="id"
+  auto-fields="true"
+  page-size="10"
+  items-provider="paymentGridProvider">
+</eg-grid>
+
index 861cf9a..462d22d 100644 (file)
@@ -97,6 +97,12 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap',
         resolve : resolver
     });
 
+    $routeProvider.when('/circ/patron/:id/bill/:xact_id', {
+        templateUrl: './circ/patron/t_xact_details',
+        controller: 'XactDetailsCtrl',
+        resolve : resolver
+    });
+
     $routeProvider.when('/circ/patron/:id/messages', {
         templateUrl: './circ/patron/t_messages',
         controller: 'PatronMessagesCtrl',
@@ -122,8 +128,8 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap',
  * Patron service
  */
 .factory('patronSvc',
-       ['$q','$timeout','$location','egCore','egUser',
-function($q , $timeout , $location , egCore,  egUser) {
+       ['$q','$timeout','$location','egCore','egUser','$locale',
+function($q , $timeout , $location , egCore,  egUser , $locale) {
 
     var service = {
         // cached patron search results
@@ -295,6 +301,14 @@ function($q , $timeout , $location , egCore,  egUser) {
         )
     }
 
+    // Avoid using parens [e.g. (1.23)] to indicate negative numbers, 
+    // which is the Angular default.
+    // http://stackoverflow.com/questions/17441254/why-angularjs-currency-filter-formats-negative-numbers-with-parenthesis
+    // FIXME: This change needs to be moved into a project-wide collection
+    // of locale overrides.
+    $locale.NUMBER_FORMATS.PATTERNS[1].negPre = '-';
+    $locale.NUMBER_FORMATS.PATTERNS[1].negSuf = '';
+
     return service;
 }])
 
index 4286563..c5fe127 100644 (file)
@@ -119,9 +119,9 @@ function($q , egCore , patronSvc) {
  * Manages Bills
  */
 .controller('PatronBillsCtrl',
-       ['$scope','$q','$routeParams','$locale','egCore','egConfirmDialog',
+       ['$scope','$q','$routeParams','egCore','egConfirmDialog','$location',
         'egGridDataProvider','billSvc','patronSvc','egPromptDialog','$modal',
-function($scope,  $q , $routeParams,  $locale , egCore , egConfirmDialog , 
+function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
          egGridDataProvider , billSvc , patronSvc , egPromptDialog , $modal) {
 
     $scope.initTab('bills', $routeParams.id);
@@ -190,14 +190,6 @@ function($scope,  $q , $routeParams,  $locale , egCore , egConfirmDialog ,
         return -(amount / 100);
     }
 
-    // Avoid using parens [e.g. (1.23)] to indicate negative numbers, 
-    // which is the Angular default.
-    // http://stackoverflow.com/questions/17441254/why-angularjs-currency-filter-formats-negative-numbers-with-parenthesis
-    // FIXME: This change needs to be moved into a project-wide collection
-    // of locale overrides.
-    $locale.NUMBER_FORMATS.PATTERNS[1].negPre = '-';
-    $locale.NUMBER_FORMATS.PATTERNS[1].negSuf = '';
-
     var query = {usr : billSvc.userId, balance_owed : {'<>' : 0}};
     $scope.gridQuery = function() {return query};
     $scope.gridSort = ['xact_start']; // default sort
@@ -397,7 +389,81 @@ function($scope,  $q , $routeParams,  $locale , egCore , egConfirmDialog ,
             }
         );
     }
+
+    // direct the user to the transaction details page
+    $scope.showFullDetails = function(all) {
+        if (all[0]) 
+            $location.path('/circ/patron/' + 
+                patronSvc.current.id() + '/bill/' + all[0].id);
+    }
 }])
 
+/**
+ * Displays details of a single transaction
+ */
+.controller('XactDetailsCtrl',
+       ['$scope','$q','$routeParams','egCore','egGridDataProvider',
+function($scope,  $q , $routeParams , egCore , egGridDataProvider) {
+
+    $scope.initTab('bills', $routeParams.id);
+    var xact_id = $routeParams.xact_id;
+    var bills = [];
+    var payments = [];
+
+    egCore.pcrud.retrieve('mobts', xact_id, 
+        {   flesh : 5,
+            flesh_fields : {
+                mobts : ['circulation','grocery'],
+                circ : ['target_copy'],
+                acp : ['call_number'],
+                acn : ['record'],
+                bre : ['simple_record']
+            },
+            // avoid fetching the MARC blob by specifying which 
+            // fields on the bre to select.  More may be needed.
+            // note that fleshed fields are explicitly selected.
+            select : { bre : ['id'] }
+        },
+        {authoritative : true}
+    ).then(function(xact) {
+        xact.billing_location(egCore.org.get(xact.billing_location()));
+        $scope.xact = xact;
+    });
+
+    // --- bills grid
+    var billProvider = egGridDataProvider.instance();
+    billProvider.get = function(offset, count) {
+        return billProvider.arrayNotifier(bills, offset, count);
+    }
+    billProvider.itemFieldValue = billProvider.nestedItemFieldValue;
+    $scope.billGridProvider = billProvider;
+
+    egCore.net.request(
+        'open-ils.circ',
+        'open-ils.circ.money.billing.retrieve.all.authoritative',
+        egCore.auth.token(), xact_id
+    ).then(function(mbs) {  
+        bills = mbs;
+        billProvider.increment();
+    });
+
+    // --- payments grid
+    var paymentProvider = egGridDataProvider.instance();
+    paymentProvider.get = function(offset, count) {
+        return paymentProvider.arrayNotifier(payments, offset, count);
+    }
+    paymentProvider.itemFieldValue = paymentProvider.nestedItemFieldValue;
+    $scope.paymentGridProvider = paymentProvider;
+
+    egCore.net.request(
+        'open-ils.circ',
+        'open-ils.circ.money.payment.retrieve.all.authoritative',
+        egCore.auth.token(), xact_id
+    ).then(function(mps) {
+        payments = mps;
+        paymentProvider.increment();
+    });
+
+}])
 
 
index 489f4f6..cf80393 100644 (file)
@@ -18,6 +18,9 @@ angular.module('egGridMod',
             // flattener-style sort array
             sort : '=',
 
+            // default page size
+            pageSize : '@',
+
             // if true, grid columns are derived from all non-virtual
             // fields on the base idlClass
             autoFields : '@',
@@ -104,7 +107,7 @@ angular.module('egGridMod',
 
             grid.init = function() {
                 grid.offset = 0;
-                grid.limit = 25;
+                grid.limit = Number($scope.pageSize) || 25;
                 $scope.items = [];
                 $scope.showGridConf = false;
                 grid.totalCount = -1;
@@ -1198,7 +1201,7 @@ angular.module('egGridMod',
                     if (cls && (clsobj = egCore.idl.classes[cls])) {
                         idlField = clsobj.fields.filter(
                             function(f) { return f.name == step })[0];
-                        obj = obj[step]();
+                        obj = obj[step] ? obj[step]() : '';
                     } else {
                         if (angular.isFunction(obj[step])) {
                             obj = obj[step]();
@@ -1210,7 +1213,12 @@ angular.module('egGridMod',
 
                 if (obj === null || obj === undefined || obj === '') return '';
                 if (!idlField) return obj;
-                return $filter('egGridValueFilter')(obj, idlField);
+                return obj;
+
+                // egGridValueFilter is applied in the template.
+                // not sure why this was here.. may be getting
+                // called from another context
+                //return $filter('egGridValueFilter')(obj, idlField);
             }
         }
 
@@ -1421,8 +1429,19 @@ angular.module('egGridMod',
     return function(value, column) {                                             
         switch(column.datatype) {                                                
             case 'bool':                                                       
-                // Browser will translate true/false for us                    
-                return ''+Boolean(value == 't');                                  
+                switch(value) {
+                    // Browser will translate true/false for us                    
+                    case 't' : 
+                    case '1' :  // legacy
+                    case true:
+                        return ''+true;
+                    case 'f' : 
+                    case '0' :  // legacy
+                    case false:
+                        return ''+false;
+                    // value may be null,  '', etc.
+                    default : return '';
+                }
             case 'timestamp':                                                  
                 // canned angular date filter FTW                              
                 return $filter('date')(value, 'shortDate');