1 dojo.require('openils.CGI');
2 dojo.require('openils.Util');
3 dojo.require('openils.User');
4 dojo.require('openils.Event');
6 const SET_BARCODE_REGEX = 'opac.barcode_regex';
7 const SET_PATRON_TIMEOUT = 'circ.selfcheck.patron_login_timeout';
8 const SET_ALERT_ON_CHECKOUT_EVENT = 'circ.selfcheck.alert_on_checkout_event';
9 const SET_AUTO_OVERRIDE_EVENTS = 'circ.selfcheck.auto_override_checkout_events';
10 const SET_PATRON_PASSWORD_REQUIRED = 'circ.selfcheck.patron_password_required';
12 function SelfCheckManager() {
14 this.cgi = new openils.CGI();
16 this.workstation = null;
17 this.authtoken = null;
20 this.patronBarcodeRegex = null;
22 // current item barcode
23 this.itemBarcode = null;
25 // are we currently performing a renewal?
26 this.isRenewal = false;
28 // is a transaction pending?
29 this.pendingXact = false;
31 // dict of org unit settings for "here"
32 this.orgSettings = {};
36 * Fetch the org-unit settings, initialize the display, etc.
38 SelfCheckManager.prototype.init = function() {
40 this.staff = openils.User.user;
41 this.workstation = openils.User.workstation;
42 this.authtoken = openils.User.authtoken;
43 this.loadOrgSettings();
45 if(this.cgi.param('patron')) {
46 // Patron barcode via cgi param. Mainly used for debugging.
47 this.loginPatron(this.cgi.param('patron'));
54 * Loads the org unit settings
56 SelfCheckManager.prototype.loadOrgSettings = function() {
58 var settings = fieldmapper.aou.fetchOrgSettingBatch(
62 SET_ALERT_ON_CHECKOUT_EVENT,
63 SET_AUTO_OVERRIDE_EVENTS,
69 this.orgSettings[k] = settings[k].value;
72 if(settings[SET_BARCODE_REGEX])
73 this.patronBarcodeRegex = new RegExp(settings[SET_BARCODE_REGEX].value);
76 SelfCheckManager.prototype.drawLoginPage = function() {
79 var bcHandler = function(barcode) {
80 // handle patron barcode entry
82 if(self.orgSettings[SET_PATRON_PASSWORD_REQUIRED]) {
84 // password is required. wire up the scan box to read it
86 msg : 'Please enter your password', // TODO i18n
87 handler : function(pw) { self.loginPatron(barcode, ps); }
90 dojo.connect(selfckScanBox, 'onKeyDown', pwHandler);
93 // password is not required, go ahead and login
94 self.loginPatron(barcode);
99 msg : 'Please log in with your library barcode.', // TODO
107 SelfCheckManager.prototype.loginPatron = function(barcode, passwd) {
108 console.log('loginPatron: ' + barcode);
110 if(this.orgSettings[SET_PATRON_PASSWORD_REQUIRED]) {
112 // patron password is required. Verify it.
114 var res = fieldmapper.standardRequest(
115 ['open-ils.actor', 'open-ils.actor.verify_user_password'],
116 {params : [this.authtoken, barcode, null, hex_md5(passwd)]}
120 return alert('login failed'); // TODO
124 // retrieve the fleshed user by barcode
125 this.patron = fieldmapper.standardRequest(
126 ['open-ils.actor', 'open-ils.actor.user.fleshed.retrieve_by_barcode'],
127 {params : [this.authtoken, barcode]}
130 var evt = openils.Event.parse(this.patron);
133 // User login failed, why?
135 switch(evt.textcode) {
137 case 'ACTOR_USER_NOT_FOUND':
138 return alert('user not found'); // TODO
141 return alert('staff login timed out'); // TODO
144 return alert('unexpected patron login error occured: ' + evt.textcode); // TODO
148 // patron login succeeded
149 dojo.byId('oils-selfck-user-banner').innerHTML = 'Welcome, ' + this.patron.usrname(); // TODO i18n
155 * Manages the main input box
156 * @param msg The context message to display with the box
157 * @param clearOnly Don't update the context message, just clear the value and re-focus
158 * @param handler Optional "on-enter" handler.
160 SelfCheckManager.prototype.updateScanBox = function(args) {
162 selfckScanBox.attr('value', '');
165 selfckScanBox.attr('value', args.value);
168 dojo.byId('oils-selfck-scan-text').innerHTML = args.msg;
170 if(selfckScanBox._lastHandler && (args.handler || args.clearHandler)) {
171 console.log('disconnecting ' + selfckScanBox._lastHandler);
172 dojo.disconnect(selfckScanBox._lastHandler);
176 console.log('updating scan box with ['+args.msg+'] and handler ' + args.handler);
178 selfckScanBox._lastHandler = dojo.connect(
182 if(e.keyCode != dojo.keys.ENTER)
184 args.handler(selfckScanBox.attr('value'));
189 selfckScanBox.focus();
193 * Sets up the checkout/renewal interface
195 SelfCheckManager.prototype.drawCircPage = function() {
199 msg : 'Please enter an item barcode', // TODO i18n
200 handler : function(barcode) { self.checkout(barcode); }
203 openils.Util.show('oils-selfck-circ-page');
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'));
213 * Check out a single item. If the item is already checked
214 * out to the patron, redirect to renew()
216 SelfCheckManager.prototype.checkout = function(barcode, override) {
219 this.updateScanbox(null, true);
223 // TODO see if it's a patron barcode
224 // TODO see if this item has already been checked out in this session
226 var method = 'open-ils.circ.checkout.full';
227 if(override) method += '.override';
229 var result = fieldmapper.standardRequest(
230 ['open-ils.circ', 'open-ils.circ.checkout.full'],
233 patron_id : this.patron.id(),
234 copy_barcode : barcode
240 if(dojo.isArray(result)) {
241 // list of results. See if we can override all of them.
244 var evt = openils.Event.parse(result);
246 switch(evt.textcode) {
247 // standard result events
250 this.displayCheckout(evt);
253 case 'OPEN_CIRCULATION_EXISTS':
263 console.log("Circ resulted in " + js2JSON(result));
269 SelfCheckManager.prototype.renew = function() {
273 * Display the result of a checkout or renewal in the items out table
275 SelfCheckManager.prototype.displayCheckout = function(evt) {
277 var copy = evt.payload.copy;
278 var record = evt.payload.record;
279 var circ = evt.payload.circ;
280 var row = this.circTemplate.cloneNode(true);
284 var pic = $n(template, 'jacket');
285 pic.setAttribute('src', '/opac/ac/jacket/small/' + cleanISBN(record.isbn()));
289 this.byName(row, 'barcode').innerHTML = copy.barcode();
290 this.byName(row, 'title').innerHTML = record.title();
291 this.byName(row, 'author').innerHTML = record.author();
292 this.circTbody.appendChild(row);
296 SelfCheckManager.prototype.byName = function(node, name) {
297 return dojo.query('[name=' + name+']', node)[0];
303 SelfCheckManager.prototype.printReceipt = function() {
307 * Build the patron holds table
309 SelfCheckManager.prototype.displayHolds = function() {
314 * Logout the patron and return to the login page
316 SelfCheckManager.prototype.logoutPatron = function() {
321 * Fire up the manager on page load
323 openils.Util.addOnLoad(
325 new SelfCheckManager().init();