checkout from patron barcode entry UI
authorBill Erickson <berick@esilibrary.com>
Thu, 1 May 2014 19:03:54 +0000 (15:03 -0400)
committerBill Erickson <berick@esilibrary.com>
Thu, 1 May 2014 19:03:54 +0000 (15:03 -0400)
* includes opt-in logic
* includes link from splash page

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/index.tt2
Open-ILS/src/templates/staff/circ/patron/t_bcsearch.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/t_splash.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/app.js

index 7a99b7b..14c87b7 100644 (file)
 <!-- TODO: APP_JS should really be called APP_ADDONS or some such.
     It just means "load these things, too, and load them last" -->
 <link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ/patron.css" />
+
+<script>
+// this could live in a .tt2 file instead -- if it gets large
+angular.module('egCoreMod').factory('egAppStrings', function() {return {
+OPT_IN_DIALOG : 
+    '[% l('Does patron {{user.family_name()}}, {{user.first_given_name()}} from {{org.name()}} ({{org.shortname()}}) consent to having their personal information shared with your library?') %]'
+}});
+</script>
+
 [% END %]
 
 <div class="row">
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bcsearch.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bcsearch.tt2
new file mode 100644 (file)
index 0000000..8396e23
--- /dev/null
@@ -0,0 +1,28 @@
+
+<form ng-submit="submitBarcode(args)" role="form" class="form-inline">
+  <div class="input-group">
+
+    <label class="input-group-addon" 
+      for="patron-checkout-barcode" >[% l('Patron Barcode') %]</label>
+
+    <input select-me="selectMe" class="form-control"
+      ng-model="args.barcode" 
+      placeholder="[% l('Patron Barcode') %]"
+      id="patron-checkout-barcode" type="text"/> 
+
+    <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+
+    <!-- do we really need a button?
+    <span class="input-group-btn">
+      <input type="submit" class="btn btn-default" value="[% l('Submit') %]"/>
+    </span>
+    -->
+  </div>
+</form>
+
+<br/>
+<div class="alert alert-warning" ng-show="bcNotFound">
+  [% l('Barcode Not Found: [_1]', '{{bcNotFound}}') %]
+</div>
+
+
index cc8e5cf..d259698 100644 (file)
         </div>
         <div class="panel-body">
           <div>
-            <img src="/xul/server/skin/media/images/portal/retreivepatron.png"/>
-            <a target="_self" href="./circ/patron/search">[% l('Find Patrons / Checkout') %]</a>
+            <img src="/xul/server/skin/media/images/portal/forward.png"/>
+            <a target="_self" href="./circ/patron/bcsearch">[% l('Check Out Items') %]</a>
           </div>
           <div>
             <img src="/xul/server/skin/media/images/portal/back.png"/>
             <a target="_self" href="./circ/checkin/index">[% l('Check In Items') %]</a>
           </div>
+          <div>
+            <img src="/xul/server/skin/media/images/portal/retreivepatron.png"/>
+            <a target="_self" href="./circ/patron/search">[% l('Search For Patron By Name') %]</a>
+          </div>
         </div>
       </div>
     </div>
               [% l('Evergreen Documentation') %]
             </a>
           </div>
+          <div>
+            <img src="/xul/server/skin/media/images/portal/helpdesk.png"/>
+            <a target="_top" href="./admin/workstation/index">
+              [% l('Workstation Administration') %]
+            </a>
+          </div>
         </div>
       </div>
     </div>
index e2ebb30..2fa5a19 100644 (file)
@@ -52,6 +52,13 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap',
         resolve : resolver
     });
 
+    $routeProvider.when('/circ/patron/bcsearch', {
+        templateUrl: './circ/patron/t_bcsearch',
+        controller: 'PatronBarcodeSearchCtrl',
+        resolve : resolver
+    });
+
+
     $routeProvider.when('/circ/patron/:id/checkout', {
         templateUrl: './circ/patron/t_checkout',
         controller: 'PatronCheckoutCtrl',
@@ -152,6 +159,12 @@ function($q , $timeout , egNet,  egAuth,  egUser,  egEnv,  egOrg) {
                         "unable to fetch user "+id+': '+js2JSON(err))
                 }
             );
+        } else {
+
+            // reset with no patron
+            service.resetPatronLists();
+            service.current = null;
+            service.patron_stats = null;
         }
     }
 
@@ -215,6 +228,93 @@ function($scope,  $q,  $filter,  egNet,  egAuth,  egUser,  patronSvc,  egEnv,  e
     $scope.patron_stats = function() { return patronSvc.patron_stats }
 }])
 
+.controller('PatronBarcodeSearchCtrl',
+       ['$scope','$location','egAuth','egNet','egEvent','egOrg','egConfirmDialog','egUser','egAppStrings','patronSvc',
+function($scope , $location , egAuth , egNet , egEvent , egOrg , egConfirmDialog , egUser , egAppStrings , patronSvc) {
+    $scope.selectMe = true; // focus text input
+    patronSvc.setDefault(); // clear the default user
+
+    // jump to the patron checkout UI
+    function loadPatron(user_id) {
+        $location.path('/circ/patron/' + user_id + '/checkout');
+    }
+
+    // create an opt-in=yes response for the loaded user
+    function createOptIn(user_id) {
+        egNet.request(
+            'open-ils.actor',
+            'open-ils.actor.user.org_unit_opt_in.create',
+            egAuth.token(), user_id).then(function(resp) {
+                if (evt = egEvent.parse(resp)) return alert(evt);
+                loadPatron(user_id);
+            }
+        );
+    }
+
+    $scope.submitBarcode = function(args) {
+        $scope.bcNotFound = null;
+        if (!args.barcode) return;
+
+        // blur so next time it's set to true it will re-apply select()
+        $scope.selectMe = false;
+
+        var user_id;
+
+        // lookup barcode
+        egNet.request(
+            'open-ils.actor',
+            'open-ils.actor.get_barcodes',
+            egAuth.token(), egAuth.user().ws_ou(), 'actor', args.barcode)
+
+        .then(function(resp) { // get_barcodes
+
+            if (evt = egEvent.parse(resp)) {
+                alert(evt); // FIXME
+                return;
+            }
+
+            if (!resp || !resp[0]) {
+                $scope.bcNotFound = args.barcode;
+                $scope.selectMe = true;
+                return;
+            }
+
+            // see if an opt-in request is needed
+            user_id = resp[0].id;
+            return egNet.request(
+                'open-ils.actor',
+                'open-ils.actor.user.org_unit_opt_in.check',
+                egAuth.token(), user_id);
+
+        }).then(function(optInResp) { // opt_in_check
+
+            if (evt = egEvent.parse(optInResp)) {
+                alert(evt); // FIXME
+                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 : []})
+
+            .then(function(user) { // retrieve user
+                egConfirmDialog.open(
+                    egAppStrings.OPT_IN_DIALOG, '',
+                    {   org : egOrg.get(egAuth.user().ws_ou()),
+                        user : user,
+                        ok : function() { createOptIn(user.id()) },
+                        cancel : function() {}
+                    }
+                );
+            })
+        });
+    }
+}])
+
 
 /**
  * Manages patron search