diff --git a/InvenTree/InvenTree/static/script/inventree/modals.js b/InvenTree/InvenTree/static/script/inventree/modals.js
index 158cf67a77..5b76203927 100644
--- a/InvenTree/InvenTree/static/script/inventree/modals.js
+++ b/InvenTree/InvenTree/static/script/inventree/modals.js
@@ -166,14 +166,28 @@ function modalSetContent(modal, content='') {
}
+function modalSetSubmitText(modal, text) {
+ if (text) {
+ $(modal).find('#modal-form-submit').html(text);
+ }
+}
+
+
+function modalSetCloseText(modal, text) {
+ if (text) {
+ $(modal).find('#modal-form-close').html(text);
+ }
+}
+
+
function modalSetButtonText(modal, submit_text, close_text) {
/* Set the button text for a modal form
*
* submit_text - text for the form submit button
* close_text - text for the form dismiss button
*/
- $(modal).find("#modal-form-submit").html(submit_text);
- $(modal).find("#modal-form-close").html(close_text);
+ modalSetSubmitText(modal, submit_text);
+ modalSetCloseText(modal, close_text);
}
diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html
index 8b5e1d6e28..20032e557c 100644
--- a/InvenTree/stock/templates/stock/location.html
+++ b/InvenTree/stock/templates/stock/location.html
@@ -120,6 +120,12 @@
inventreeDel('show-part-locs');
});
+ {% if location %}
+ $("#barcode-check-in").click(function() {
+ barcodeCheckIn({{ location.id }});
+ });
+ {% endif %}
+
$("#stock-export").click(function() {
launchModalForm("{% url 'stock-export-options' %}", {
submit_text: "Export",
diff --git a/InvenTree/templates/js/barcode.html b/InvenTree/templates/js/barcode.html
index ced4ebbf7e..7f4273d7eb 100644
--- a/InvenTree/templates/js/barcode.html
+++ b/InvenTree/templates/js/barcode.html
@@ -1,25 +1,5 @@
{% load i18n %}
-/*
- * Pass barcode data to the server.
- */
-function scanBarcode(barcode, options={}) {
-
- inventreePut(
- '/api/barcode/',
- {
- 'barcode': barcode,
- },
- {
- method: 'POST',
- success: function(response, status) {
- console.log(response);
- },
- }
- );
-}
-
-
function makeBarcodeInput(placeholderText='') {
/*
* Generate HTML for a barcode input
@@ -28,8 +8,6 @@ function makeBarcodeInput(placeholderText='') {
placeholderText = placeholderText || '{% trans "Scan barcode data here using wedge scanner" %}';
var html = `
-
`;
@@ -60,6 +37,12 @@ function showBarcodeError(modal, message, style='danger') {
$(modal + ' #barcode-error-message').html(html);
}
+
+function showInvalidResponseError(modal, response, status) {
+ showBarcodeMessage(modal, `{% trans "Invalid server response" %}
{% trans "Status" %}: '${status}'`);
+}
+
+
function clearBarcodeError(modal, message) {
$(modal + ' #barcode-error-message').html('');
@@ -73,6 +56,8 @@ function enableBarcodeInput(modal, enabled=true) {
barcode.prop('disabled', !enabled);
modalEnable(modal, enabled);
+
+ barcode.focus();
}
function getBarcodeData(modal) {
@@ -86,7 +71,7 @@ function getBarcodeData(modal) {
el.val('');
el.focus();
- return barcode;
+ return barcode.trim();
}
@@ -97,54 +82,87 @@ function barcodeDialog(title, options={}) {
var modal = '#modal-form';
+ function sendBarcode() {
+ var barcode = getBarcodeData(modal);
+
+ if (barcode && barcode.length > 0) {
+
+ if (options.onScan) {
+ options.onScan(barcode);
+ }
+ }
+ }
+
$(modal).on('shown.bs.modal', function() {
$(modal + ' .modal-form-content').scrollTop(0);
+ var barcode = $(modal + ' #barcode');
+
+ // Handle 'enter' key on barcode
+ barcode.keyup(function(event) {
+ event.preventDefault();
+
+ if (event.which == 10 || event.which == 13) {
+ sendBarcode();
+ }
+ });
+
// Ensure the barcode field has focus
- $(modal + ' #barcode').focus();
+ barcode.focus();
var form = $(modal).find('.js-modal-form');
// Override form submission
form.submit(function() {
-
- var barcode = getBarcodeData(modal);
-
- if (options.submit) {
- options.submit(barcode);
- }
-
return false;
});
+ // Callback for when the "submit" button is pressed on the modal
modalSubmit(modal, function() {
-
- var barcode = getBarcodeData(modal);
-
- if (options.submit) {
- options.submit(barcode);
+ if (options.onSubmit) {
+ options.onSubmit();
}
});
+ if (options.onShow) {
+ options.onShow();
+ }
+
});
modalSetTitle(modal, title);
- modalShowSubmitButton(modal, true);
+
+ if (options.onSubmit) {
+ modalShowSubmitButton(modal, true);
+ } else {
+ modalShowSubmitButton(modal, false);
+ }
var content = '';
- if (options.headerContent) {
- content += options.headerContent;
- }
-
content += `
{% trans "Scan barcode data below" %}
`;
+
+ content += `
`;
+ content += `
`;
+
+ // Optional content after barcode input
+ content += `';
+
modalSetContent(modal, content);
$(modal).modal({
@@ -152,6 +170,10 @@ function barcodeDialog(title, options={}) {
keyboard: false,
});
+ if (options.preShow) {
+ options.preShow();
+ }
+
$(modal).modal('show');
}
@@ -167,7 +189,7 @@ function barcodeScanDialog() {
barcodeDialog(
"Scan Barcode",
{
- submit: function(barcode) {
+ onScan: function(barcode) {
enableBarcodeInput(modal, false);
inventreePut(
'/api/barcode/',
@@ -190,12 +212,12 @@ function barcodeScanDialog() {
}
} else if ('error' in response) {
- showBarcodeError(modal, response.error, 'warning');
+ showBarcodeMessage(modal, response.error, 'warning');
} else {
- showBarcodeError(modal, "{% trans 'Unknown response from server' %}", 'warning');
+ showBarcodeMessage(modal, "{% trans 'Unknown response from server' %}", 'warning');
}
} else {
- showBarcodeError(modal, `{% trans "Invalid server response" %}.
Status code: '${status}'`);
+ showInvalidResponseError(modal, response, status);
}
},
},
@@ -214,9 +236,9 @@ function linkBarcodeDialog(stockitem, options={}) {
var modal = '#modal-form';
barcodeDialog(
- "Link Barcode",
+ "{% trans 'Link Barcode to Stock Item' %}",
{
- submit: function(barcode) {
+ onScan: function(barcode) {
enableBarcodeInput(modal, false);
inventreePut(
'/api/barcode/link/',
@@ -228,8 +250,6 @@ function linkBarcodeDialog(stockitem, options={}) {
method: 'POST',
success: function(response, status) {
- console.log(response);
-
enableBarcodeInput(modal, true);
if (status == 'success') {
@@ -238,13 +258,13 @@ function linkBarcodeDialog(stockitem, options={}) {
$(modal).modal('hide');
location.reload();
} else if ('error' in response) {
- showBarcodeError(modal, response.error, 'warning');
+ showBarcodeMessage(modal, response.error, 'warning');
} else {
- showBarcodeError(modal, "{% trans 'Unknown response from server' %}", warning);
+ showBarcodeMessage(modal, "{% trans 'Unknown response from server' %}", warning);
}
} else {
- showBarcodeError(modal, `{% trans "Invalid server response" %}.
Status code: '${status}'`);
+ showInvalidResponseError(modal, response, status);
}
},
},
@@ -287,3 +307,202 @@ function unlinkBarcode(stockitem) {
}
);
}
+
+
+/*
+ * Display dialog to check multiple stock items in to a stock location.
+ */
+function barcodeCheckIn(location_id, options={}) {
+
+ var modal = '#modal-form';
+
+ // List of items we are going to checkin
+ var items = [];
+
+
+ function reloadTable() {
+
+ modalEnable(modal, false);
+
+ // Remove click listeners
+ $(modal + ' .button-item-remove').off('click');
+
+ var table = $(modal + ' #items-table-div');
+
+ var html = `
+
+
+
+ {% trans "Part" %} |
+ {% trans "Location" %} |
+ {% trans "Quantity" %} |
+ |
+
+
+ `;
+
+ items.forEach(function(item) {
+ html += `
+
+ ${imageHoverIcon(item.part_detail.thumbnail)} ${item.part_detail.name} |
+ ${item.location_detail.name} |
+ ${item.quantity} |
+ ${makeIconButton('fa-times-circle icon-red', 'button-item-remove', item.pk, '{% trans "Remove stock item" %}')} |
+
`;
+ });
+
+ html += `
+
+
`;
+
+ table.html(html);
+
+ modalEnable(modal, items.length > 0);
+
+ $(modal + ' #barcode').focus();
+
+
+ $(modal + ' .button-item-remove').on('click', function() {
+ var pk = $(this).attr('pk');
+
+ for (var ii = 0; ii < items.length; ii++) {
+ if (pk.toString() == items[ii].pk.toString()) {
+ //items.splice(ii, 1);
+ break;
+ }
+ }
+
+ reloadTable();
+
+ });
+ }
+
+ var table = `
`;
+
+ // Extra form fields
+ var extra = `
+
`;
+
+ barcodeDialog(
+ "{% trans "Check Stock Items into Location" %}",
+ {
+ headerContent: table,
+ preShow: function() {
+ modalSetSubmitText(modal, '{% trans "Check In" %}');
+ modalEnable(modal, false);
+ reloadTable();
+ },
+ onShow: function() {
+ },
+ extraFields: extra,
+ onSubmit: function() {
+
+
+ // Called when the 'check-in' button is pressed
+
+ var data = {location: location_id};
+
+ // Extract 'notes' field
+ data.notes = $(modal + ' #notes').val();
+
+ var entries = [];
+
+ items.forEach(function(item) {
+ entries.push({
+ pk: item.pk,
+ quantity: item.quantity,
+ });
+ });
+
+ data.items = entries;
+
+ inventreePut(
+ '{% url 'api-stock-transfer' %}',
+ data,
+ {
+ method: 'POST',
+ success: function(response, status) {
+ // Hide the modal
+ $(modal).modal('hide');
+ if (status == 'success' && 'success' in response) {
+
+ showAlertOrCache('alert-success', response.success, true);
+ location.reload();
+ } else {
+ showAlertOrCache('alert-success', 'Error transferring stock', false);
+ }
+ }
+ }
+ );
+ },
+ onScan: function(barcode) {
+ enableBarcodeInput(modal, false);
+ inventreePut(
+ '/api/barcode/',
+ {
+ barcode: barcode,
+ },
+ {
+ method: 'POST',
+ error: function() {
+ enableBarcodeInput(modal, true);
+ showBarcodeMessage(modal, '{% trans "Server error" %}');
+ },
+ success: function(response, status) {
+
+ enableBarcodeInput(modal, true);
+
+ if (status == 'success') {
+ if ('stockitem' in response) {
+ stockitem = response.stockitem;
+
+ var duplicate = false;
+
+ items.forEach(function(item) {
+ if (item.pk == stockitem.pk) {
+ duplicate = true;
+ }
+ });
+
+ if (duplicate) {
+ showBarcodeMessage(modal, "{% trans "Stock Item already scanned" %}", "warning");
+ } else {
+
+ if (stockitem.location == location_id) {
+ 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");
+
+ reloadTable();
+ }
+
+ } else {
+ // Barcode does not match a stock item
+ showBarcodeMessage(modal, "{% trans "Barcode does not match Stock Item" %}", "warning");
+ }
+ } else {
+ showInvalidResponseError(modal, response, status);
+ }
+ },
+ },
+ );
+ },
+ }
+ );
+}