scan missing pieces
authorBill Erickson <berick@esilibrary.com>
Mon, 28 Jul 2014 18:59:15 +0000 (14:59 -0400)
committerBill Erickson <berick@esilibrary.com>
Mon, 28 Jul 2014 18:59:15 +0000 (14:59 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/cat/item/missing_pieces.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_new_message_dialog.tt2 [deleted file]
Open-ILS/src/templates/staff/circ/share/t_new_message_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/navbar.tt2
Open-ILS/web/js/ui/default/staff/cat/item/missing_pieces.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/app.js
Open-ILS/web/js/ui/default/staff/circ/services/circ.js
Open-ILS/web/js/ui/default/staff/services/event.js

diff --git a/Open-ILS/src/templates/staff/cat/item/missing_pieces.tt2 b/Open-ILS/src/templates/staff/cat/item/missing_pieces.tt2
new file mode 100644 (file)
index 0000000..2581ba7
--- /dev/null
@@ -0,0 +1,69 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Scan Item as Missing Pieces"); 
+  ctx.page_app = "egItemMissingPieces";
+  ctx.page_ctrl = "MissingPiecesCtrl";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/item/missing_pieces.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+s.CONFIRM_MARK_MISSING_TITLE = "[% l('Mark item as missing pieces?') %]";
+s.CONFIRM_MARK_MISSING_BODY = 
+  "[% l('[_1] / [_2]', '{{barcode}}', '{{title}}') %]";
+s.CIRC_NOT_FOUND = 
+  "[% l('No circulation found for item with barcode [_1].  Item not modified.', '{{barcode}}') %]"
+}])
+</script>
+[% END %]
+
+<div class="container-fluid" style="text-align:center">
+  <div class="alert alert-info alert-less-pad strong-text-2">
+    <span>[% l('Scan Item as Missing Pieces') %]</span>
+  </div>
+</div>
+
+<form ng-submit="submitBarcode(args)" role="form" class="form-inline">
+  <div class="input-group">
+
+    <label class="input-group-addon" 
+      for="patron-lookup-barcode" >[% l('Patron Barcode') %]</label>
+
+    <input 
+      focus-me="selectMe" 
+      select-me="selectMe"
+      class="form-control barcode"
+      ng-model="args.barcode" 
+      placeholder="[% l('Patron Barcode') %]"
+      id="patron-lookup-barcode" type="text"/> 
+
+    <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+  </div>
+</form>
+
+<br/>
+<div class="alert alert-warning" ng-show="bcNotFound">
+  [% l('Barcode Not Found: [_1]', '{{bcNotFound}}') %]
+</div>
+
+<hr/>
+
+<div ng-show="letter"> 
+  <div class="row">
+    <div class="col-md-2">
+      <button ng-click="print_letter()" class="btn btn-default">[% l('Print Letter') %]</button>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-6">
+      <textarea ng-model="letter" rows="25" style="width:100%"></textarea>
+    </div>
+  </div>
+</div>
+
+[% END %]
+
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_new_message_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_new_message_dialog.tt2
deleted file mode 100644 (file)
index d3555a0..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<form ng-submit="ok(args)" role="form">
-    <div class="modal-header">
-      <button type="button" class="close" ng-click="cancel()" 
-        aria-hidden="true">&times;</button>
-      <h4 class="modal-title">[% l('Apply Standing Penalty / Message') %]</h4>
-    </div>
-    <div class="modal-body">
-      <div class="row">
-        <div class="col-md-8">
-          <ul class="nav nav-pills">
-            <!-- 21 == SILENT_NOTE -->
-            <li ng-class="{active : args.penalty == 21}">
-              <a href ng-click="args.penalty=21">[% l('Note') %]</a>
-            </li>
-            <!-- 20 == ALERT_NOTE -->
-            <li ng-class="{active : args.penalty == 20}">
-              <a href ng-click="args.penalty=20">[% l('Alert') %]</a>
-            </li>
-            <!-- 25 == STAFF_CHR -->
-            <li ng-class="{active : args.penalty == 25}">
-              <a href ng-click="args.penalty=25">[% l('Block') %]</a>
-            </li>
-          </ul>
-        </div>
-        <div class="col-md-4 pull-right">
-          <select class="form-control" ng-model="args.penalty">
-            <option ng-selected="args.penalty < 100"></option>
-            <option ng-repeat="penalty in penalties" 
-              value="{{penalty.id()}}">{{penalty.label()}}</option>
-          </select>
-        </div>
-      </div>
-      <div class="form-group row pad-vert">
-        <div class="col-md-12">
-          <textarea class="form-control" 
-            ng-model="args.note" placeholder="[% l('Note...') %]">
-          </textarea>
-        </div>
-      </div>
-    </div>
-    <div class="modal-footer">
-      <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
-      <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
-    </div>
-</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_new_message_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_new_message_dialog.tt2
new file mode 100644 (file)
index 0000000..1cd94f0
--- /dev/null
@@ -0,0 +1,45 @@
+<form ng-submit="ok(args)" role="form">
+    <div class="modal-header">
+      <button type="button" class="close" ng-click="cancel()" 
+        aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Apply Standing Penalty / Message') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="row">
+        <div class="col-md-8">
+          <ul class="nav nav-pills">
+            <!-- 21 == SILENT_NOTE -->
+            <li ng-class="{active : args.penalty == 21}">
+              <a href ng-click="args.penalty=21">[% l('Note') %]</a>
+            </li>
+            <!-- 20 == ALERT_NOTE -->
+            <li ng-class="{active : args.penalty == 20}">
+              <a href ng-click="args.penalty=20">[% l('Alert') %]</a>
+            </li>
+            <!-- 25 == STAFF_CHR -->
+            <li ng-class="{active : args.penalty == 25}">
+              <a href ng-click="args.penalty=25">[% l('Block') %]</a>
+            </li>
+          </ul>
+        </div>
+        <div class="col-md-4 pull-right">
+          <select class="form-control" ng-model="args.penalty">
+            <option ng-selected="args.penalty < 100"></option>
+            <option ng-repeat="penalty in penalties" 
+              value="{{penalty.id()}}">{{penalty.label()}}</option>
+          </select>
+        </div>
+      </div>
+      <div class="form-group row pad-vert">
+        <div class="col-md-12">
+          <textarea class="form-control" 
+            ng-model="args.note" placeholder="[% l('Note...') %]">
+          </textarea>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
+      <button class="btn btn-warning" ng-click="cancel($event)">[% l('Cancel') %]</button>
+    </div>
+</form>
index 1782dee..6d0e6d8 100644 (file)
               <span>[% l('Replace Barcode') %]</span>
             </a>
           </li>
+          <li>
+            <a href="./cat/item/missing_pieces" target="_self">
+              <span class="glyphicon glyphicon-th"></span>
+              <span>[% l('Scan Item as Missing Pieces') %]</span>
+            </a>
+          </li>
         </ul>
-      </li>
+      </li><!-- circ -->
 
       <!-- cataloging -->
       <li class="dropdown">
diff --git a/Open-ILS/web/js/ui/default/staff/cat/item/missing_pieces.js b/Open-ILS/web/js/ui/default/staff/cat/item/missing_pieces.js
new file mode 100644 (file)
index 0000000..06fad21
--- /dev/null
@@ -0,0 +1,123 @@
+angular.module('egItemMissingPieces',
+    ['ngRoute', 'ui.bootstrap', 'egCoreMod','egUiMod'])
+
+.controller('MissingPiecesCtrl',
+       ['$scope','$q','$window','$location','egCore','egConfirmDialog','egAlertDialog','egCirc',
+function($scope , $q , $window , $location , egCore , egConfirmDialog , egAlertDialog , egCirc) {
+    
+    $scope.selectMe = true; // focus text input
+    $scope.args = {};
+
+    function get_copy(barcode) {
+
+        return egCore.net.request(
+            'open-ils.actor',
+            'open-ils.actor.get_barcodes',
+            egCore.auth.token(), egCore.auth.user().ws_ou(), 
+            'asset', barcode)
+
+        .then(function(resp) { // get_barcodes
+
+            if (evt = egCore.evt.parse(resp)) {
+                console.error(evt.toString());
+                return $q.reject();
+            }
+
+            if (!resp || !resp[0]) {
+                $scope.bcNotFound = barcode;
+                $scope.selectMe = true;
+                return $q.reject();
+            }
+
+            return egCore.pcrud.search('acp', {id : resp[0].id}, {
+                flesh : 3, 
+                flesh_fields : {
+                    acp : ['call_number'],
+                    acn : ['record'],
+                    bre : ['simple_record']
+                },
+                select : { 
+                    // avoid fleshing MARC on the bre
+                    // note: don't add simple_record.. not sure why
+                    bre : ['id']
+                } 
+            })
+        })
+    }
+
+    function mark_missing_pieces(copy) {
+
+        egConfirmDialog.open(
+            egCore.strings.CONFIRM_MARK_MISSING_TITLE,
+            egCore.strings.CONFIRM_MARK_MISSING_BODY, {
+            barcode : copy.barcode(), 
+            title : copy.call_number().record().simple_record().title()
+
+        }).result.then(function() {
+
+            // kick off mark missing
+            return egCore.net.request(
+                'open-ils.circ',
+                'open-ils.circ.mark_item_missing_pieces',
+                egCore.auth.token(), copy.id()
+            )
+
+        }).then(function(resp) {
+            var evt = egCore.evt.parse(resp); // should always produce event
+
+            if (evt.textcode == 'ACTION_CIRCULATION_NOT_FOUND') {
+                return egAlertDialog.open(
+                    egCore.strings.CIRC_NOT_FOUND, {barcode : copy.barcode()});
+            }
+
+            var payload = evt.payload;
+
+            // TODO: open copy editor inline?  new tab?
+
+            // print the missing pieces slip
+            var promise = $q.when();
+            if (payload.slip) {
+                // wait for completion, since it may spawn a confirm dialog
+                promise = egCore.print.print({
+                    context : 'default', 
+                    content_type : 'text/html',
+                    content : payload.slip.template_output().data()
+                });
+            }
+
+            if (payload.letter) {
+                $scope.letter = payload.letter.template_output().data();
+            }
+
+            // apply patron penalty
+            if (payload.circ) {
+                promise.then(function() {
+                    egCirc.create_penalty(payload.circ.usr())
+                });
+            }  
+
+        });
+    }
+
+    $scope.print_letter = function() {
+        egCore.print.print({
+            context : 'mail',
+            content_type : 'text/plain',
+            content : $scope.letter
+        });
+    }
+
+    // find the item by barcode, then proceed w/ missing pieces
+    $scope.submitBarcode = function(args) {
+
+        $scope.bcNotFound = null;
+        if (!args.barcode) return;
+
+        $scope.selectMe = false;
+        $scope.letter = null;
+
+        get_copy(args.barcode).then(mark_missing_pieces);
+    }
+
+}])
+
index 044a99b..71fbf05 100644 (file)
@@ -948,8 +948,8 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
  * Manages messages
  */
 .controller('PatronMessagesCtrl',
-       ['$scope','$q','$routeParams','egCore','$modal','patronSvc',
-function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
+       ['$scope','$q','$routeParams','egCore','$modal','patronSvc','egCirc',
+function($scope , $q , $routeParams,  egCore , $modal , patronSvc , egCirc) {
     $scope.initTab('messages', $routeParams.id);
     var usr_id = $routeParams.id;
 
@@ -1051,38 +1051,12 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
     }
 
     $scope.createPenalty = function() {
-        $modal.open({
-            templateUrl: './circ/patron/t_new_message_dialog',
-            controller: 
-                   ['$scope','$modalInstance','staffPenalties',
-            function($scope , $modalInstance , staffPenalties) {
-                $scope.focusNote = true;
-                $scope.penalties = staffPenalties;
-                $scope.args = {penalty : 21}; // default to Note
-                $scope.setPenalty = function(id) {
-                    args.penalty = id;
-                }
-                $scope.ok = function(count) { $modalInstance.close($scope.args) }
-                $scope.cancel = function () { $modalInstance.dismiss() }
-            }],
-            resolve : { staffPenalties : fetchPenaltyTypes }
-        }).result.then(
-            function(args) {
-                var pen = new egCore.idl.ausp();
-                pen.usr(usr_id);
-                pen.org_unit(egCore.auth.user().ws_ou());
-                pen.note(args.note);
-                pen.standing_penalty(args.penalty);
-                pen.staff(egCore.auth.user().id());
-                pen.set_date('now');
-                egCore.pcrud.create(pen).then(function() { 
-                    activeGrid.refresh();
-                    // force a refresh of the user, since they may now
-                    // have blocking penalties, etc.
-                    patronSvc.setPrimary(patronSvc.current.id(), null, true);
-                });
-            }
-        );
+        egCirc.create_penalty(usr_id).then(function() {
+            activeGrid.refresh();
+            // force a refresh of the user, since they may now
+            // have blocking penalties, etc.
+            patronSvc.setPrimary(patronSvc.current.id(), null, true);
+        });
     }
 
     $scope.editPenalty = function(selected) {
@@ -1092,36 +1066,12 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
         var penalty = patronSvc.current.standing_penalties().filter(
             function(p) {return p.id() == selected[0].id})[0];
 
-        $modal.open({
-            templateUrl: './circ/patron/t_new_message_dialog',
-            controller: 
-                   ['$scope','$modalInstance','staffPenalties',
-            function($scope , $modalInstance , staffPenalties) {
-                $scope.focusNote = true;
-                $scope.penalties = staffPenalties;
-                $scope.args = {
-                    penalty : penalty.standing_penalty().id(),
-                    note : penalty.note()
-                }
-                $scope.setPenalty = function(id) {
-                    args.penalty = id;
-                }
-                $scope.ok = function(count) { $modalInstance.close($scope.args) }
-                $scope.cancel = function () { $modalInstance.dismiss() }
-            }],
-            resolve : { staffPenalties : fetchPenaltyTypes }
-        }).result.then(
-            function(args) {
-                penalty.note(args.note);
-                penalty.standing_penalty(args.penalty);
-                egCore.pcrud.update(penalty).then(function() { 
-                    activeGrid.refresh();
-                    // force a refresh of the user, since they may now
-                    // have blocking penalties, etc.
-                    patronSvc.setPrimary(patronSvc.current.id(), null, true);
-                });
-            }
-        );
+        egCirc.edit_penalty(penalty).then(function() {
+            activeGrid.refresh();
+            // force a refresh of the user, since they may now
+            // have blocking penalties, etc.
+            patronSvc.setPrimary(patronSvc.current.id(), null, true);
+        });
     }
 }])
 
index f2d6884..68401f1 100644 (file)
@@ -467,6 +467,17 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         });
     }
 
+    service.get_staff_penalty_types = function() {
+        if (egCore.env.csp) 
+            return $q.when(egCore.env.csp.list);
+        return egCore.pcrud.search(
+            // id <= 100 are reserved for system use
+            'csp', {id : {'>': 100}}, {}, {atomic : true})
+        .then(function(penalties) {
+            return egCore.env.absorbList(penalties, 'csp').list;
+        });
+    }
+
     // ideally all of these data should be returned with the response,
     // but until then, grab what we need.
     service.flesh_response_data = function(action, evt, params, options) {
@@ -1402,6 +1413,68 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) {
         return check_digit;
     }
 
+    service.create_penalty = function(user_id) {
+        return $modal.open({
+            templateUrl: './circ/share/t_new_message_dialog',
+            controller: 
+                   ['$scope','$modalInstance','staffPenalties',
+            function($scope , $modalInstance , staffPenalties) {
+                $scope.focusNote = true;
+                $scope.penalties = staffPenalties;
+                $scope.args = {penalty : 21}; // default to Note
+                $scope.setPenalty = function(id) {
+                    args.penalty = id;
+                }
+                $scope.ok = function(count) { $modalInstance.close($scope.args) }
+                $scope.cancel = function($event) { 
+                    $modalInstance.dismiss();
+                    $event.preventDefault();
+                }
+            }],
+            resolve : { staffPenalties : service.get_staff_penalty_types }
+        }).result.then(
+            function(args) {
+                var pen = new egCore.idl.ausp();
+                pen.usr(user_id);
+                pen.org_unit(egCore.auth.user().ws_ou());
+                pen.note(args.note);
+                pen.standing_penalty(args.penalty);
+                pen.staff(egCore.auth.user().id());
+                pen.set_date('now');
+                return egCore.pcrud.create(pen);
+            }
+        );
+    }
+
+    // assumes, for now anyway,  penalty type is fleshed onto usr_penalty.
+    service.edit_penalty = function(usr_penalty) {
+        return $modal.open({
+            templateUrl: './circ/share/t_new_message_dialog',
+            controller: 
+                   ['$scope','$modalInstance','staffPenalties',
+            function($scope , $modalInstance , staffPenalties) {
+                $scope.focusNote = true;
+                $scope.penalties = staffPenalties;
+                $scope.args = {
+                    penalty : usr_penalty.standing_penalty().id(),
+                    note : usr_penalty.note()
+                }
+                $scope.setPenalty = function(id) { args.penalty = id; }
+                $scope.ok = function(count) { $modalInstance.close($scope.args) }
+                $scope.cancel = function($event) { 
+                    $modalInstance.dismiss();
+                    $event.preventDefault();
+                }
+            }],
+            resolve : { staffPenalties : service.get_staff_penalty_types }
+        }).result.then(
+            function(args) {
+                usr_penalty.note(args.note);
+                usr_penalty.standing_penalty(args.penalty);
+                return egCore.pcrud.update(usr_penalty);
+            }
+        );
+    }
 
     return service;
 
index ccec585..dbf0d82 100644 (file)
@@ -35,6 +35,7 @@ angular.module('egCoreMod')
                 this.ilsperm = args.ilsperm;
                 this.ilspermloc = args.ilspermloc;
                 this.note = args.note;
+                this.success = this.textcode == 'SUCCESS';
                 this.toString = function() {
                     var s = 'Event: ' + (this.code || '') + ':' + 
                         this.textcode + ' -> ' + new String(this.desc);