From b2788373d4bd1b8125a67b1aa3709f7da8e3108b Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Fri, 6 Oct 2017 11:15:05 -0700 Subject: [PATCH] LP#1706147: handle multiple matches on patron barcode completion in web client To test: 1. Add a barcode completion rule for BR1, applying to users and set to active, where "BR1" is the prefix. 2. Create a user with barcode "BR100001" and home library BR1. 3. Create another user with barcode "00001". 4. Login to the web client with BR1 as your working location. Go to "Check Out Item" and enter barcode "00001". EG will retrieve one of the two accounts you created; it ought to present a dialog that allows you to choose between BR00001 and 00001 (or none of the above). Signed-off-by: Jeff Davis Signed-off-by: Cesar Velez Signed-off-by: Galen Charlton --- .../js/ui/default/staff/circ/patron/app.js | 165 ++++++++++++------ 1 file changed, 110 insertions(+), 55 deletions(-) diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js index f92eac1096..eaaf9ba037 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js @@ -436,8 +436,8 @@ function($scope, $q , $location , $filter , egCore , egNet , egUser , egAlertDi }]) .controller('PatronBarcodeSearchCtrl', - ['$scope','$location','egCore','egConfirmDialog','egUser','patronSvc', -function($scope , $location , egCore , egConfirmDialog , egUser , patronSvc) { + ['$scope','$location','egCore','egConfirmDialog','egUser','patronSvc','$uibModal','$q', +function($scope , $location , egCore , egConfirmDialog , egUser , patronSvc , $uibModal , $q) { $scope.selectMe = true; // focus text input patronSvc.clearPrimary(); // clear the default user @@ -472,72 +472,127 @@ function($scope , $location , egCore , egConfirmDialog , egUser , patronSvc) { var user_id; - // lookup barcode - egCore.net.request( - 'open-ils.actor', - 'open-ils.actor.get_barcodes', - egCore.auth.token(), egCore.auth.user().ws_ou(), - 'actor', args.barcode) + // given a scanned barcode, this function finds any matching users + // and handles multiple matches due to barcode completion + function handleBarcodeCompletion(scanned_barcode) { + var deferred = $q.defer(); - .then(function(resp) { // get_barcodes + egCore.net.request( + 'open-ils.actor', + 'open-ils.actor.get_barcodes', + egCore.auth.token(), egCore.auth.user().ws_ou(), + 'actor', scanned_barcode) - if (evt = egCore.evt.parse(resp)) { - alert(evt); // FIXME - return; - } + .then(function(resp) { // get_barcodes - if (!resp || !resp[0]) { - $scope.bcNotFound = args.barcode; - $scope.selectMe = true; - egCore.audio.play('warning.patron.not_found'); - return; - } + if (evt = egCore.evt.parse(resp)) { + alert(evt); // FIXME + deferred.reject(); + return; + } + + if (!resp || !resp[0]) { + $scope.bcNotFound = args.barcode; + $scope.selectMe = true; + egCore.audio.play('warning.patron.not_found'); + deferred.reject(); + return; + } + + if (resp.length == 1) { + // exactly one matching barcode: return it + deferred.resolve(); + user_id = resp[0].id; + } else { + // multiple matching barcodes: let the user pick one + var barcode_map = {}; + var matches = []; + var promises = []; + var selected_barcode; + angular.forEach(resp, function(match) { + promises.push( + egUser.get(match.id, {useFields : ['home_ou']}).then(function(user) { + barcode_map[match.barcode] = user.id(); + matches.push( { + barcode: match.barcode, + title: user.first_given_name() + ' ' + user.family_name(), + org_name: user.home_ou().name(), + org_shortname: user.home_ou().shortname() + }); + }) + ); + }); + return $q.all(promises) + .then(function() { + $uibModal.open({ + templateUrl: './circ/share/t_barcode_choice_dialog', + controller: + ['$scope', '$uibModalInstance', + function($scope, $uibModalInstance) { + $scope.matches = matches; + $scope.ok = function(barcode) { + $uibModalInstance.close(); + selected_barcode = barcode; + } + $scope.cancel = function() {$uibModalInstance.dismiss()} + }], + }).result.then(function() { + deferred.resolve(); + user_id = barcode_map[selected_barcode]; + }); + }); + } + }); + return deferred.promise; + } + + // call our function to lookup matching users for the scanned barcode + handleBarcodeCompletion(args.barcode).then(function() { // see if an opt-in request is needed - user_id = resp[0].id; return egCore.net.request( 'open-ils.actor', 'open-ils.actor.user.org_unit_opt_in.check', - egCore.auth.token(), user_id); + egCore.auth.token(), user_id + ).then(function(optInResp) { // opt_in_check - }).then(function(optInResp) { // opt_in_check - - if (evt = egCore.evt.parse(optInResp)) { - alert(evt); // FIXME - return; - } + if (evt = egCore.evt.parse(optInResp)) { + alert(evt); // FIXME + return; + } - if (optInResp == 2) { - // opt-in disallowed at this location by patron's home library - $scope.optInRestricted = true; - $scope.selectMe = true; - egCore.audio.play('warning.patron.opt_in_restricted'); - return; - } - - if (optInResp == 1) { - // opt-in handled or not needed - return loadPatron(user_id); - } + if (optInResp == 2) { + // opt-in disallowed at this location by patron's home library + $scope.optInRestricted = true; + $scope.selectMe = true; + egCore.audio.play('warning.patron.opt_in_restricted'); + return; + } + + if (optInResp == 1) { + // opt-in handled or not needed + return loadPatron(user_id); + } - // opt-in needed, show the opt-in dialog - egUser.get(user_id, {useFields : []}) + // opt-in needed, show the opt-in dialog + egUser.get(user_id, {useFields : []}) - .then(function(user) { // retrieve user - var org = egCore.org.get(user.home_ou()); - egConfirmDialog.open( - egCore.strings.OPT_IN_DIALOG_TITLE, - egCore.strings.OPT_IN_DIALOG, - { family_name : user.family_name(), - first_given_name : user.first_given_name(), - org_name : org.name(), - org_shortname : org.shortname(), - ok : function() { createOptIn(user.id()) }, - cancel : function() {} - } - ); + .then(function(user) { // retrieve user + var org = egCore.org.get(user.home_ou()); + egConfirmDialog.open( + egCore.strings.OPT_IN_DIALOG_TITLE, + egCore.strings.OPT_IN_DIALOG, + { family_name : user.family_name(), + first_given_name : user.first_given_name(), + org_name : org.name(), + org_shortname : org.shortname(), + ok : function() { createOptIn(user.id()) }, + cancel : function() {} + } + ); + }) }) - }); + }) } }]) -- 2.43.2