LP#1712686 - display completed barcode on copy grids not partial input
[Evergreen.git] / Open-ILS / web / js / ui / default / staff / circ / renew / app.js
1 /**
2  * Renewal
3  */
4
5 angular.module('egRenewApp', 
6     ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'egGridMod'])
7
8 .config(function($routeProvider, $locationProvider, $compileProvider) {
9     $locationProvider.html5Mode(true);
10     $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob):/); // grid export
11     var resolver = {delay : function(egStartup) {return egStartup.go()}};
12
13     $routeProvider.when('/circ/renew/renew', {
14         templateUrl: './circ/renew/t_renew',
15         controller: 'RenewCtrl',
16         resolve : resolver
17     });
18
19     $routeProvider.when('/circ/renew/renew', {
20         templateUrl: './circ/renew/t_renew',
21         controller: 'RenewCtrl',
22         resolve : resolver
23     });
24     
25     $routeProvider.otherwise({redirectTo : '/circ/renew/renew'});
26 })
27
28
29
30
31 .controller('RenewCtrl',
32        ['$scope','$window','$location','egCore','egGridDataProvider','egCirc',
33 function($scope , $window , $location , egCore , egGridDataProvider , egCirc) {
34
35     egCore.hatch.getItem('circ.renew.strict_barcode')
36         .then(function(sb){ $scope.strict_barcode = sb });
37     $scope.focusBarcode = true;
38     $scope.renewals = [];
39
40     var today = new Date();
41     $scope.renewalArgs = {due_date : today};
42
43     $scope.sort_money = function (a,b) {
44         var ma = parseFloat(a);
45         var mb = parseFloat(b);
46         if (ma < mb) return -1;
47         if (ma > mb) return 1;
48         return 0
49     }
50
51     $scope.gridDataProvider = egGridDataProvider.instance({
52         get : function(offset, count) {
53             return this.arrayNotifier($scope.renewals, offset, count);
54         }
55     });
56
57     // avoid multiple, in-flight attempts on the same barcode
58     var pending_barcodes = {};
59
60     $scope.renew = function(args) {
61         var params = angular.copy(args);
62
63         if (args.sticky_date) {
64             params.due_date = args.due_date.toISOString();
65         } else {
66             delete params.due_date;
67         }
68         delete params.sticky_date;
69          if (!args.copy_barcode) return;
70
71         args.copy_barcode = ''; // reset UI input
72
73         if (pending_barcodes[params.copy_barcode]) {
74             console.log(
75                 "Skipping renewals of redundant barcode " 
76                 + params.copy_barcode
77             );
78             return;
79         }
80
81         pending_barcodes[params.copy_barcode] = true;
82         send_renewal(params);
83
84         $scope.focusBarcode = true; // return focus to barcode input
85     }
86
87     function send_renewal(params) {
88
89         params.noncat_type = params.noncat ? params.noncat_type : '';
90
91         // populate the grid row before we send the request so that the
92         // order of actions is maintained and so the user gets an 
93         // immediate reaction to their barcode input action.
94         var row_item = {
95             index : $scope.renewals.length,
96             input_barcode : params.copy_barcode,
97             noncat_type : params.noncat_type
98         };
99
100         $scope.renewals.unshift(row_item);
101         $scope.gridDataProvider.refresh();
102
103         egCore.hatch.setItem('circ.renew.strict_barcode', $scope.strict_barcode);
104         var options = {check_barcode : $scope.strict_barcode};
105
106         egCirc.renew(params, options).then(
107             function(final_resp) {
108
109                 row_item.evt = final_resp.evt;
110                 angular.forEach(final_resp.data, function(val, key) {
111                     row_item[key] = val;
112                 });
113
114                 row_item['copy_barcode'] = row_item.acp.barcode();
115
116                 if (row_item.mbts) {
117                     var amt = Number(row_item.mbts.balance_owed());
118                     if (amt != 0) {
119                         $scope.billable_barcode = row_item.copy_barcode;
120                         $scope.billable_amount = amt;
121                         $scope.fine_total = 
122                             ($scope.fine_total * 100 + amt * 100) / 100;
123                     }
124                 }
125
126                 if ($scope.trim_list && checkinSvc.checkins.length > 20)
127                     checkinSvc.checkins = checkinSvc.checkins.splice(0, 20);
128
129             },
130             function() {
131                 // Circ was rejected somewhere along the way.
132                 // Remove the copy from the grid since there was no action.
133                 // note: since renewals are unshifted onto the array, the
134                 // index value does not (generally) match the array position.
135                 var pos = -1;
136                 angular.forEach($scope.renewals, function(co, idx) {
137                     if (co.index == row_item.index) pos = idx;
138                 });
139                 $scope.renewals.splice(pos, 1);
140                 $scope.gridDataProvider.refresh();
141             }
142
143         )['finally'](function() {
144
145             // regardless of the outcome of the circ, remove the 
146             // barcode from the pending list.
147             if (params.copy_barcode)
148                 delete pending_barcodes[params.copy_barcode];
149         });
150     }
151
152     $scope.fetchLastCircPatron = function(items) {
153         var renewal = items[0];
154         if (!renewal || !renewal.acp) return;
155
156         egCirc.last_copy_circ(renewal.acp.id())
157         .then(function(circ) {
158
159             if (circ) {
160                 // jump to the patron UI (separate app)
161                 $window.location.href = $location
162                     .path('/circ/patron/' + circ.usr() + '/checkout')
163                     .absUrl();
164                 return;
165             }
166
167             $scope.alert = {item_never_circed : renewal.acp.barcode()};
168         });
169     }
170
171     $scope.showMarkDamaged = function(items) {
172         var copy_ids = [];
173         angular.forEach(items, function(item) {
174             if (item.acp) copy_ids.push(item.acp.id());
175         });
176
177         if (copy_ids.length) {
178             egCirc.mark_damaged(copy_ids).then(function() {
179                 // update grid items?
180             });
181         }
182     }
183
184     $scope.showLastFewCircs = function(items) {
185         if (items.length && (copy = items[0].acp)) {
186             var url = $location.path(
187                 '/cat/item/' + copy.id() + '/circ_list').absUrl();
188             $window.open(url, '_blank').focus();
189         }
190     }
191
192     $scope.abortTransit = function(items) {
193         var transit_ids = [];
194         angular.forEach(items, function(item) {
195             if (item.transit) transit_ids.push(item.transit.id());
196         });
197
198         egCirc.abort_transits(transit_ids).then(function() {
199             // update grid items?
200         });
201     }
202
203     $scope.print_receipt = function() {
204         var print_data = {circulations : []}
205
206         if ($scope.renewals.length == 0) return $q.when();
207
208         angular.forEach($scope.renewals, function(renewal) {
209             if (renewal.circ) {
210                 print_data.circulations.push({
211                     circ : egCore.idl.toHash(renewal.circ),
212                     copy : egCore.idl.toHash(renewal.acp),
213                     title : egCore.idl.toHash(renewal.title),
214                     author : egCore.idl.toHash(renewal.author)
215                 });
216             }
217         });
218
219         return egCore.print.print({
220             context : 'default', 
221             template : 'renew', 
222             scope : print_data,
223         });
224     }
225 }])
226