diff --git a/InvenTree/barcode/api.py b/InvenTree/barcode/api.py
index cecdf0b349..f8a2c37329 100644
--- a/InvenTree/barcode/api.py
+++ b/InvenTree/barcode/api.py
@@ -90,7 +90,7 @@ class BarcodeScan(APIView):
if loc is not None:
response['stocklocation'] = plugin.renderStockLocation(loc)
- response['url'] = reverse('location-detail', kwargs={'pk': loc.id})
+ response['url'] = reverse('stock-location-detail', kwargs={'pk': loc.id})
match_found = True
# Try to associate with a part
diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py
index c8211aaeca..3e874e91e5 100644
--- a/InvenTree/stock/api.py
+++ b/InvenTree/stock/api.py
@@ -160,7 +160,8 @@ class StockAdjust(APIView):
try:
quantity = Decimal(str(entry.get('quantity', None)))
except (ValueError, TypeError, InvalidOperation):
- raise ValidationError({'quantity': 'Each entry must contain a valid quantity field'})
+ # Default to the quantity of the item
+ quantity = item.quantity
if quantity < 0:
raise ValidationError({'quantity': 'Quantity field must not be less than zero'})
diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html
index e73ce8c7f9..d284a74e98 100644
--- a/InvenTree/stock/templates/stock/item_base.html
+++ b/InvenTree/stock/templates/stock/item_base.html
@@ -460,7 +460,7 @@ $("#barcode-unlink").click(function() {
});
$("#barcode-scan-into-location").click(function() {
- scanItemIntoLocation({{ item.id }});
+ scanItemsIntoLocation([{{ item.id }}]);
});
{% if item.in_stock %}
diff --git a/InvenTree/templates/js/barcode.js b/InvenTree/templates/js/barcode.js
index 9c9a8c1b08..0cc58be914 100644
--- a/InvenTree/templates/js/barcode.js
+++ b/InvenTree/templates/js/barcode.js
@@ -25,6 +25,25 @@ function makeBarcodeInput(placeholderText='') {
return html;
}
+function makeNotesField(options={}) {
+
+ var tooltip = options.tooltip || '{% trans "Enter optional notes for stock transfer" %}';
+
+ return `
+
`;
+}
+
function showBarcodeMessage(modal, message, style='danger') {
@@ -386,22 +405,10 @@ function barcodeCheckIn(location_id, options={}) {
var table = ``;
// Extra form fields
- var extra = `
- `;
+ var extra = makeNotesField();
barcodeDialog(
- "{% trans "Check Stock Items into Location" %}",
+ '{% trans "Check Stock Items into Location" %}',
{
headerContent: table,
preShow: function() {
@@ -414,7 +421,6 @@ function barcodeCheckIn(location_id, options={}) {
extraFields: extra,
onSubmit: function() {
-
// Called when the 'check-in' button is pressed
var data = {location: location_id};
@@ -434,7 +440,7 @@ function barcodeCheckIn(location_id, options={}) {
data.items = entries;
inventreePut(
- '{% url 'api-stock-transfer' %}',
+ "{% url 'api-stock-transfer' %}",
data,
{
method: 'POST',
@@ -446,7 +452,7 @@ function barcodeCheckIn(location_id, options={}) {
showAlertOrCache('alert-success', response.success, true);
location.reload();
} else {
- showAlertOrCache('alert-success', 'Error transferring stock', false);
+ showAlertOrCache('alert-success', '{% trans "Error transferring stock" %}', false);
}
}
}
@@ -482,25 +488,25 @@ function barcodeCheckIn(location_id, options={}) {
});
if (duplicate) {
- showBarcodeMessage(modal, "{% trans "Stock Item already scanned" %}", "warning");
+ showBarcodeMessage(modal, '{% trans "Stock Item already scanned" %}', "warning");
} else {
if (stockitem.location == location_id) {
- showBarcodeMessage(modal, "{% trans "Stock Item already in this location" %}");
+ showBarcodeMessage(modal, '{% trans "Stock Item already in this location" %}');
return;
}
// Add this stock item to the list
items.push(stockitem);
- showBarcodeMessage(modal, "{% trans "Added stock item" %}", "success");
+ showBarcodeMessage(modal, '{% trans "Added stock item" %}', "success");
reloadTable();
}
} else {
// Barcode does not match a stock item
- showBarcodeMessage(modal, "{% trans "Barcode does not match Stock Item" %}", "warning");
+ showBarcodeMessage(modal, '{% trans "Barcode does not match Stock Item" %}', "warning");
}
} else {
showInvalidResponseError(modal, response, status);
@@ -512,3 +518,135 @@ function barcodeCheckIn(location_id, options={}) {
}
);
}
+
+
+/*
+ * Display dialog to check a single stock item into a stock location
+ */
+function scanItemsIntoLocation(item_id_list, options={}) {
+
+ var modal = options.modal || '#modal-form';
+
+ var stock_location = null;
+
+ // Extra form fields
+ var extra = makeNotesField();
+
+ // Header contentfor
+ var header = `
+
+ `;
+
+ function updateLocationInfo(location) {
+ var div = $(modal + ' #header-div');
+
+ if (stock_location && stock_location.pk) {
+ div.html(`
+
+ {% trans "Location" %}
+ ${stock_location.name}
+ ${stock_location.description}
+
+ `);
+ } else {
+ div.html('');
+ }
+ }
+
+ barcodeDialog(
+ '{% trans "Check Into Location" %}',
+ {
+ headerContent: header,
+ extraFields: extra,
+ preShow: function() {
+ modalSetSubmitText(modal, '{% trans "Check In" %}');
+ modalEnable(modal, false);
+ },
+ onShow: function() {
+ },
+ onSubmit: function() {
+ // Called when the 'check-in' button is pressed
+ if (!stock_location) {
+ return;
+ }
+
+ var items = [];
+
+ item_id_list.forEach(function(pk) {
+ items.push({
+ pk: pk,
+ });
+ })
+
+ var data = {
+ location: stock_location.pk,
+ notes: $(modal + ' #notes').val(),
+ items: items,
+ };
+
+ // Send API request
+ inventreePut(
+ '{% url "api-stock-transfer" %}',
+ data,
+ {
+ method: 'POST',
+ success: function(response, status) {
+ // First hide the modal
+ $(modal).modal('hide');
+
+ if (status == 'success' && 'success' in response) {
+ showAlertOrCache('alert-success', response.success, true);
+ location.reload();
+ } else {
+ showAlertOrCache('alert-danger', '{% trans "Error transferring stock" %}', false);
+ }
+ }
+ }
+ )
+ },
+ onScan: function(barcode) {
+ updateLocationInfo(null);
+ enableBarcodeInput(modal, false);
+ inventreePut(
+ '/api/barcode/',
+ {
+ barcode: barcode,
+ },
+ {
+ method: 'POST',
+ error: function() {
+ enableBarcodeInput(modal, true);
+ showBarcodeMessage(modal, '{% trans "Server error" %}');
+ },
+ success: function(response, status) {
+ modalEnable(modal, false);
+ enableBarcodeInput(modal, true);
+
+ if (status == 'success') {
+ if ('stocklocation' in response) {
+ // Barcode corresponds to a StockLocation
+ stock_location = response.stocklocation;
+
+ updateLocationInfo(stock_location);
+ modalEnable(modal, true);
+
+ } else {
+ // Barcode does *NOT* correspond to a StockLocation
+ showBarcodeMessage(
+ modal,
+ '{% trans "Barcode does not match a valid location" %}',
+ "warning",
+ );
+ }
+ } else {
+ // Invalid response returned from server
+ showInvalidResponseError(modal, response, status);
+ }
+ }
+ }
+ )
+ }
+ }
+ )
+}
\ No newline at end of file