]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/ui/default/circ/selfcheck/selfcheck.js
Plugged in the summary data in the sidebar. Kicked off the nls file
[working/Evergreen.git] / Open-ILS / web / js / ui / default / circ / selfcheck / selfcheck.js
1 dojo.require('openils.CGI');
2 dojo.require('openils.Util');
3 dojo.require('openils.User');
4 dojo.require('openils.Event');
5
6 dojo.requireLocalization('openils.circ', 'selfcheck');
7 var localeStrings = dojo.i18n.getLocalization('openils.circ', 'selfcheck');
8
9
10 const SET_BARCODE_REGEX = 'opac.barcode_regex';
11 const SET_PATRON_TIMEOUT = 'circ.selfcheck.patron_login_timeout';
12 const SET_ALERT_ON_CHECKOUT_EVENT = 'circ.selfcheck.alert_on_checkout_event';
13 const SET_AUTO_OVERRIDE_EVENTS = 'circ.selfcheck.auto_override_checkout_events';
14 const SET_PATRON_PASSWORD_REQUIRED = 'circ.selfcheck.patron_password_required';
15
16 function SelfCheckManager() {
17
18     this.cgi = new openils.CGI();
19     this.staff = null; 
20     this.workstation = null;
21     this.authtoken = null;
22
23     this.patron = null; 
24     this.patronBarcodeRegex = null;
25
26     // current item barcode
27     this.itemBarcode = null; 
28
29     // are we currently performing a renewal?
30     this.isRenewal = false; 
31
32     // is a transaction pending?
33     this.pendingXact = false; 
34
35     // dict of org unit settings for "here"
36     this.orgSettings = {};
37 }
38
39 /**
40  * Fetch the org-unit settings, initialize the display, etc.
41  */
42 SelfCheckManager.prototype.init = function() {
43
44     this.staff = openils.User.user;
45     this.workstation = openils.User.workstation;
46     this.authtoken = openils.User.authtoken;
47     this.loadOrgSettings();
48
49     if(this.cgi.param('patron')) {
50         // Patron barcode via cgi param.  Mainly used for debugging.
51         this.loginPatron(this.cgi.param('patron'));
52     } else {
53         this.drawLoginPage();
54     }
55 }
56
57 /**
58  * Loads the org unit settings
59  */
60 SelfCheckManager.prototype.loadOrgSettings = function() {
61
62     var settings = fieldmapper.aou.fetchOrgSettingBatch(
63         this.staff.ws_ou(), [
64             SET_BARCODE_REGEX,
65             SET_PATRON_TIMEOUT,
66             SET_ALERT_ON_CHECKOUT_EVENT,
67             SET_AUTO_OVERRIDE_EVENTS,
68         ]
69     );
70
71     for(k in settings) {
72         if(settings[k])
73             this.orgSettings[k] = settings[k].value;
74     }
75
76     if(settings[SET_BARCODE_REGEX]) 
77         this.patronBarcodeRegex = new RegExp(settings[SET_BARCODE_REGEX].value);
78 }
79
80 SelfCheckManager.prototype.drawLoginPage = function() {
81     var self = this;
82
83     var bcHandler = function(barcode) {
84         // handle patron barcode entry
85
86         if(self.orgSettings[SET_PATRON_PASSWORD_REQUIRED]) {
87             
88             // password is required.  wire up the scan box to read it
89             self.updateScanBox({
90                 msg : 'Please enter your password', // TODO i18n 
91                 handler : function(pw) { self.loginPatron(barcode, ps); }
92             });
93
94             dojo.connect(selfckScanBox, 'onKeyDown', pwHandler);
95
96         } else {
97             // password is not required, go ahead and login
98             self.loginPatron(barcode);
99         }
100     };
101
102     this.updateScanBox({
103         msg : 'Please log in with your library barcode.', // TODO
104         handler : bcHandler
105     });
106 }
107
108 /**
109  * Login the patron.  
110  */
111 SelfCheckManager.prototype.loginPatron = function(barcode, passwd) {
112
113     if(this.orgSettings[SET_PATRON_PASSWORD_REQUIRED]) {
114
115         // patron password is required.  Verify it.
116
117         var res = fieldmapper.standardRequest(
118             ['open-ils.actor', 'open-ils.actor.verify_user_password'],
119             {params : [this.authtoken, barcode, null, hex_md5(passwd)]}
120         );
121
122         if(res == 0) {
123             return alert('login failed'); // TODO
124         }
125     } 
126
127     // retrieve the fleshed user by barcode
128     this.patron = fieldmapper.standardRequest(
129         ['open-ils.actor', 'open-ils.actor.user.fleshed.retrieve_by_barcode'],
130         {params : [this.authtoken, barcode]}
131     );
132
133     var evt = openils.Event.parse(this.patron);
134     if(evt) {
135
136         // User login failed, why?
137         
138         switch(evt.textcode) {
139
140             case 'ACTOR_USER_NOT_FOUND':
141                 return alert('user not found'); // TODO
142
143             case 'NO_SESSION':
144                 return alert('staff login timed out'); // TODO
145
146             default:
147                 return alert('unexpected patron login error occured: ' + evt.textcode); // TODO
148         }
149     }
150
151     // patron login succeeded
152     dojo.byId('oils-selfck-user-banner').innerHTML = 'Welcome, ' + this.patron.usrname(); // TODO i18n
153     this.drawCircPage();
154 }
155
156
157 /**
158  * Manages the main input box
159  * @param msg The context message to display with the box
160  * @param clearOnly Don't update the context message, just clear the value and re-focus
161  * @param handler Optional "on-enter" handler.  
162  */
163 SelfCheckManager.prototype.updateScanBox = function(args) {
164
165     selfckScanBox.attr('value', '');
166
167     if(args.value)
168         selfckScanBox.attr('value', args.value);
169
170     if(args.msg) 
171         dojo.byId('oils-selfck-scan-text').innerHTML = args.msg;
172
173     if(selfckScanBox._lastHandler && (args.handler || args.clearHandler)) {
174         dojo.disconnect(selfckScanBox._lastHandler);
175     }
176
177     if(args.handler) {
178         selfckScanBox._lastHandler = dojo.connect(
179             selfckScanBox, 
180             'onKeyDown', 
181             function(e) {
182                 if(e.keyCode != dojo.keys.ENTER) 
183                     return;
184                 args.handler(selfckScanBox.attr('value'));
185             }
186         );
187     }
188
189     selfckScanBox.focus();
190 }
191
192 /**
193  *  Sets up the checkout/renewal interface
194  */
195 SelfCheckManager.prototype.drawCircPage = function() {
196
197     var self = this;
198     this.updateScanBox({
199         msg : 'Please enter an item barcode', // TODO i18n
200         handler : function(barcode) { self.checkout(barcode); }
201     });
202
203     openils.Util.show('oils-selfck-circ-page');
204
205     this.circTbody = dojo.byId('oils-selfck-circ-tbody');
206     if(!this.circTemplate)
207         this.circTemplate = this.circTbody.removeChild(dojo.byId('oils-selfck-circ-row'));
208
209     // items out, holds, and fines summaries
210
211     // fines summary
212     fieldmapper.standardRequest(
213         ['open-ils.actor', 'open-ils.actor.user.fines.summary'],
214         {   async : true,
215             params : [this.authtoken, this.patron.id()],
216             oncomplete : function(r) {
217                 var summary = openils.Util.readResponse(r);
218                 dojo.byId('oils-selfck-fines-total').innerHTML = 
219                     dojo.string.substitute(
220                         localeStrings.TOTAL_FINES_ACCOUNT, 
221                         [summary.balance_owed()]
222                     );
223             }
224         }
225     );
226
227     // items out summary
228
229     this.updateHoldsSummary();
230     this.updateCircSummary();
231 }
232
233 SelfCheckManager.prototype.updateHoldsSummary = function(decrement) {
234
235
236     var self = this;
237     var oncomplete = function() {
238         dojo.byId('oils-selfck-holds-total').innerHTML = 
239             dojo.string.substitute(
240                 localeStrings.TOTAL_HOLDS, 
241                 [self.holdsSummary.total]
242             );
243
244         dojo.byId('oils-selfck-holds-ready').innerHTML = 
245             dojo.string.substitute(
246                 localeStrings.HOLDS_READY_FOR_PICKUP, 
247                 [self.holdsSummary.ready]
248             );
249     };
250
251     if(!this.holdsSummary) {
252         fieldmapper.standardRequest(
253             ['open-ils.circ', 'open-ils.circ.holds.user_summary'],
254             {   async : true,
255                 params : [this.authtoken, this.patron.id()],
256                 oncomplete : function(r) {
257                     var summary = openils.Util.readResponse(r);
258                     self.holdsSummary = {};
259                     self.holdsSummary.ready = Number(summary['4']);
260                     self.holdsSummary.total = 0;
261                     for(var i in summary) 
262                         self.holdsSummary.total += Number(summary[i]);
263                     oncomplete();
264                 }
265             }
266         );
267     } else {
268
269         if(this.decrement) 
270             this.holdsSummary.ready -= 1;
271     
272         oncomplete();
273     }
274 }
275
276
277 SelfCheckManager.prototype.updateCircSummary = function(increment) {
278
279     var self = this;
280     var oncomplete = function() {
281         dojo.byId('oils-selfck-circ-account-total').innerHTML = 
282             dojo.string.substitute(
283                 localeStrings.TOTAL_ITEMS_ACCOUNT, 
284                 [self.circSummary.total]
285             );
286
287         dojo.byId('oils-selfck-circ-session-total').innerHTML = 
288             dojo.string.substitute(
289                 localeStrings.TOTAL_ITEMS_SESSION, 
290                 [self.circSummary.session]
291             );
292     }
293
294     if(this.circSummary) {
295
296         if(increment) {
297             // local checkout occurred.  Add to the total and the session.
298             this.circSummary.total += 1;
299             this.circSummary.session += 1;
300         }
301
302         oncomplete();
303
304     } else {
305         // fetch the circ summary for the patron
306         var summary = fieldmapper.standardRequest(
307             ['open-ils.actor', 'open-ils.actor.user.checked_out.count'],
308             {
309                 async : true,
310                 params : [this.authtoken, this.patron.id()],
311                 oncomplete : function(r) {
312                     var summary = openils.Util.readResponse(r);
313                     self.circSummary = {
314                         total : Number(summary.out) + Number(summary.overdue),
315                         overdue : Number(summary.overdue),
316                         session : 0
317                     }
318                     oncomplete();
319                 }
320             }
321         );
322     }
323 }
324
325
326
327 /**
328  * Check out a single item.  If the item is already checked 
329  * out to the patron, redirect to renew()
330  */
331 SelfCheckManager.prototype.checkout = function(barcode, override) {
332
333     if(!barcode) {
334         this.updateScanbox(null, true);
335         return;
336     }
337
338     // TODO see if it's a patron barcode
339     // TODO see if this item has already been checked out in this session
340
341     var method = 'open-ils.circ.checkout.full';
342     if(override) method += '.override';
343
344     var result = fieldmapper.standardRequest(
345         ['open-ils.circ', 'open-ils.circ.checkout.full'],
346         {params: [
347             this.authtoken, {
348                 patron_id : this.patron.id(),
349                 copy_barcode : barcode
350             }
351         ]}
352     );
353
354
355     if(dojo.isArray(result)) {
356         // list of results.  See if we can override all of them.
357
358     } else {
359         var evt = openils.Event.parse(result);
360
361         switch(evt.textcode) {
362             // standard result events
363             
364             case 'SUCCESS':
365                 this.displayCheckout(evt);
366                 break;
367
368             case 'OPEN_CIRCULATION_EXISTS':
369                 // TODO renewal
370                 break;
371
372             case 'NO_SESSION':
373                 // TODO logout staff
374                 break;
375         }
376     }
377
378     console.log("Circ resulted in " + js2JSON(result));
379 }
380
381 /**
382  * Renew an item
383  */
384 SelfCheckManager.prototype.renew = function() {
385 }
386
387 /**
388  * Display the result of a checkout or renewal in the items out table
389  */
390 SelfCheckManager.prototype.displayCheckout = function(evt) {
391
392     var copy = evt.payload.copy;
393     var record = evt.payload.record;
394     var circ = evt.payload.circ;
395     var row = this.circTemplate.cloneNode(true);
396
397     /*
398     if(record.isbn()) {
399             var pic = $n(template, 'jacket');
400             pic.setAttribute('src', '/opac/ac/jacket/small/' + cleanISBN(record.isbn()));
401     }
402     */
403
404     this.byName(row, 'barcode').innerHTML = copy.barcode();
405     this.byName(row, 'title').innerHTML = record.title();
406     this.byName(row, 'author').innerHTML = record.author();
407     this.circTbody.appendChild(row);
408 }
409
410
411 SelfCheckManager.prototype.byName = function(node, name) {
412     return dojo.query('[name=' + name+']', node)[0];
413 }
414
415 /**
416  * Print a receipt
417  */
418 SelfCheckManager.prototype.printReceipt = function() {
419 }
420
421 /**
422  * Build the patron holds table
423  */
424 SelfCheckManager.prototype.displayHolds = function() {
425 }
426
427
428 /**
429  * Logout the patron and return to the login page
430  */
431 SelfCheckManager.prototype.logoutPatron = function() {
432 }
433
434
435 /**
436  * Fire up the manager on page load
437  */
438 openils.Util.addOnLoad(
439     function() {
440         new SelfCheckManager().init();
441     }
442 );