LP#1773417 Revamp item and call number tranfers
authorDan Wells <dbw2@calvin.edu>
Tue, 12 Jun 2018 18:20:03 +0000 (14:20 -0400)
committerDan Wells <dbw2@calvin.edu>
Wed, 18 Jul 2018 13:40:40 +0000 (09:40 -0400)
This commit attempts to achieve the goals of both simplification and
feature completeness/flexibility.  In brief, limit the number of
marking and transfer options, then have the code decide the right
action to take given the circumstances.

There are now just two "marking" actions, one at the record level,
one at the holdings level.  The holdings level mark will automatically
mark the destination as specifically as possible from the selected row,
which means either to the library or call number (vol) level.

We are also now down to two transfer options: transfer the selected
item, or transfer the selected call number.  Either option will use
as much given context as possible, then fill in any blanks with
reasonable defaults and actions.

As part of the change, a number of functions and variables are also
renamed.  This is all done for clarification, and in most cases is
due to the variable or function now being used more generally (i.e.
it is used in both the item and vol context, so it is confusing to
be named 'volume_transfer_target', etc.).

Finally, clear up a fair bit of now redundant and unused code.

Signed-off-by: Dan Wells <dbw2@calvin.edu>
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/templates/staff/cat/catalog/index.tt2
Open-ILS/src/templates/staff/cat/catalog/t_catalog.tt2
Open-ILS/src/templates/staff/cat/catalog/t_holdings.tt2
Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js
Open-ILS/web/js/ui/default/staff/cat/catalog/app.js
Open-ILS/web/js/ui/default/staff/circ/services/item.js

index bb7d232..f2c75f7 100644 (file)
       "[% l('Hold Transfer Destination set') %]";                
     s.MARK_CONJ_TARGET =                                                                                                            
       "[% l('Conjoined Item Target set') %]";                
-    s.MARK_VOL_TARGET =                                                                                                            
-      "[% l('Volume Transfer Target set') %]";                
-    s.MARK_ITEM_TARGET =                                                                                                            
-      "[% l('Item Transfer Target set') %]";                
+    s.MARK_HOLDINGS_TARGET = "[% l('Holdings transfer target set') %]";
     s.MARK_OVERLAY_TARGET =                                                                                                            
       "[% l('Record Overlay Target set') %]";                
 
index 5d49ad3..5c2630e 100644 (file)
@@ -66,9 +66,9 @@
                 </a>
             </li>
             <li role="menuitem">
-                <a ng-click="markVolTransfer()" href="">
-                    [% l('Volume Transfer') %]
-                    <span class="target-record-aside" ng-if="current_voltransfer_target">[% l('(Currently [_1])', '{{current_voltransfer_target}}') %]</span>
+                <a ng-click="markHoldingsTransfer()" href="">
+                    [% l('Holdings Transfer') %]
+                    <span class="target-record-aside" ng-if="current_transfer_target">[% l('(Currently [_1])', '{{current_transfer_target}}') %]</span>
                 </a>
             </li>
             <li role="menuitem">
index 2980123..f188a1a 100644 (file)
       label="[% l('Request Items') %]"></eg-grid-action>
     <eg-grid-action handler="attach_to_peer_bib"
       label="[% l('Link as Conjoined to Previously Marked Bib Record') %]"></eg-grid-action>
-<!--
-    <eg-grid-action handler="markLibAsVolTarget"
-      label="[% l('Choose Library for Volume/Copy Transfer Destination') %]"></eg-grid-action>
--->
-
     <eg-grid-action handler="selectedHoldingsItemStatus" group="[% l('Show') %]"
       label="[% l('Item Status (list)') %]"></eg-grid-action>
     <eg-grid-action handler="selectedHoldingsItemStatusDetail" group="[% l('Show') %]"
       label="[% l('Item as Damaged') %]"></eg-grid-action>
     <eg-grid-action handler="selectedHoldingsMissing" group="[% l('Mark') %]"
       label="[% l('Item as Missing') %]"></eg-grid-action>
-    <eg-grid-action handler="markLibFromSelectedAsVolTarget" group="[% l('Mark') %]"
-      label="[% l('Library as Volume Transfer Destination') %]"></eg-grid-action>
-    <eg-grid-action handler="markVolAsItemTarget" group="[% l('Mark') %]" disabled="vols_not_shown"
-      label="[% l('Volume as Item Transfer Destination') %]"></eg-grid-action>
+    <eg-grid-action handler="markFromSelectedAsHoldingsTarget" group="[% l('Mark') %]"
+      label="[% l('Library/Volume as Transfer Destination') %]"></eg-grid-action>
 
     <eg-grid-action handler="selectedHoldingsVolAdd" group="[% l('Add') %]"
       label="[% l('Volumes') %]"></eg-grid-action>
     <eg-grid-action handler="selectedHoldingsVolCopyDelete" group="[% l('Delete') %]" disabled="copies_not_shown"
       label="[% l('Volumes and Copies') %]"></eg-grid-action>
 
-<!--
-    <eg-grid-action handler="transferVolumesToRecord" group="[% l('Transfer') %]"
-      label="[% l('Volumes to Previously Marked Record') %]"></eg-grid-action>
-    <eg-grid-action handler="transferVolumesToLibrary" group="[% l('Transfer') %]"
-      label="[% l('Volumes to Previously Marked Library') %]"></eg-grid-action>
--->
-
-    <eg-grid-action handler="transferVolumesToRecordAndLibrary" group="[% l('Transfer') %]"
+    <eg-grid-action handler="transferVolumes" group="[% l('Transfer') %]"
       label="[% l('Volumes to Previously Marked Destination') %]"></eg-grid-action>
 
-<!--
-    <eg-grid-action handler="changeItemOwningLib" group="[% l('Transfer') %]"
-      label="[% l('Copies to Previously Marked Library') %]"></eg-grid-action>
--->
-
     <eg-grid-action handler="transferItems" group="[% l('Transfer') %]"
-      label="[% l('Items to Previously Marked Volume') %]"></eg-grid-action>
+      label="[% l('Items to Previously Marked Destination') %]"></eg-grid-action>
 
     <eg-grid-field label="[% l('Owning Library') %]"  path="owner_label" flex="4" align="right" visible></eg-grid-field>
     <eg-grid-field label="[% l('Call Number') %]"     path="call_number.label" visible></eg-grid-field>
index f6ccffb..3208a42 100644 (file)
@@ -725,7 +725,7 @@ function($scope,  $q , $routeParams , $timeout , $window , $uibModal , bucketSvc
     }
 
     $scope.transferCopies = function(copies) {
-        var xfer_target = egCore.hatch.getLocalItem('eg.cat.item_transfer_target');
+        var xfer_target = egCore.hatch.getLocalItem('eg.cat.transfer_target_vol');
         var copy_ids = copies.map(
             function(curr,idx,arr) {
                 return curr.id;
index c3505ab..203bb71 100644 (file)
@@ -377,7 +377,7 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
     }
 
     $scope.current_overlay_target     = egCore.hatch.getLocalItem('eg.cat.marked_overlay_record');
-    $scope.current_voltransfer_target = egCore.hatch.getLocalItem('eg.cat.marked_volume_transfer_record');
+    $scope.current_transfer_target    = egCore.hatch.getLocalItem('eg.cat.transfer_target_record');
     $scope.current_conjoined_target   = egCore.hatch.getLocalItem('eg.cat.marked_conjoined_record');
 
     $scope.quickReceive = function () {
@@ -443,11 +443,12 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
         ngToast.create(egCore.strings.MARK_CONJ_TARGET);
     };
 
-    $scope.markVolTransfer = function () {
-        ngToast.create(egCore.strings.MARK_VOL_TARGET);
-        $scope.current_voltransfer_target = $scope.record_id;
-        egCore.hatch.setLocalItem('eg.cat.marked_volume_transfer_record',$scope.record_id);
-        egCore.hatch.removeLocalItem('eg.cat.volume_transfer_target');
+    $scope.markHoldingsTransfer = function () {
+        $scope.current_transfer_target = $scope.record_id;
+        egCore.hatch.setLocalItem('eg.cat.transfer_target_record',$scope.record_id);
+        egCore.hatch.removeLocalItem('eg.cat.transfer_target_lib');
+        egCore.hatch.removeLocalItem('eg.cat.transfer_target_vol');
+        ngToast.create(egCore.strings.MARK_HOLDINGS_TARGET);
     };
 
     $scope.markOverlay = function () {
@@ -458,10 +459,10 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
 
     $scope.clearRecordMarks = function () {
         $scope.current_overlay_target     = null;
-        $scope.current_voltransfer_target = null;
+        $scope.current_transfer_target    = null;
         $scope.current_conjoined_target   = null;
         $scope.current_hold_transfer_dest = null;
-        egCore.hatch.removeLocalItem('eg.cat.marked_volume_transfer_record');
+        egCore.hatch.removeLocalItem('eg.cat.transfer_target_record');
         egCore.hatch.removeLocalItem('eg.cat.marked_conjoined_record');
         egCore.hatch.removeLocalItem('eg.cat.marked_overlay_record');
         egCore.hatch.removeLocalItem('eg.circ.hold.title_transfer_target');
@@ -1314,57 +1315,26 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
         $timeout(function() { $window.open(url, '_blank') });
     }
 
-    $scope.markVolAsItemTarget = function() {
-        if ($scope.holdingsGridControls.selectedItems()[0].call_number.id) { // cn.id missing when vols are collapsed
-            egCore.hatch.setLocalItem(
-                'eg.cat.item_transfer_target',
-                $scope.holdingsGridControls.selectedItems()[0].call_number.id
-            );
-            ngToast.create(egCore.strings.MARK_ITEM_TARGET);
-        }
-    }
-
-    $scope.markLibAsVolTarget = function() {
-        var recId = $scope.record_id;
-        return $uibModal.open({
-            templateUrl: './cat/catalog/t_choose_vol_target_lib',
-            backdrop: 'static',
-            animation: true,
-            controller:
-                   ['$scope','$uibModalInstance',
-            function($scope , $uibModalInstance) {
-
-                var orgId = egCore.hatch.getLocalItem('eg.cat.volume_transfer_target') || 1;
-                $scope.org = egCore.org.get(orgId);
-                $scope.cant_have_vols = function (id) { return !egCore.org.CanHaveVolumes(id); };
-                $scope.ok = function(org) {
-                    egCore.hatch.setLocalItem(
-                        'eg.cat.volume_transfer_target',
-                        org.id()
-                    );
-                    egCore.hatch.setLocalItem(
-                        'eg.cat.marked_volume_transfer_record',
-                        recId
-                    );
-                    $uibModalInstance.close();
-                }
-                $scope.cancel = function($event) {
-                    $uibModalInstance.dismiss();
-                    $event.preventDefault();
-                }
-            }]
-        });
-    }
-    $scope.markLibFromSelectedAsVolTarget = function() {
+    $scope.markFromSelectedAsHoldingsTarget = function() {
         egCore.hatch.setLocalItem(
-            'eg.cat.volume_transfer_target',
+            'eg.cat.transfer_target_lib',
             $scope.holdingsGridControls.selectedItems()[0].owner_id
         );
         egCore.hatch.setLocalItem(
-            'eg.cat.marked_volume_transfer_record',
+            'eg.cat.transfer_target_record',
             $scope.record_id
         );
-        ngToast.create(egCore.strings.MARK_VOL_TARGET);
+        if ($scope.holdingsGridControls.selectedItems()[0].call_number.id) { // cn.id missing when vols are collapsed, or we are on an empty lib
+            egCore.hatch.setLocalItem(
+                'eg.cat.transfer_target_vol',
+                $scope.holdingsGridControls.selectedItems()[0].call_number.id
+            );
+        } else {
+            // clear out the stale value if we're on a lib-only
+            // or vol-collapsed row
+            egCore.hatch.removeLocalItem('eg.cat.transfer_target_vol');
+        }
+        ngToast.create(egCore.strings.MARK_HOLDINGS_TARGET);
     }
 
     $scope.selectedHoldingsItemStatusDetail = function (){
@@ -1378,20 +1348,35 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
         );
     }
 
-    $scope.transferVolumesToRecord = function (){
-        var target_record = egCore.hatch.getLocalItem('eg.cat.marked_volume_transfer_record');
-        if (!target_record) return;
-        if ($scope.record_id == target_record) return;
-        var items = $scope.holdingsGridControls.selectedItems();
-        if (!items.length) return;
+    $scope.transferVolumes = function (){
+        var target_record = egCore.hatch.getLocalItem('eg.cat.transfer_target_record');
+        var target_lib = egCore.hatch.getLocalItem('eg.cat.transfer_target_lib');
+        if (!target_lib
+            && (!target_record || ($scope.record_id == target_record) )
+        ) return;
 
-        var vols_to_move   = {};
-        angular.forEach(items, function(item) {
-            if (!(item.call_number.owning_lib in vols_to_move)) {
-                vols_to_move[item.call_number.owning_lib] = new Array;
+        var vols_to_move = {};
+        if (target_lib) {
+            // we're moving volumes to a different library
+            var vol_ids = gatherSelectedVolumeIds();
+            if (vol_ids.length) {
+                vols_to_move[target_lib] = vol_ids;
+
+                // if we're *only* switching libs,
+                // grab the current record as the target
+                target_record = target_record || $scope.record_id;
             }
-            vols_to_move[item.call_number.owning_lib].push(item.call_number.id);
-        });
+        } else {
+            // we're moving volumes to the same library they exist in
+            // currently, but on a different record
+            var items = $scope.holdingsGridControls.selectedItems();
+            angular.forEach(items, function(item) {
+                if (!(item.call_number.owning_lib in vols_to_move)) {
+                    vols_to_move[item.call_number.owning_lib] = new Array;
+                }
+                vols_to_move[item.call_number.owning_lib].push(item.call_number.id);
+            });
+        }
 
         var promises = [];        
         angular.forEach(vols_to_move, function(vols, owning_lib) {
@@ -1417,54 +1402,35 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
         });
     }
 
-    function transferVolumes(new_record){
-        var xfer_target = egCore.hatch.getLocalItem('eg.cat.volume_transfer_target');
-
-        if (xfer_target) {
-            egCore.net.request(
-                'open-ils.cat',
-                'open-ils.cat.asset.volume.batch.transfer.override',
-                egCore.auth.token(), {
-                    docid   : (new_record ? new_record : $scope.record_id),
-                    lib     : xfer_target,
-                    volumes : gatherSelectedVolumeIds()
-                }
-            ).then(function(success) {
-                if (success) {
-                    ngToast.create(egCore.strings.VOLS_TRANSFERED);
-                    holdingsSvcInst.fetchAgain().then(function() {
-                        $scope.holdingsGridDataProvider.refresh();
-                    });
-                } else {
-                    alert('Could not transfer volumes!');
-                }
-            });
-        }
-        
-    }
-
-    $scope.transferVolumesToLibrary = function() {
-        transferVolumes();
-    }
-
-    $scope.transferVolumesToRecordAndLibrary = function() {
-        var target_record = egCore.hatch.getLocalItem('eg.cat.marked_volume_transfer_record');
-        if (!target_record) return;
-        transferVolumes(target_record);
-    }
-
     // this "transfers" selected copies to a new owning library,
-    // auto-creating volumes and deleting unused volumes as required.
-    $scope.changeItemOwningLib = function() {
-        var xfer_target = egCore.hatch.getLocalItem('eg.cat.volume_transfer_target');
+    // auto-creating volumes as required
+    $scope.transferItemsAutoFill = function() {
+        var target_record = egCore.hatch.getLocalItem('eg.cat.transfer_target_record');
+        var target_lib = egCore.hatch.getLocalItem('eg.cat.transfer_target_lib');
+        if (!target_lib
+            && (!target_record || ($scope.record_id == target_record) )
+        ) return;
+
         var items = $scope.holdingsGridControls.selectedItems();
-        if (!xfer_target || !items.length) {
+        if (!items.length) {
             return;
         }
+
         var vols_to_move   = {};
         var copies_to_move = {};
         angular.forEach(items, function(item) {
-            if (item.call_number.owning_lib != xfer_target) {
+            var needs_move = false;
+            if (target_lib
+                && (item.call_number.owning_lib != target_lib)) {
+                    item.call_number.owning_lib = target_lib;
+                    needs_move = true;
+            }
+            if (target_record
+                && (item.call_number.record != target_record)) {
+                    item.call_number.record = target_record;
+                    needs_move = true;
+            }
+            if (needs_move) {
                 if (item.call_number.id in vols_to_move) {
                     copies_to_move[item.call_number.id].push(item.id);
                 } else {
@@ -1474,7 +1440,7 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
                 }
             }
         });
-    
+
         var promises = [];
         angular.forEach(vols_to_move, function(vol) {
             promises.push(egCore.net.request(
@@ -1482,8 +1448,8 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
                 'open-ils.cat.call_number.find_or_create',
                 egCore.auth.token(),
                 vol.label,
-                vol.record,
-                xfer_target,
+                vol.record, // may be new
+                vol.owning_lib, // may be new
                 vol.prefix.id,
                 vol.suffix.id,
                 vol.label_class
@@ -1515,9 +1481,16 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e
     };
 
     $scope.transferItems = function (){
-        var xfer_target = egCore.hatch.getLocalItem('eg.cat.item_transfer_target');
+        var xfer_target = egCore.hatch.getLocalItem('eg.cat.transfer_target_vol');
+
+        if (!xfer_target) {
+            // we have no specific volume, let's try to fill in the
+            // blanks instead
+            return $scope.transferItemsAutoFill();
+        }
+
         var copy_ids = gatherSelectedHoldingsIds();
-        if (xfer_target && copy_ids.length > 0) {
+        if (copy_ids.length > 0) {
             egCore.net.request(
                 'open-ils.cat',
                 'open-ils.cat.transfer_copies_to_volume',
index d931d3a..aaed14d 100644 (file)
@@ -779,7 +779,7 @@ function(egCore , egCirc , $uibModal , $q , $timeout , $window , egConfirmDialog
     // this "transfers" selected copies to a new owning library,
     // auto-creating volumes and deleting unused volumes as required.
     service.changeItemOwningLib = function(items) {
-        var xfer_target = egCore.hatch.getLocalItem('eg.cat.volume_transfer_target');
+        var xfer_target = egCore.hatch.getLocalItem('eg.cat.transfer_target_lib');
         if (!xfer_target || !items.length) {
             return;
         }
@@ -804,7 +804,7 @@ function(egCore , egCirc , $uibModal , $q , $timeout , $window , egConfirmDialog
         });
 
         var promises = [];
-        angular.forEach(vols_to_move, function(vol) {
+        angular.forEach(vols_to_move, function(vol, vol_id) {
             promises.push(egCore.net.request(
                 'open-ils.cat',
                 'open-ils.cat.call_number.find_or_create',
@@ -823,24 +823,21 @@ function(egCore , egCirc , $uibModal , $q , $timeout , $window , egConfirmDialog
                     'open-ils.cat.transfer_copies_to_volume',
                     egCore.auth.token(),
                     resp.acn_id,
-                    copies_to_move[vol.id]
+                    copies_to_move[vol_id]
                 );
             }));
         });
 
-        angular.forEach(
-            items,
-            function(cp){
-                promises.push(
-                    function(){ service.add_barcode_to_list(cp.barcode) }
-                )
+        $q.all(promises)
+        .then(
+            function() {
+                angular.forEach(items, function(cp){service.add_barcode_to_list(cp.barcode)});
             }
         );
-        $q.all(promises);
     }
 
     service.transferItems = function (items){
-        var xfer_target = egCore.hatch.getLocalItem('eg.cat.item_transfer_target');
+        var xfer_target = egCore.hatch.getLocalItem('eg.cat.transfer_target_vol');
         var copy_ids = service.gatherSelectedHoldingsIds(items);
         if (xfer_target && copy_ids.length > 0) {
             egCore.net.request(