From 552ca8e5c4358297157573faa6a9a63898048b93 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 20 Dec 2021 22:09:08 +1100 Subject: [PATCH] Adds javascript function to merge multiple stock items together --- InvenTree/templates/js/translated/stock.js | 219 +++++++++++++++++++-- InvenTree/templates/stock_table.html | 1 + 2 files changed, 207 insertions(+), 13 deletions(-) diff --git a/InvenTree/templates/js/translated/stock.js b/InvenTree/templates/js/translated/stock.js index 6360f396bb..23db95ccba 100644 --- a/InvenTree/templates/js/translated/stock.js +++ b/InvenTree/templates/js/translated/stock.js @@ -52,6 +52,7 @@ loadStockTestResultsTable, loadStockTrackingTable, loadTableFilters, + mergeStockItems, removeStockRow, serializeStockItem, stockItemFields, @@ -595,17 +596,17 @@ function assignStockToCustomer(items, options={}) { buttons += ''; html += ` - - ${thumbnail} ${part.full_name} - -
- ${quantity} -
-
- - ${location} - ${buttons} - + + ${thumbnail} ${part.full_name} + +
+ ${quantity} +
+
+ + ${location} + ${buttons} + `; } @@ -615,13 +616,13 @@ function assignStockToCustomer(items, options={}) { method: 'POST', preFormContent: html, fields: { - 'customer': { + customer: { value: options.customer, filters: { is_customer: true, }, }, - 'notes': {}, + notes: {}, }, confirm: true, confirmMessage: '{% trans "Confirm stock assignment" %}', @@ -694,6 +695,184 @@ function assignStockToCustomer(items, options={}) { } +/** + * Merge multiple stock items together + */ +function mergeStockItems(items, options={}) { + + // Generate HTML content for the form + var html = ` +
+
{% trans "Warning: Merge operation cannot be reversed" %}
+ {% trans "Some information will be lost when merging stock items" %}: + +
+ `; + + html += ` + + + + + + + + + + + `; + + // Keep track of how many "locations" there are + var locations = []; + + for (var idx = 0; idx < items.length; idx++) { + var item = items[idx]; + + var pk = item.pk; + + if (item.location && !locations.includes(item.location)) { + locations.push(item.location); + } + + var part = item.part_detail; + var location = locationDetail(item, false); + + var thumbnail = thumbnailImage(part.thumbnail || part.image); + + var quantity = ''; + + if (item.serial && item.quantity == 1) { + quantity = `{% trans "Serial" %}: ${item.serial}`; + } else { + quantity = `{% trans "Quantity" %}: ${item.quantity}`; + } + + quantity += stockStatusDisplay(item.status, {classes: 'float-right'}); + + var buttons = `
`; + + buttons += makeIconButton( + 'fa-times icon-red', + 'button-stock-item-remove', + pk, + '{% trans "Remove row" %}', + ); + + html += ` +
+ + + + + + `; + } + + html += '
{% trans "Part" %}{% trans "Stock Item" %}{% trans "Location" %}
${thumbnail} ${part.full_name} +
+ ${quantity} +
+
+
${location}${buttons}
'; + + var location = locations.length == 1 ? locations[0] : null; + + constructForm('{% url "api-stock-merge" %}', { + method: 'POST', + preFormContent: html, + fields: { + location: { + value: location, + icon: 'fa-sitemap', + }, + notes: {}, + allow_mismatched_suppliers: {}, + allow_mismatched_status: {}, + }, + confirm: true, + confirmMessage: '{% trans "Confirm stock item merge" %}', + title: '{% trans "Merge Stock Items" %}', + afterRender: function(fields, opts) { + // Add button callbacks to remove rows + $(opts.modal).find('.button-stock-item-remove').click(function() { + var pk = $(this).attr('pk'); + + $(opts.modal).find(`#stock_item_${pk}`).remove(); + }); + }, + onSubmit: function(fields, opts) { + + // Extract data elements from the form + var data = { + items: [], + }; + + var item_pk_values = []; + + items.forEach(function(item) { + var pk = item.pk; + + // Does the row still exist in the form? + var row = $(opts.modal).find(`#stock_item_${pk}`); + + if (row.exists()) { + item_pk_values.push(pk); + + data.items.push({ + item: pk, + }); + } + }); + + var extra_fields = [ + 'location', + 'notes', + 'allow_mismatched_suppliers', + 'allow_mismatched_status', + ]; + + extra_fields.forEach(function(field) { + data[field] = getFormFieldValue(field, fields[field], opts); + }); + + opts.nested = { + 'items': item_pk_values + }; + + // Submit the form data + inventreePut( + '{% url "api-stock-merge" %}', + data, + { + method: 'POST', + success: function(response) { + $(opts.modal).modal('hide'); + + if (options.success) { + options.success(response); + } + }, + error: function(xhr) { + switch (xhr.status) { + case 400: + handleFormErrors(xhr.responseJSON, fields, opts); + break; + default: + $(opts.modal).modal('hide'); + showApiError(xhr, opts.url); + break; + } + } + } + ) + } + }); +} + + /** * Perform stock adjustments */ @@ -1875,6 +2054,20 @@ function loadStockTable(table, options) { stockAdjustment('move'); }); + $('#multi-item-merge').click(function() { + var items = $(table).bootstrapTable('getSelections'); + + mergeStockItems(items, { + success: function(response) { + $(table).bootstrapTable('refresh'); + + showMessage('{% trans "Merged stock items" %}', { + style: 'success', + }); + } + }); + }); + $('#multi-item-assign').click(function() { var items = $(table).bootstrapTable('getSelections'); diff --git a/InvenTree/templates/stock_table.html b/InvenTree/templates/stock_table.html index 1f873d7c58..4a20938869 100644 --- a/InvenTree/templates/stock_table.html +++ b/InvenTree/templates/stock_table.html @@ -49,6 +49,7 @@
  • {% trans "Remove stock" %}
  • {% trans "Count stock" %}
  • {% trans "Move stock" %}
  • +
  • {% trans "Merge stock" %}
  • {% trans "Order stock" %}
  • {% trans "Assign to customer" %}
  • {% trans "Change stock status" %}