LP#1612752 No canceled transits in webstaff transit list
[working/Evergreen.git] / Open-ILS / web / js / ui / default / staff / circ / transits / list.js
1 angular.module('egTransitListApp', 
2     ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'egGridMod'])
3
4 .config(function($routeProvider, $locationProvider, $compileProvider) {
5     $locationProvider.html5Mode(true);
6     $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob):/); // grid export
7
8     var resolver = {delay : 
9         ['egStartup', function(egStartup) {return egStartup.go()}]}
10
11     $routeProvider.when('/circ/transits/list', {
12         templateUrl: './circ/transits/t_list',
13         controller: 'TransitListCtrl',
14         resolve : resolver
15     });
16
17     $routeProvider.otherwise({redirectTo : '/circ/transits/list'});
18 })
19
20 .controller('TransitListCtrl',
21        ['$scope','$q','$routeParams','$window','egCore','egTransits','egGridDataProvider','$uibModal','$timeout',
22 function($scope , $q , $routeParams , $window , egCore , egTransits , egGridDataProvider , $uibModal , $timeout) {
23
24     $scope.transit_direction = 'to';
25
26     function init_dates() {
27         // setup date filters
28         var start = new Date(); // midnight this morning
29         start.setHours(0);
30         start.setMinutes(0);
31         var end = new Date(); // near midnight tonight
32         end.setHours(23);
33         end.setMinutes(59);
34         $scope.dates = {
35             start_date : start,
36             end_date : new Date()
37         }
38     }
39     init_dates();
40
41     function date_range() {
42         if ($scope.dates.start_date > $scope.dates.end_date) {
43             var tmp = $scope.dates.start_date;
44             $scope.dates.start_date = $scope.dates.end_date;
45             $scope.dates.end_date = tmp;
46         }
47         $scope.dates.start_date.setHours(0);
48         $scope.dates.start_date.setMinutes(0);
49         $scope.dates.end_date.setHours(23);
50         $scope.dates.end_date.setMinutes(59);
51         try {
52             var start = $scope.dates.start_date.toISOString().replace(/T.*/,'');
53             var end = $scope.dates.end_date.toISOString().replace(/T.*/,'');
54         } catch(E) { // handling empty date widgets; maybe dangerous if something else can happen
55             init_dates();
56             return date_range();
57         }
58         var today = new Date().toISOString().replace(/T.*/,'');
59         if (end == today) end = 'now';
60         return [start, end];
61     }
62
63     function load_item(transits) {
64         if (!transits) return;
65         if (!angular.isArray(transits)) transits = [transits];
66         angular.forEach(transits, function(transit) {
67             $window.open(
68                 egCore.env.basePath + '/cat/item/' +
69                 transit.target_copy().id(),
70                 '_blank'
71             ).focus()
72         });
73     }
74
75     $scope.load_item = function(action, data, transits) {
76         load_item(transits);
77     }
78
79     function abort_transit(transits) {
80         if (!transits) return;
81         if (!angular.isArray(transits)) transits = [transits];
82         if (transits.length == 0) return;
83         egTransits.abort_transits( transits, refresh_page );
84     }
85
86     $scope.abort_transit = function(action, date, transits) {
87         abort_transit(transits);
88     }
89
90     $scope.add_copies_to_bucket = function() {
91         var copy_list = [];
92         angular.forEach($scope.grid_controls.selectedItems(), function(transit) {
93             copy_list.push(transit['target_copy.id']);
94         });
95         if (copy_list.length == 0) return;
96
97         // FIXME what follows ought to be refactored into a factory
98         return $uibModal.open({
99             templateUrl: './cat/catalog/t_add_to_bucket',
100             animation: true,
101             size: 'md',
102             controller:
103                    ['$scope','$uibModalInstance',
104             function($scope , $uibModalInstance) {
105
106                 $scope.bucket_id = 0;
107                 $scope.newBucketName = '';
108                 $scope.allBuckets = [];
109
110                 egCore.net.request(
111                     'open-ils.actor',
112                     'open-ils.actor.container.retrieve_by_class.authoritative',
113                     egCore.auth.token(), egCore.auth.user().id(),
114                     'copy', 'staff_client'
115                 ).then(function(buckets) { $scope.allBuckets = buckets; });
116
117                 $scope.add_to_bucket = function() {
118                     var promises = [];
119                     angular.forEach(copy_list, function (cp) {
120                         var item = new egCore.idl.ccbi()
121                         item.bucket($scope.bucket_id);
122                         item.target_copy(cp);
123                         promises.push(
124                             egCore.net.request(
125                                 'open-ils.actor',
126                                 'open-ils.actor.container.item.create',
127                                 egCore.auth.token(), 'copy', item
128                             )
129                         );
130
131                         return $q.all(promises).then(function() {
132                             $uibModalInstance.close();
133                         });
134                     });
135                 }
136
137                 $scope.add_to_new_bucket = function() {
138                     var bucket = new egCore.idl.ccb();
139                     bucket.owner(egCore.auth.user().id());
140                     bucket.name($scope.newBucketName);
141                     bucket.description('');
142                     bucket.btype('staff_client');
143
144                     return egCore.net.request(
145                         'open-ils.actor',
146                         'open-ils.actor.container.create',
147                         egCore.auth.token(), 'copy', bucket
148                     ).then(function(bucket) {
149                         $scope.bucket_id = bucket;
150                         $scope.add_to_bucket();
151                     });
152                 }
153
154                 $scope.cancel = function() {
155                     $uibModalInstance.dismiss();
156                 }
157             }]
158         });
159     }
160
161
162     function gatherSelectedRecordIds () {
163         var rid_list = [];
164         angular.forEach(
165             $scope.grid_controls.selectedItems(),
166             function (item) {
167                 if (rid_list.indexOf(item['target_copy.call_number.record.simple_record.id']) == -1)
168                     rid_list.push(item['target_copy.call_number.record.simple_record.id']);
169             }
170         );
171         return rid_list;
172     }
173     function gatherSelectedHoldingsIds (rid) {
174         var cp_id_list = [];
175         angular.forEach(
176             $scope.grid_controls.selectedItems(),
177             function (item) {
178                 if (rid && item['target_copy.call_number.record.simple_record.id'] != rid) return;
179                 cp_id_list.push(item['target_copy.id']);
180             }
181         );
182         return cp_id_list;
183     }
184
185     var spawnHoldingsEdit = function (hide_vols, hide_copies){
186         angular.forEach(gatherSelectedRecordIds(), function (r) {
187             egCore.net.request(
188                 'open-ils.actor',
189                 'open-ils.actor.anon_cache.set_value',
190                 null, 'edit-these-copies', {
191                     record_id: r,
192                     copies: gatherSelectedHoldingsIds(r),
193                     raw: {},
194                     hide_vols : hide_vols,
195                     hide_copies : hide_copies
196                 }
197             ).then(function(key) {
198                 if (key) {
199                     var url = egCore.env.basePath + 'cat/volcopy/' + key;
200                     $timeout(function() { $window.open(url, '_blank') });
201                 } else {
202                     alert('Could not create anonymous cache key!');
203                 }
204             });
205         });
206     }
207    
208     $scope.edit_copies = function() { 
209         spawnHoldingsEdit(true, false);
210     }
211
212     function current_query() {
213         var filter = {
214             'source_send_time' : { 'between' : date_range() },
215             'dest_recv_time'   : null,
216             'cancel_time'      : null
217         };
218         if ($scope.transit_direction == 'to') { filter['dest'] = $scope.context_org.id(); }
219         if ($scope.transit_direction == 'from') { filter['source'] = $scope.context_org.id(); }
220         return filter;
221     }
222
223     $scope.grid_controls = {
224         activateItem : load_item,
225         setQuery : current_query
226     }
227
228     function refresh_page() {
229         $scope.grid_controls.setQuery(current_query());
230         $scope.grid_controls.refresh();
231     }
232
233     $scope.context_org = egCore.org.get(egCore.auth.user().ws_ou());
234     $scope.$watch('context_org', function(newVal, oldVal) {
235         if (newVal && newVal != oldVal) refresh_page();
236     });
237     $scope.$watch('transit_direction', function(newVal, oldVal) {
238         if (newVal && newVal != oldVal) refresh_page();
239     });
240     $scope.$watch('dates.start_date', function(newVal, oldVal) {
241         if (newVal && newVal != oldVal) refresh_page();
242     });
243     $scope.$watch('dates.end_date', function(newVal, oldVal) {
244         if (newVal && newVal != oldVal) refresh_page();
245     });
246
247     function fetch_all_matching_transits(transits) {
248         var deferred = $q.defer();
249         var filter = current_query();
250         egCore.pcrud.search('atc',
251             filter, {
252                 'flesh' : 5,
253                 // atc -> target_copy       -> call_number -> record -> simple_record
254                 // atc -> hold_transit_copy -> hold        -> usr    -> card
255                 'flesh_fields' : {
256                     'atc' : ['target_copy','dest','source','hold_transit_copy'],
257                     'acp' : ['call_number','location','circ_lib'],
258                     'acn' : ['record'],
259                     'bre' : ['simple_record'],
260                     'ahtc' : ['hold'],
261                     'ahr' : ['usr'],
262                     'au' : ['card']
263                 },
264                 'select' : { 'bre' : ['id'] },
265                 order_by : { atc : 'source_send_time' },
266             }
267         ).then(
268             deferred.resolve, null,
269             function(transit) {
270                 transits.push(egCore.idl.toHash(transit));
271             }
272         );
273         return deferred.promise;
274     }
275
276     $scope.print_full_list = function() {
277         var print_data = { transits : [] };
278
279         return fetch_all_matching_transits(print_data.transits).then(function() {
280             if (print_data.transits.length == 0) return $q.when();
281             return egCore.print.print({
282                 template : 'transit_list',
283                 scope : print_data
284             });
285         });
286
287     }
288 }])
289