group member details; patron tab numbers
authorBill Erickson <berick@esilibrary.com>
Tue, 10 Jun 2014 15:45:58 +0000 (11:45 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 10 Jun 2014 15:45:58 +0000 (11:45 -0400)
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_add_to_group_dialog.tt2 [deleted file]
Open-ILS/src/templates/staff/circ/patron/t_group.tt2
Open-ILS/src/templates/staff/circ/patron/t_move_to_group_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/css/circ/patron.css.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/app.js

index c08791d..b7ec957 100644 (file)
@@ -72,13 +72,25 @@ angular.module('egCoreMod').run(['egStrings', function(s) {
         <a href="./circ/patron/{{patron().id()}}/checkout">[% l('Check Out') %]</a>
       </li>
       <li ng-class="{active : tab == 'items_out', disabled : !patron()}">
-        <a href="./circ/patron/{{patron().id()}}/items_out">[% l('Items Out') %]</a>
+        <a href="./circ/patron/{{patron().id()}}/items_out">
+          [% l('Items Out') %] 
+          <span ng-if="patron()"><!-- lack of space / newline below intentional -->
+          (<span ng-class="{'patron-summary-alert-small' : patron_stats().checkouts.overdue}">{{patron_stats().checkouts.total_out}}</span>)
+          </span>
+        </a>
       </li>
       <li ng-class="{active : tab == 'holds', disabled : !patron()}">
-        <a href="./circ/patron/{{patron().id()}}/holds">[% l('Holds') %]</a>
+        <a href="./circ/patron/{{patron().id()}}/holds">
+          [% l('Holds') %]
+          <span ng-if="patron()">
+            (<span>{{patron_stats().holds.total}} / {{patron_stats().holds.ready}}</span>)
+          </span>
+        </a>
       </li>
       <li ng-class="{active : tab == 'bills', disabled : !patron()}">
-        <a href="./circ/patron/{{patron().id()}}/bills">[% l('Bills') %]</a>
+        <a href="./circ/patron/{{patron().id()}}/bills">
+          [% l('Bills') %]
+        </a>
       </li>
       <li ng-class="{active : tab == 'messages', disabled : !patron()}">
         <a href="./circ/patron/{{patron().id()}}/messages">[% l('Messages') %]</a>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_add_to_group_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_add_to_group_dialog.tt2
deleted file mode 100644 (file)
index caa1d84..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<div>
-  <div class="modal-header">
-    <button type="button" class="close" ng-click="cancel()" 
-      aria-hidden="true">&times;</button>
-    <h4 class="modal-title">[% l('Move user into this group?') %]</h4>
-  </div>
-  <div class="modal-body">
-    <a href="./circ/patron/{{user.id()}}/checkout" target="_self">
-      [% 
-        l('[_1], [_2] [_3] : [_4]', 
-          '{{user.family_name()}}',
-          '{{user.first_given_name()}}',
-          '{{user.second_given_name()}}',
-          '{{user.card().barcode()}}') 
-      %]
-    </a>
-  </div>
-  <div class="modal-footer">
-    <button class="btn btn-primary" ng-click="ok()">[% l('Move User') %]</button>
-    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
-  </div>
-</div>
index 9a74166..8d28161 100644 (file)
@@ -1,5 +1,13 @@
 
 <div class="strong-text-2">[% l('Group Member Details') %]</div>
+<div class="pad-vert flex-row">
+  <div>[% l('Total Owed: ') %]</div>
+  <div class="pad-horiz">{{totals.owed | currency}}</div>
+  <div>[% l('Total Out: ') %]</div>
+  <div class="pad-horiz">{{totals.total_out}}</div>
+  <div>[% l('Total Overdue: ') %]</div>
+  <div class="pad-horiz">{{totals.overdue}}</div>
+</div>
 <div class="pad-vert"></div>
 <eg-grid
   idl-class="au"
@@ -15,6 +23,9 @@
   <eg-grid-action label="[% l('Remove Selected From Group') %]" 
     handler="removeFromGroup"></eg-grid-action>
 
+  <eg-grid-action label="[% l("Move Selected Patrons to Another Patron's Group") %]" 
+    handler="moveToAnotherGroup"></eg-grid-action>
+
   <eg-grid-field path="active"></eg-grid-field>
   <eg-grid-field path="barred"></eg-grid-field>
   <eg-grid-field path="dob"></eg-grid-field>
@@ -23,7 +34,7 @@
   <eg-grid-field path="master_account"></eg-grid-field>
   <eg-grid-field path="second_given_name"></eg-grid-field>
   <eg-grid-field path="stats.fines.balance_owed" nonsortable label="[% l('Balance Owed') %]"></eg-grid-field>
-  <eg-grid-field path="stats.checkouts.count" nonsortable label="[% l('Items Out') %]"></eg-grid-field>
+  <eg-grid-field path="stats.checkouts.out" nonsortable label="[% l('Items Out') %]"></eg-grid-field>
   <eg-grid-field path="stats.checkouts.overdue" nonsortable label="[% l('Items Overdue') %]"></eg-grid-field>
 
   <!-- needed for query, sorting -->
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_move_to_group_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_move_to_group_dialog.tt2
new file mode 100644 (file)
index 0000000..96e9733
--- /dev/null
@@ -0,0 +1,28 @@
+<div>
+  <div class="modal-header">
+    <button type="button" class="close" ng-click="cancel()" 
+      aria-hidden="true">&times;</button>
+    <h4 ng-if="!outbound" class="modal-title">
+      [% l('Move user into this group?') %]
+    </h4>
+    <h4 ng-if="outbound" class="modal-title">
+      [% l("Move selected users to the following user's group?") %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <a href="./circ/patron/{{user.id()}}/checkout" target="_self">
+      [% 
+        l('[_1], [_2] [_3] : [_4]', 
+          '{{user.family_name()}}',
+          '{{user.first_given_name()}}',
+          '{{user.second_given_name()}}',
+          '{{user.card().barcode()}}') 
+      %]
+    </a>
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-primary" ng-click="ok()">[% l('Move User') %]</button>
+    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
index d768865..f81b787 100644 (file)
@@ -5,6 +5,7 @@
 /* there are bootstrap tyles for error, warning, etc., 
 but the ones I'm finding aren't quite cutting it..*/
 .patron-summary-alert {color: red; font-weight:bold}
+.patron-summary-alert-small {color: red}
 
 .patron-summary-divider { border-top: 1px solid #CCC}
 #patron-checkout-barcode { width: 16em; }
index c312212..71bdb98 100644 (file)
@@ -343,6 +343,9 @@ function($q , $timeout , $location , egCore,  egUser , $locale) {
                 stats.checkouts.claims_returned = 
                     Number(stats.checkouts.claims_returned);
                 stats.checkouts.lost = Number(stats.checkouts.lost);
+                stats.checkouts.out = Number(stats.checkouts.out);
+                stats.checkouts.total_out = 
+                    stats.checkouts.out + stats.checkouts.overdue;
                 return stats;
             }
         );
@@ -1110,6 +1113,7 @@ function($scope,  $routeParams , $q , $location , egCore ,
 
     var statsCache = {};
     var gridQuery = {};
+    $scope.totals = {owed : 0, total_out : 0, overdue : 0}
 
     $scope.gridQuery = function() {return gridQuery}
     $scope.gridRevision = 0;
@@ -1123,6 +1127,8 @@ function($scope,  $routeParams , $q , $location , egCore ,
                 // user retrieved, flesh their stats
                 patronSvc.getUserStats(item.id).then(function(stats) {
                     item.stats = statsCache[item.id] = stats;
+                    $scope.totals.total_out += stats.checkouts.total_out; 
+                    $scope.totals.overdue += stats.checkouts.overdue; 
                 });
             }
         }
@@ -1134,6 +1140,7 @@ function($scope,  $routeParams , $q , $location , egCore ,
             usrgroup : patronSvc.current.usrgroup(),
             deleted : 'f'
         }
+        $scope.totals.owed = patronSvc.patron_stats.fines.group_balance_owed;
     });
 
     $scope.removeFromGroup = function(selected) {
@@ -1166,7 +1173,33 @@ function($scope,  $routeParams , $q , $location , egCore ,
         });
     }
 
-    function showMoveToGroupConfirm(barcode) {
+    // fetch each user ("selected" has flattened users)
+    // update the usrgroup, then update the user object
+    // After all updates are complete, refresh the grid.
+    function moveUsersToGroup(target_user, selected) {
+        var promises = [];
+
+        angular.forEach(selected, function(user) {
+            promises.push(
+                egCore.pcrud.retrieve('au', user.id)
+                .then(function(u) {
+                    u.usrgroup(target_user.usrgroup());
+                    u.ischanged(true);
+                    return egCore.net.request(
+                        'open-ils.actor',
+                        'open-ils.actor.patron.update',
+                        egCore.auth.token(), u
+                    );
+                })
+            );
+        });
+
+        $q.all(promises).then(function() {
+            $scope.gridRevision++;
+        });
+    }
+
+    function showMoveToGroupConfirm(barcode, selected) {
 
         // find the user
         egCore.pcrud.search('ac', {barcode : barcode})
@@ -1180,11 +1213,12 @@ function($scope,  $routeParams , $q , $location , egCore ,
             .then(function(user) {
                 user.card(card);
                 $modal.open({
-                    templateUrl: './circ/patron/t_add_to_group_dialog',
+                    templateUrl: './circ/patron/t_move_to_group_dialog',
                     controller: [
                                 '$scope','$modalInstance',
                         function($scope , $modalInstance) {
                             $scope.user = user;
+                            $scope.outbound = Boolean(selected);
                             $scope.ok = 
                                 function(count) { $modalInstance.close() }
                             $scope.cancel = 
@@ -1192,21 +1226,30 @@ function($scope,  $routeParams , $q , $location , egCore ,
                         }
                     ]
                 }).result.then(function() {
-                    addUserToGroup(user);
+                    if (selected) {
+                        moveUsersToGroup(user, selected);
+                    } else {
+                        addUserToGroup(user);
+                    }
                 });
             });
         });
     }
 
-    $scope.moveToGroup = function() {
+    // selected == move selected patrons to another patron's group
+    // !selected == patron from a different group moves into our group
+    function moveToGroup(selected) {
         egPromptDialog.open(
             egCore.strings.GROUP_ADD_USER, '',
             {ok : function(value) {
                 if (value) 
-                    showMoveToGroupConfirm(value);
+                    showMoveToGroupConfirm(value, selected);
             }}
         );
     }
 
+    $scope.moveToGroup = function() { moveToGroup() };
+    $scope.moveToAnotherGroup = function(selected) { moveToGroup(selected) };
+
 }])