webstaff: binding and receiving, logic based on XUL code
authorMike Rylander <mrylander@gmail.com>
Thu, 18 May 2017 23:26:26 +0000 (19:26 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Tue, 30 May 2017 16:06:47 +0000 (12:06 -0400)
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/templates/staff/serials/t_view_items_grid.tt2
Open-ILS/web/js/ui/default/staff/serials/directives/view-items-grid.js

index 23676dc..d669287 100644 (file)
     <eg-grid-menu-item handler="add_issuances" standalone="true"
         label="[% l('Predict New Issues') %]"></eg-grid-menu-item>
 
+    <eg-grid-menu-item handler="receive_barcode_checkbox_handler"
+      label="[% l('Barcode on receive') %]"
+      checkbox="receive_and_barcode"
+      checked="receive_and_barcode"
+      standalone="true"/>
 
+    <eg-grid-menu-item handler="receive_barcode_checkbox_handler"
+      label="[% l('Bind on receive') %]"
+      checkbox="receive_and_bind"
+      checked="receive_and_bind"
+      standalone="true"/>
+
+
+    <eg-grid-action handler="receive_selected"
+      label="[% l('Receive selected') %]"></eg-grid-action>
+    <eg-grid-action handler="bind_selected"
+      label="[% l('Bind selected') %]"></eg-grid-action>
     <eg-grid-action handler="following_issuance" disabled="need_one_selected"
       label="[% l('Add following issue') %]"></eg-grid-action>
     <eg-grid-action handler="edit_issuance_holding_code"
index 0aaf680..7a1c4b3 100644 (file)
@@ -78,7 +78,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
                 list
             ).then( function(resp) {
                 var evt = egCore.evt.parse(resp);
-                if (evt) { // any way to just throw or return this to the error handler?
+                if (evt) {
                     ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                 } else {
                     ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
@@ -115,7 +115,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
                         }
                     ).then( function(resp) {
                         var evt = egCore.evt.parse(resp);
-                        if (evt) { // any way to just throw or return this to the error handler?
+                        if (evt) {
                             ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                         } else {
                             iss.label(resp[0].label);
@@ -143,7 +143,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
             ).then(
                 function(resp) {
                     var evt = egCore.evt.parse(resp);
-                    if (evt) { // any way to just throw or return this to the error handler?
+                    if (evt) {
                         ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                     } else {
                         ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
@@ -173,7 +173,195 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
             ).then(
                 function(resp) {
                     var evt = egCore.evt.parse(resp);
-                    if (evt) { // any way to just throw or return this to the error handler?
+                    if (evt) {
+                        ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
+                    } else {
+                        ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
+                        return reload($scope.ssubId,_paging_filter);
+                    }
+                },
+                function(resp) {
+                    ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
+                }
+            );
+        });
+    }
+
+    $scope.receive_and_barcode = false;
+    $scope.receive_and_bind = false;
+
+    $scope.receive_barcode_checkbox_handler = function(item) {
+        $scope[item.checkbox] = item.checked;
+    }
+
+    $scope.receive_next = function () {
+        var list = [];
+        var next_per_stream = {};
+        angular.forEach(egSerialsCoreSvc.itemTree, function (item) {
+            if (next_per_stream[item.stream().id()]) return;
+            if (item.status() == 'Expected') {
+                next_per_stream[item.stream().id()] = item;
+                list.push(item);
+            }
+        });
+
+        return process_next('receive', list);
+    }
+
+    $scope.receive_selected = function (list) {
+        console.log(list);
+        return process_next('bind', list.map(function(item) {
+            return egSerialsCoreSvc.itemMap[item.id];
+        }));
+    }
+
+    $scope.bind_selected = function () {
+        $scope.receive_and_bind = true;
+        return process_next('bind', list.map(function(item) {
+            return egSerialsCoreSvc.itemMap[item.id];
+        }));
+    }
+
+    function process_next (mode, list) {
+
+        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 ($scope.receive_and_bind) item.unit(-2);
+        });
+
+        var method; var success_label;
+        if (mode == 'receive') {
+            method = 'open-ils.serial.receive_items';
+            success_label = 'received';
+        } else { // bind mode
+            method = 'open-ils.serial.bind_items';
+            success_label = 'bound';
+        } 
+
+        // deal with barcodes and call numbers for *NEW* units
+        var barcodes = {};
+        var call_numbers = {};
+        var call_numbers_by_siss_and_sdist = {};
+
+        var prompt_promises = [];
+        if ($scope.receive_and_barcode || $scope.receive_and_bind) { // supplying a barcode (unit) to new items
+            var new_unit_barcode = '';
+            var new_unit_call_number = '';
+            angular.forEach(list, function (item) {
+                if (new_unit_barcode) {
+                    barcodes[item.id()] = new_unit_barcode;
+                    call_numbers[item.id()] = new_unit_call_number;
+                    continue;
+                }
+
+                // TODO: I18N
+                var prompt_text = 'for '+
+                    item.issuance().label()+
+                    ' from Distribution: '+obj.sdist_map[item.stream().distribution()].label()+
+                    '/'+item.stream().id()+':';
+
+                if ($scope.receive_and_bind) {
+                    prompt_text = 'for the new unit:';
+                }
+
+                prompt_promises.push(
+                    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;
+                            }
+                        }}
+                    ).result
+                );
+
+                // now call numbers
+                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();
+
+/* XXX default to previous, as in xul?
+ *
+ *                   } else {
+ *                       // for now, let's default to the last created call number if there is one
+ *                       var acn_list = obj.network.request(
+ *                               'open-ils.pcrud',
+ *                               'open-ils.pcrud.search.acn',
+ *                               [ ses(),
+ *                                {   "record" : obj.docid,
+ *                                    "owning_lib" : obj.sdist_map[item.stream().distribution()].holding_lib().id(),
+ *                                    "deleted" : 'f'
+ *                                }, {"order_by" : {"acn" : "create_date DESC"}, "limit" : "1" } ]
+ *                       );
+ *
+ *                       if (acn_list) {
+ *                           default_cn = acn_list.label();
+ *                       }
+ */
+
+                    }
+
+                    prompt_promises.push(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;
+                            }
+                        }}
+                    ).result);
+                } 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()];
+                }
+
+                if ($scope.receive_and_bind) {
+                    new_unit_barcode = barcode;
+                    new_unit_call_number = call_number;
+                }
+            });
+        } else {
+            prompt_promises.push($q.when());
+        }
+
+        return $q.all(prompt_promises).finally(function () {
+            return egCore.net.request(
+                'open-ils.serial', method,
+                egCore.auth.token(), list, barcodes, call_numbers, donor_unit_ids
+            ).then(
+                function(resp) {
+                    var evt = egCore.evt.parse(resp);
+                    if (evt) {
                         ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                     } else {
                         ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
@@ -225,7 +413,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
             ).then(
                 function(resp) {
                     var evt = egCore.evt.parse(resp);
-                    if (evt) { // any way to just throw or return this to the error handler?
+                    if (evt) {
                         ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                     } else {
                         ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
@@ -249,3 +437,4 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
 
     }
 })
+