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>
--- /dev/null
+<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>
+
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',
* 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
)
}
+ // 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;
}])
* 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);
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
}
);
}
+
+ // 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();
+ });
+
+}])
// 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 : '@',
grid.init = function() {
grid.offset = 0;
- grid.limit = 25;
+ grid.limit = Number($scope.pageSize) || 25;
$scope.items = [];
$scope.showGridConf = false;
grid.totalCount = -1;
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]();
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);
}
}
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');