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