diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index 34032d758b..c872e558a0 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -596,12 +596,15 @@ class SalesOrderShipmentSerializer(InvenTreeModelSerializer): allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True) + order_detail = SalesOrderSerializer(source='order', read_only=True, many=False) + class Meta: model = order.models.SalesOrderShipment fields = [ 'pk', 'order', + 'order_detail', 'allocations', 'shipment_date', 'checked_by', diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index b6c98fc49e..92cdea7452 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -1216,7 +1216,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { * * options: * - output: ID / PK of the associated build output (or null for untracked items) - * - source_location: ID / PK of the top-level StockLocation to take parts from (or null) + * - source_location: ID / PK of the top-level StockLocation to source stock from (or null) */ function allocateStockToBuild(build_id, part_id, bom_items, options={}) { @@ -1329,7 +1329,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) { var html = ``; - // Render a "take from" input + // Render a "source location" input html += constructField( 'take_from', { @@ -1387,6 +1387,13 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) { options, ); + // Add callback to "clear" button for take_from field + addClearCallback( + 'take_from', + take_from_field, + options, + ); + // Initialize stock item fields bom_items.forEach(function(bom_item) { initializeRelatedField( @@ -1446,14 +1453,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) { ); }); - // Add callback to "clear" button for take_from field - addClearCallback( - 'take_from', - take_from_field, - options, - ); - - // Add button callbacks + // Add remove-row button callbacks $(options.modal).find('.button-row-remove').click(function() { var pk = $(this).attr('pk'); diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js index db2c8e46cc..2818b00534 100644 --- a/InvenTree/templates/js/translated/forms.js +++ b/InvenTree/templates/js/translated/forms.js @@ -1576,6 +1576,9 @@ function renderModelData(name, model, data, parameters, options) { case 'salesorder': renderer = renderSalesOrder; break; + case 'salesordershipment': + renderer = renderSalesOrderShipment; + break; case 'manufacturerpart': renderer = renderManufacturerPart; break; diff --git a/InvenTree/templates/js/translated/model_renderers.js b/InvenTree/templates/js/translated/model_renderers.js index bf3628d656..b2495e207f 100644 --- a/InvenTree/templates/js/translated/model_renderers.js +++ b/InvenTree/templates/js/translated/model_renderers.js @@ -241,6 +241,23 @@ function renderSalesOrder(name, data, parameters, options) { } +// Renderer for "SalesOrderShipment" model +// eslint-disable-next-line no-unused-vars +function renderSalesOrderShipment(name, data, parameters, options) { + + var so_prefix = global_settings.SALESORDER_REFERENCE_PREFIX; + + var html = ` + ${so_prefix}${data.order_detail.reference} - {% trans "Shipment" %} ${data.reference} + + {% trans "Shipment ID" %}: ${data.pk} + + `; + + return html; +} + + // Renderer for "PartCategory" model // eslint-disable-next-line no-unused-vars function renderPartCategory(name, data, parameters, options) { diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index 6e69eb6a02..b02c757df4 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -19,6 +19,7 @@ */ /* exported + allocateStockToSalesOrder, createSalesOrder, editPurchaseOrderLineItem, exportOrder, @@ -1211,6 +1212,306 @@ function loadSalesOrderShipmentTable(table, options={}) { } +/** + * Allocate stock items against a SalesOrder + * + * arguments: + * - order_id: The ID / PK value for the SalesOrder + * - lines: A list of SalesOrderLineItem objects to be allocated + * + * options: + * - source_location: ID / PK of the top-level StockLocation to source stock from (or null) + */ +function allocateStockToSalesOrder(order_id, line_items, options={}) { + + function renderLineItemRow(line_item, quantity) { + // Function to render a single line_item row + + var pk = line_item.pk; + + var part = line_item.part_detail; + + var thumb = thumbnailImage(part.thumbnail || part.image); + + var delete_button = `