2 * Checkout items to patrons
5 angular.module('egPatronApp').controller('PatronCheckoutCtrl',
7 ['$scope','$q','$modal','$routeParams','egCore','egUser','patronSvc',
8 'egGridDataProvider','$location','$timeout','egCirc',
10 function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc ,
11 egGridDataProvider , $location , $timeout , egCirc) {
13 $scope.initTab('checkout', $routeParams.id);
14 $scope.focusMe = true;
15 $scope.checkouts = patronSvc.checkouts;
16 $scope.checkoutArgs = {
17 noncat_type : 'barcode',
21 $scope.gridDataProvider = egGridDataProvider.instance({
22 get : function(offset, count) {
23 return this.arrayNotifier($scope.checkouts, offset, count);
27 $scope.disable_checkout = function() {
30 patronSvc.current.active() == 'f' ||
31 patronSvc.current.deleted() == 't' ||
32 patronSvc.current.card().active() == 'f'
36 $scope.using_hatch = egCore.hatch.usingHatch();
38 // avoid multiple, in-flight attempts on the same barcode
39 var pending_barcodes = {};
41 var printOnComplete = true;
43 'circ.staff_client.do_not_auto_attempt_print'
44 ]).then(function(settings) {
45 printOnComplete = !Boolean(
46 settings['circ.staff_client.do_not_auto_attempt_print']);
49 egCirc.get_noncat_types().then(function(list) {
50 $scope.nonCatTypes = list;
53 $scope.selectedNcType = function() {
54 if (!egCore.env.cnct) return null; // too soon
55 var type = egCore.env.cnct.map[$scope.checkoutArgs.noncat_type];
56 return type ? type.name() : null;
59 $scope.checkout = function(args) {
60 var params = angular.copy(args);
61 params.patron_id = patronSvc.current.id();
63 if (args.sticky_date) {
64 params.due_date = args.due_date.toISOString();
66 delete params.due_date;
68 delete params.sticky_date;
70 if (params.noncat_type == 'barcode') {
71 if (!args.copy_barcode) return;
73 args.copy_barcode = ''; // reset UI input
74 params.noncat_type = ''; // "barcode"
76 if (pending_barcodes[params.copy_barcode]) {
78 "Skipping checkout of redundant barcode "
84 pending_barcodes[params.copy_barcode] = true;
85 send_checkout(params);
88 egCirc.noncat_dialog(params).then(function() {
93 $scope.focusMe; // return focus to barcode input
96 function send_checkout(params) {
98 params.noncat_type = params.noncat ? params.noncat_type : '';
100 // populate the grid row before we send the request so that the
101 // order of actions is maintained and so the user gets an
102 // immediate reaction to their barcode input action.
104 index : $scope.checkouts.length,
105 copy_barcode : params.copy_barcode,
106 noncat_type : params.noncat_type
109 $scope.checkouts.unshift(row_item);
110 $scope.gridDataProvider.refresh();
112 var options = {check_barcode : $scope.strict_barcode};
114 egCirc.checkout(params, options).then(
116 // update stats locally so we don't have to fetch them w/
118 patronSvc.patron_stats.checkouts.out++;
119 patronSvc.patron_stats.checkouts.total_out++;
121 // copy the response event into the original grid row item
122 // note: angular.copy clobbers the destination
123 row_item.evt = co_resp.evt;
124 angular.forEach(co_resp.data, function(val, key) {
127 munge_checkout_resp(co_resp, row_item);
130 // Circ was rejected somewhere along the way.
131 // Remove the copy from the grid since there was no action.
132 // note: since checkouts are unshifted onto the array, the
133 // index value does not (generally) match the array position.
135 angular.forEach($scope.checkouts, function(co, idx) {
136 if (co.index == row_item.index) pos = idx;
138 $scope.checkouts.splice(pos, 1);
139 $scope.gridDataProvider.refresh();
142 )['finally'](function() {
144 // regardless of the outcome of the circ, remove the
145 // barcode from the pending list.
146 if (params.copy_barcode)
147 delete pending_barcodes[params.copy_barcode];
151 // add some checkout-specific additions for display
152 function munge_checkout_resp(co_resp, row_item) {
153 var params = co_resp.params;
155 row_item.title = egCore.env.cnct.map[params.noncat_type].name();
156 row_item.noncat_count = params.noncat_count;
157 row_item.circ = new egCore.idl.circ();
158 row_item.circ.due_date(co_resp.evt.payload.noncat_circ.duedate());
162 $scope.print_receipt = function() {
163 var print_data = {circulations : []}
165 if ($scope.checkouts.length == 0) return $q.when();
167 angular.forEach($scope.checkouts, function(co) {
169 print_data.circulations.push({
170 circ : egCore.idl.toHash(co.circ),
171 copy : egCore.idl.toHash(co.acp),
172 call_number : egCore.idl.toHash(co.acn),
179 return egCore.print.print({
181 template : 'checkout',
183 show_dialog : $scope.show_print_dialog
187 // Redirect the user to the barcode entry page to load a new patron.
188 // If configured to do so, print the receipt first
189 $scope.done = function() {
190 if (printOnComplete) {
192 $scope.print_receipt().then(function() {
193 $location.path('/circ/patron/bcsearch');
197 $location.path('/circ/patron/bcsearch');