From eb6e2c06a7d813c87db6646483c5228f88c46eb1 Mon Sep 17 00:00:00 2001 From: Mike Rylander Date: Mon, 22 May 2017 19:19:00 -0400 Subject: [PATCH] webstaff: collect receiving data in one modal Signed-off-by: Mike Rylander --- .../src/perlmods/lib/OpenILS/Application/Serial.pm | 16 +- .../templates/staff/serials/t_batch_receive.tt2 | 131 +++++++++++++ .../staff/serials/directives/view-items-grid.js | 212 +++++++++++---------- 3 files changed, 262 insertions(+), 97 deletions(-) create mode 100644 Open-ILS/src/templates/staff/serials/t_batch_receive.tt2 diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm index dbf2884d21..cbb04f2eef 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm @@ -1221,6 +1221,11 @@ __PACKAGE__->register_method( name => 'donor_unit_ids', desc => 'hash of unit_ids => 1, keyed with ids of any units giving up items', type => 'hash' + }, + { + name => 'extras', + desc => 'hash of hashes, circ_mod code and copy_location id, keyed as above', + type => 'hash' } ], 'return' => { @@ -1256,6 +1261,11 @@ __PACKAGE__->register_method( name => 'donor_unit_ids', desc => 'hash of unit_ids => 1, keyed with ids of any units giving up items', type => 'hash' + }, + { + name => 'extras', + desc => 'hash of hashes, circ_mod code and copy_location id, keyed as above', + type => 'hash' } ], 'return' => { @@ -1288,7 +1298,7 @@ __PACKAGE__->register_method( ); sub unitize_items { - my ($self, $conn, $auth, $items, $barcodes, $call_numbers, $donor_unit_ids) = @_; + my ($self, $conn, $auth, $items, $barcodes, $call_numbers, $donor_unit_ids, $extras) = @_; my $editor = new_editor("authtoken" => $auth, "xact" => 1); return $editor->die_event unless $editor->checkauth; @@ -1366,7 +1376,11 @@ sub unitize_items { $unit->{"note"} = "Item ID: " . $item->id; return $unit; } + $unit->barcode($barcodes->{$item->id}) if exists($barcodes->{$item->id}); + $unit->location($extras->{copy_locations}->{$item->id}) if exists($extras->{copy_locations}->{$item->id}); + $unit->circ_modifier($extras->{circ_mods}->{$item->id}) if exists($extras->{circ_mods}->{$item->id}); + my $evt = _create_sunit($editor, $unit); return $evt if $evt; if ($unit_id == -2) { diff --git a/Open-ILS/src/templates/staff/serials/t_batch_receive.tt2 b/Open-ILS/src/templates/staff/serials/t_batch_receive.tt2 new file mode 100644 index 0000000000..3f78a0cf2b --- /dev/null +++ b/Open-ILS/src/templates/staff/serials/t_batch_receive.tt2 @@ -0,0 +1,131 @@ +
+ + + + + +
diff --git a/Open-ILS/web/js/ui/default/staff/serials/directives/view-items-grid.js b/Open-ILS/web/js/ui/default/staff/serials/directives/view-items-grid.js index d883f86aeb..19644f97d5 100644 --- a/Open-ILS/web/js/ui/default/staff/serials/directives/view-items-grid.js +++ b/Open-ILS/web/js/ui/default/staff/serials/directives/view-items-grid.js @@ -241,30 +241,31 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider , } }); - return process_next('receive', list); + return process_next('receive', list, $scope.receive_and_barcode); } $scope.receive_selected = function (list) { return process_next('receive', list.map(function(item) { return egCore.idl.Clone(egSerialsCoreSvc.itemMap[item.id]); - })); + }), $scope.receive_and_barcode); } $scope.bind_selected = function (list) { return process_next('bind', list.map(function(item) { return egCore.idl.Clone(egSerialsCoreSvc.itemMap[item.id]); - }), true); + }), true, true); } - function process_next (mode, list, receive_and_bind) { + function process_next (mode, list, do_barcode, bind) { + var bibId = $scope.bibId; if (!list.length) return $q.reject(); var donor_unit_ids = {}; angular.forEach(list, function (item) { if (item.unit()) donor_unit_ids[item.unit().id()] = 1; - if ($scope.receive_and_barcode) item.unit(-1); - if (receive_and_bind) item.unit(-2); + if (do_barcode) item.unit(-1); + if (bind) item.unit(-2); }); var method; var success_label; @@ -276,121 +277,140 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider , success_label = 'bound'; } + // deal with locations and circ mods for *NEW* units + var copy_locations = {}; + var circ_mods = {}; + // deal with barcodes and call numbers for *NEW* units var barcodes = {}; var call_numbers = {}; var call_numbers_by_siss_and_sdist = {}; - var r_and_b_barcode = ''; - var r_and_b_callnumber = ''; - var deferred = $q.defer(); var current_promise = deferred.promise; var last_promise; - if ($scope.receive_and_barcode || receive_and_bind) { // supplying a barcode (unit) to new items - - angular.forEach(list, function (item) { + if (do_barcode || bind) { // supplying a barcode (unit) to new items + + last_promise = current_promise.then(function(){ return $uibModal.open({ + templateUrl: './serials/t_batch_receive', + size: 'lg', + windowClass: 'eg-wide-modal', + backdrop: 'static', + controller: + ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) { + + $scope.receive_date = new Date(); + $scope.barcode_items = do_barcode; + $scope.force_bind = bind; + $scope.bind = bind; + $scope.items = list; + $scope.acn_list = []; + $scope.acpl_list = []; + + var acpl_hash = {}; + var acn_hash = {}; + + $scope.bind_or_none = function (index) { + return !$scope.barcode_items || ($scope.bind && index > 0); + } - if (last_promise) current_promise = last_promise; + $scope.focus_next_barcode = function (index) { + index++; + $('#item_barcode_'+index).focus().select(); + } - // TODO: I18N - var prompt_text = 'for '+ - item.issuance().label()+ - ' from Distribution: '+item.stream().distribution().label()+ - '/'+item.stream().id()+':'; + $scope.$watch('auto_barcodes', function (n) { + var bc = '@@AUTO'; + if (!n) bc = ''; - if (receive_and_bind) { - prompt_text = 'for the new unit:'; - } + angular.forEach($scope.items, function (i) { + var _barcode = i._barcode; + i._barcode = bc || i._old_barcode; + i._old_barcode = _barcode; + }); + }); - last_promise = current_promise.then(function() { - if (receive_and_bind && r_and_b_barcode) { - barcodes[item.id()] = r_and_b_barcode; - return $q.when(); + $scope.apply_template_overrides = function (e) { + if ($scope.selected_call_number) { + angular.forEach($scope.items, function (i) { + i._call_number = $scope.selected_call_number; + }); + } + if ($scope.selected_circ_mod) { + angular.forEach($scope.items, function (i) { + i._circ_mod = $scope.selected_circ_mod; + }); + } + if ($scope.selected_copy_location) { + angular.forEach($scope.items, function (i) { + i._copy_location = $scope.selected_copy_location; + }); + } } - return egPromptDialog.open( - 'Please enter a barcode ' + prompt_text, '@@AUTO', - {ok : function(barcode) { - if (barcode) { - barcode = String( barcode ).replace(/\s/g,''); - if (!barcode || barcode == 'null') { - barcode = '@@AUTO'; -/* - * } else { - * // XXX test for barcode in use - * // disable alarm sound temporarily - * var sound_setting = obj.data.no_sound; - * if (!sound_setting) { // undefined or false - * obj.data.no_sound = true; obj.data.stash('no_sound'); - * } - * var test = obj.network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ barcode ]); - * if (typeof test.ilsevent == 'undefined') { - * alert('Another copy has barcode "' + barcode + '", defaulting to system-generated.'); - * barcode = '@@AUTO'; - * } - * if (!sound_setting) { - * obj.data.no_sound = sound_setting; obj.data.stash('no_sound'); - * } - */ - } - barcodes[item.id()] = barcode; - if (receive_and_bind && !r_and_b_barcode) - r_and_b_barcode = barcode; - } else { - barcodes[item.id()] = '@@AUTO'; - } - }} - ).result; - }).then(function() { - if (receive_and_bind && r_and_b_callnumber) { - call_numbers[item.id()] = r_and_b_callnumber; - return $q.when(); - } + var pile_o_promises = [$q.when()]; + // let's gather what we need... + angular.forEach(list, function (i) { + if (i.stream().distribution()[mode + '_call_number']()) + i._call_number = i.stream().distribution()[mode + '_call_number']().label(); - if (typeof call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution().id()] == 'undefined') { - var default_cn = 'DEFAULT'; - // if they defined a *_call_number, honor it as the default - var preset_cn = item.stream().distribution()[mode + '_call_number'](); - if (preset_cn) { - default_cn = preset_cn.label(); + if (i.stream().distribution()[mode + '_unit_template']()) { + i._copy_location = i.stream().distribution()[mode + '_unit_template']().location(); + i._circ_mod = i.stream().distribution()[mode + '_unit_template']().circ_modifier(); } - } else { - // we have already seen this same issuance and distribution combo, so use the same call number - call_numbers[item.id()] = call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution().id()]; - } + }); - return egPromptDialog.open('Please enter/adjust a call number'+prompt_text, default_cn, - {ok : function(call_number) { - if (call_number) { - call_number = String( call_number ).replace(/\s/g,''); - if (!call_number || call_number == 'null') - call_number = 'DEFAULT'; - call_numbers[item.id()] = call_number; - call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution().id()] = call_number; - if (receive_and_bind && !r_and_b_callnumber) - r_and_b_callnumber = call_number; - } else { - call_numbers[item.id()] = 'DEFAULT'; - } - }} - ).result; - }); + pile_o_promises.push(egCore.pcrud.search( + 'acpl', + {owning_lib : egCore.org.fullPath(egCore.auth.user().ws_ou(), true)}, + {},{ atomic : true } + ).then(function (list) { + $scope.acpl_list = list.map(function(i){return egCore.idl.toHash(i)}); + return $q.when(); + })); + + pile_o_promises.push(egCore.pcrud.search( + 'acn', + {record : bibId, owning_lib : egCore.org.fullPath(egCore.auth.user().ws_ou(), true)}, + {},{ atomic : true } + ).then(function (list) { + $scope.acn_list = list.map(function(i){return egCore.idl.toHash(i)}); + return $q.when(); + })); - }); + pile_o_promises.push(egCore.pcrud.retrieveAll( + 'ccm', {}, { atomic : true } + ).then(function (list) { + $scope.ccm_list = list.map(function(i){return egCore.idl.toHash(i)}); + return $q.when(); + })); + + $q.all(pile_o_promises).then(function() { + console.log('receive data collected'); + }); + + $scope.ok = function(items) { $uibModalInstance.close(items) } + $scope.cancel = function () { $uibModalInstance.dismiss() } + }] + }).result}); } if (last_promise) current_promise = last_promise; - current_promise.then(function () { - console.log(list); - console.log(barcodes); - console.log(call_numbers); - console.log(donor_unit_ids); + current_promise.then(function (items) { + + angular.forEach(items, function(i, index) { + copy_locations[i.id()] = i._copy_location; + circ_mods[i.id()] = i._circ_mod; + call_numbers[i.id()] = i._call_number || 'DEFAULT'; + barcodes[i.id()] = i._barcode || '@@AUTO'; + if (bind && index > 0) barcodes[i.id()] = items[0]._barcode; + }); return egCore.net.request( 'open-ils.serial', method, - egCore.auth.token(), list, barcodes, call_numbers, donor_unit_ids + egCore.auth.token(), items, barcodes, call_numbers, donor_unit_ids, + {circ_mods:circ_mods, copy_locations : copy_locations} ).then( function(resp) { var evt = egCore.evt.parse(resp); -- 2.11.0