take steps to block checking out to patrons with certain conditions
authorGalen Charlton <gmc@equinoxinitiative.org>
Fri, 5 Jun 2020 22:11:27 +0000 (18:11 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Fri, 5 Jun 2020 22:12:25 +0000 (18:12 -0400)
To wit:

- patron is inactive
- patron is barred
- patron is expired
- patron has active standing penalties that block CIRC

Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/perlmods/lib/OpenILS/Application/Curbside.pm
Open-ILS/src/templates/staff/circ/curbside/t_arrived_manager.tt2
Open-ILS/src/templates/staff/circ/curbside/t_staged_manager.tt2
Open-ILS/src/templates/staff/circ/curbside/t_to_be_staged_manager.tt2
Open-ILS/web/js/ui/default/staff/circ/curbside/directives/arrived_manager.js
Open-ILS/web/js/ui/default/staff/circ/curbside/directives/staged_manager.js
Open-ILS/web/js/ui/default/staff/circ/curbside/directives/to_be_staged_manager.js
Open-ILS/web/js/ui/default/staff/circ/curbside/services/core.js

index 606a917..8379bf3 100644 (file)
@@ -237,7 +237,7 @@ sub fetch_arrived {
     },{
         ($limit  ? (limit  => $limit) : ()),
         ($offset ? (offset => $offset) : ()),
-        flesh => 2, flesh_fields => {acsp => ['patron'], au => ['card','standing_penalties']},
+        flesh => 3, flesh_fields => {acsp => ['patron'], au => ['card','standing_penalties'], ausp => ['standing_penalty']},
         order_by => { acsp => 'arrival' }
     }]);
 
@@ -324,7 +324,7 @@ sub fetch_staged {
     },{
         ($limit  ? (limit  => $limit) : ()),
         ($offset ? (offset => $offset) : ()),
-        flesh => 2, flesh_fields => {acsp => ['patron'], au => ['card','standing_penalties']},
+        flesh => 3, flesh_fields => {acsp => ['patron'], au => ['card','standing_penalties'], ausp => ['standing_penalty']},
         order_by => { acsp => 'slot' }
     }]);
 
@@ -419,7 +419,7 @@ sub fetch_to_be_staged {
     },{
         ($limit  ? (limit  => $limit) : ()),
         ($offset ? (offset => $offset) : ()),
-        flesh => 2, flesh_fields => {acsp => ['patron'], au => ['card','standing_penalties']},
+        flesh => 3, flesh_fields => {acsp => ['patron'], au => ['card','standing_penalties'], ausp => ['standing_penalty']},
         order_by => { acsp => 'slot' }
     }]);
 
index 6123028..bdc350b 100644 (file)
@@ -13,7 +13,7 @@
         label="[% l('Refresh List')%]"></eg-grid-menu-item>
 
     <eg-grid-field label="[% l('Pickup Date/Time') %]" path="slot.slot" datatype="timestamp"></eg-grid-field>
-    <eg-grid-field label="[% l('Patron') %]" path="slot.patron" compiled>
+    <eg-grid-field label="[% l('Patron') %]" path="slot.patron" compiled handlers="gridCellHandlers">
       <a href="./circ/patron/{{item.slot.patron().id()}}/holds" target="_blank">
         {{item.slot.patron().family_name()}} / {{item.slot.patron().card().barcode()}}
         <span class="glyphicon glyphicon-new-window"></span>
       <span ng-show="item.slot.notes()">
         <strong>[% l('Notes:') %]</strong> {{item.slot.notes()}}
       </span>
+      <div class="alert alert-warning" ng-show="col.handlers.patronIsBlocked(item['slot'].patron())">
+        [% l('Patron is blocked from checkouts.') %]
+      </div>
     </eg-grid-field>
     <eg-grid-field label="[% l('Appointment ID') %]" path="slot.id"></eg-grid-field>
     <eg-grid-field label="[% l('Action') %]" handlers="gridCellHandlers" compiled>
       <button class="btn btn-sm btn-primary"
-        ng-disabled="col.handlers.wasHandled(item['slot_id'])"
+        ng-disabled="col.handlers.wasHandled(item['slot_id']) || col.handlers.patronIsBlocked(item['slot'].patron())"
         ng-click="col.handlers.mark_delivered(item['slot_id'])">
         [% l('Check Out Items And Mark As Delivered') %]
       </button>
index c2a6023..9d3c580 100644 (file)
@@ -13,7 +13,7 @@
         label="[% l('Refresh List')%]"></eg-grid-menu-item>
 
     <eg-grid-field label="[% l('Pickup Date/Time') %]" path="slot.slot" datatype="timestamp"></eg-grid-field>
-    <eg-grid-field label="[% l('Patron') %]" path="slot.patron" compiled>
+    <eg-grid-field label="[% l('Patron') %]" path="slot.patron" compiled handlers="gridCellHandlers">
       <a href="./circ/patron/{{item.slot.patron().id()}}/holds" target="_blank">
         {{item.slot.patron().family_name()}} / {{item.slot.patron().card().barcode()}}
         <span class="glyphicon glyphicon-new-window"></span>
       <span ng-show="item.slot.notes()">
         <strong>[% l('Notes:') %]</strong> {{item.slot.notes()}}
       </span>
+      <div class="alert alert-warning" ng-show="col.handlers.patronIsBlocked(item['slot'].patron())">
+        [% l('Patron is blocked from checkouts.') %]
+      </div>
     </eg-grid-field>
     <eg-grid-field label="[% l('Appointment ID') %]" path="slot.id"></eg-grid-field>
     <eg-grid-field label="[% l('Action') %]" handlers="gridCellHandlers" compiled>
       <div class="row">
         <div class="col-xs-12">
           <button class="btn btn-sm btn-primary"
-            ng-disabled="col.handlers.wasHandled(item['slot_id'])"
+            ng-disabled="col.handlers.wasHandled(item['slot_id']) || col.handlers.patronIsBlocked(item['slot'].patron())"
             ng-click="col.handlers.mark_arrived(item['slot_id'])">
             [% l('Mark As Patron Arrived') %]
           </button>
@@ -37,7 +40,7 @@
       <div class="row">
         <div class="col-xs-12">
           <button class="btn btn-sm btn-success"
-            ng-disabled="col.handlers.wasHandled(item['slot_id'])"
+            ng-disabled="col.handlers.wasHandled(item['slot_id']) || col.handlers.patronIsBlocked(item['slot'].patron())"
             ng-click="col.handlers.mark_delivered(item['slot_id'])">
             [% l('Check Out Items And Mark As Delivered') %]
           </button>
index a4f504f..ffe98df 100644 (file)
@@ -13,7 +13,7 @@
         label="[% l('Refresh List')%]"></eg-grid-menu-item>
 
     <eg-grid-field label="[% l('Pickup Date/Time') %]" path="slot.slot" datatype="timestamp"></eg-grid-field>
-    <eg-grid-field label="[% l('Patron') %]" path="slot.patron" compiled>
+    <eg-grid-field label="[% l('Patron') %]" path="slot.patron" compiled handlers="gridCellHandlers">
       <a href="./circ/patron/{{item.slot.patron().id()}}/holds" target="_blank">
         {{item.slot.patron().family_name()}} / {{item.slot.patron().card().barcode()}}
         <span class="glyphicon glyphicon-new-window"></span>
@@ -22,6 +22,9 @@
       <span ng-show="item.slot.notes()">
         <strong>[% l('Notes:') %]</strong> {{item.slot.notes()}}
       </span>
+      <div class="alert alert-warning" ng-show="col.handlers.patronIsBlocked(item['slot'].patron())">
+        [% l('Patron is blocked from checkouts.') %]
+      </div>
     </eg-grid-field>
     <eg-grid-field label="[% l('Appointment ID') %]" path="slot.id"></eg-grid-field>
     <eg-grid-field label="[% l('Items for Pickup') %]" path="holds" compiled>
@@ -29,7 +32,7 @@
     </eg-grid-field>
     <eg-grid-field label="[% l('Action') %]" handlers="gridCellHandlers" compiled>
       <button class="btn btn-sm btn-primary"
-        ng-disabled="col.handlers.wasHandled(item['slot_id'])"
+        ng-disabled="col.handlers.wasHandled(item['slot_id']) || col.handlers.patronIsBlocked(item['slot'].patron())"
         ng-click="col.handlers.mark_staged(item['slot_id'])">
         [% l('Mark As Staged And Ready') %]
       </button>
index 5c24ff4..1613279 100644 (file)
@@ -90,5 +90,8 @@ function($scope , $q , egCurbsideCoreSvc , egCore , egGridDataProvider , egProgr
     $scope.gridCellHandlers.wasHandled = function(id) {
         return $scope.wasHandled[id];
     }
+    $scope.gridCellHandlers.patronIsBlocked = function(usr) {
+        return egCurbsideCoreSvc.patron_blocked(usr);
+    }
 
 }]}});
index 915582d..2f0050c 100644 (file)
@@ -138,5 +138,8 @@ function($scope , $q , egCurbsideCoreSvc , egCore , egGridDataProvider , egProgr
     $scope.gridCellHandlers.wasHandled = function(id) {
         return $scope.wasHandled[id];
     }
+    $scope.gridCellHandlers.patronIsBlocked = function(usr) {
+        return egCurbsideCoreSvc.patron_blocked(usr);
+    }
 
 }]}});
index e99e319..b3c7efc 100644 (file)
@@ -11,7 +11,6 @@ angular.module('egCurbsideAppDep')
         '$uibModal','$timeout','$location','egConfirmDialog','ngToast','$interval',
 function($scope , $q , egCurbsideCoreSvc , egCore , egGridDataProvider ,
          $uibModal , $timeout , $location , egConfirmDialog , ngToast , $interval) {
-console.debug('GMC');
 
     $scope.gridControls = {};
 
@@ -89,5 +88,8 @@ console.debug('GMC');
     $scope.gridCellHandlers.wasHandled = function(id) {
         return $scope.wasHandled[id];
     }
+    $scope.gridCellHandlers.patronIsBlocked = function(usr) {
+        return egCurbsideCoreSvc.patron_blocked(usr);
+    }
 
 }]}});
index dc5faa1..1dcd3b0 100644 (file)
@@ -133,6 +133,25 @@ function(egCore , orderByFilter , $q , $filter , $uibModal , ngToast , egConfirm
         );
     }
 
+    service.patron_blocked = function(usr) {
+        if (usr.barred() == 't' ||
+            usr.active() == 'f') {
+            return true;
+        }
+        var expire = Date.parse(usr.expire_date());
+        if (expire < new Date()) {
+            return true;
+        }
+        var blocked_by_penalty = false;
+        angular.forEach(usr.standing_penalties(), function(penalty) {
+            if (blocked_by_penalty) return;
+            if (penalty.stop_date()) return;
+            if (!penalty.standing_penalty().block_list()) return;
+            if (penalty.standing_penalty().block_list().match(/CIRC/))
+                blocked_by_penalty = true;
+        });
+        return blocked_by_penalty;
+    }
 
     return service;
 }])