diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py
index 4a6e7111e8..64be7c885f 100644
--- a/InvenTree/stock/api.py
+++ b/InvenTree/stock/api.py
@@ -143,7 +143,7 @@ class StockAdjust(APIView):
         elif 'items' in request.data:
             _items = request.data['items']
         else:
-            raise ValidationError({'items': 'Request must contain list of stock items'})
+            raise ValidationError({'items': _('Request must contain list of stock items')})
 
         # List of validated items
         self.items = []
@@ -151,13 +151,14 @@ class StockAdjust(APIView):
         for entry in _items:
 
             if not type(entry) == dict:
-                raise ValidationError({'error': 'Improperly formatted data'})
+                raise ValidationError({'error': _('Improperly formatted data')})
 
             try:
-                pk = entry.get('pk', None)
+                # Look for 'pk' value first, with 'id' as a backup
+                pk = entry.get('pk', entry.get('id', None))
                 item = StockItem.objects.get(pk=pk)
             except (ValueError, StockItem.DoesNotExist):
-                raise ValidationError({'pk': 'Each entry must contain a valid pk field'})
+                raise ValidationError({'pk': _('Each entry must contain a valid pk field')})
 
             if self.allow_missing_quantity and 'quantity' not in entry:
                 entry['quantity'] = item.quantity
@@ -165,10 +166,10 @@ 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 value"})
+                raise ValidationError({'quantity': _("Each entry must contain a valid quantity value")})
 
             if quantity < 0:
-                raise ValidationError({'quantity': 'Quantity field must not be less than zero'})
+                raise ValidationError({'quantity': _('Quantity field must not be less than zero')})
 
             self.items.append({
                 'item': item,
diff --git a/InvenTree/templates/js/forms.js b/InvenTree/templates/js/forms.js
index b7af665393..ffe3868746 100644
--- a/InvenTree/templates/js/forms.js
+++ b/InvenTree/templates/js/forms.js
@@ -441,7 +441,17 @@ function constructFormBody(fields, options) {
     modalEnable(modal, true);
     
     // Insert generated form content
-    $(modal).find('.modal-form-content').html(html);
+    $(modal).find('#form-content').html(html);
+
+    if (options.preFormContent) {
+        console.log('pre form content', options.preFormContent);
+        $(modal).find('#pre-form-content').html(options.preFormContent);
+    }
+
+    if (options.postFormContent) {
+        console.log('post form content', options.postFormContent);
+        $(modal).find('#post-form-content').html(options.postFormContent);
+    }
     
     // Clear any existing buttons from the modal
     $(modal).find('#modal-footer-buttons').html('');
diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js
index 2413d36089..42cbc74a68 100644
--- a/InvenTree/templates/js/stock.js
+++ b/InvenTree/templates/js/stock.js
@@ -20,6 +20,138 @@ function stockStatusCodes() {
 }
 
 
+/**
+ * Perform stock adjustments
+ */
+function adjustStock(items, options={}) {
+
+    var formTitle = 'Form Title Here';
+    var actionTitle = null;
+
+    switch (options.action) {
+        case 'move':
+            formTitle = '{% trans "Transfer Stock" %}';
+            actionTitle = '{% trans "Move" %}';
+            break;
+        case 'count':
+            formTitle = '{% trans "Count Stock" %}';
+            actionTitle = '{% trans "Count" %}';
+            break;
+        case 'take':
+            formTitle = '{% trans "Remove Stock" %}';
+            actionTitle = '{% trans "Take" %}';
+            break;
+        case 'add':
+            formTitle = '{% trans "Add Stock" %}';
+            actionTitle = '{% trans "Add" %}';
+            break;
+        case 'delete':
+            formTitle = '{% trans "Delete Stock" %}';
+            break;
+        default:
+            break;
+    }
+
+    // Generate modal HTML content
+    var html = `
+    
+    
+    
+        | {% trans "Part" %}+ | {% trans "Stock" %}+ | {% trans "Location" %}+ | ${actionTitle || ''}+ | 
+    
+    
+    `;
+
+    items.forEach(function(item) {
+
+        var pk = item.pk;
+
+        var image = item.part_detail.thumbnail || item.part_detail.image || blankImage();
+
+        var status = stockStatusDisplay(item.status, {
+            classes: 'float-right'
+        });
+
+        var quantity = item.quantity;
+
+        var location = locationDetail(item, false);
+
+        if (item.location_detail) {
+            location = item.location_detail.pathstring;
+        }
+
+        if (item.serial != null) {
+            quantity = `#${item.serial}`;
+        }
+
+        var actionInput = '';
+
+        if (actionTitle != null) {
+            actionInput = constructNumberInput(
+                item.pk,
+                {
+                    value: item.quantity,
+                    min_value: 0,
+                }
+            )
+        };
+
+        var buttons = ``;
+
+        buttons += makeIconButton(
+            'fa-trash-alt icon-red',
+            'button-stock-item-remove',
+            pk,
+            '{% trans "Remove stock item" %}',
+        );
+
+        buttons += `
`;
+
+        html += `
+        
+            | + ${item.part_detail.full_name} | ${quantity}${status}+ | ${location}+ | + +
+                    ${actionInput}
+                    ${buttons}
+                + | 
`;
+
+    });
+
+    html += `
`;
+
+    var modal = createNewModal({
+        title: formTitle,
+    });
+
+    constructFormBody({}, {
+        preFormContent: html,
+        confirm: true,
+        modal: modal,
+    });
+
+    // Attach callbacks for the action buttons
+    $(modal).find('.button-stock-item-remove').click(function() {
+        var pk = $(this).attr('pk');
+
+        $(modal).find(`#stock_item_${pk}`).remove();
+    });
+
+    attachToggle(modal);
+
+    $(modal + ' .select2-container').addClass('select-full-width');
+    $(modal + ' .select2-container').css('width', '100%');
+}
+
+
 function removeStockRow(e) {
     // Remove a selected row from a stock modal form
 
@@ -228,6 +360,58 @@ function loadStockTestResultsTable(table, options) {
 
 }
 
+
+function locationDetail(row, showLink=true) {
+    /* 
+     * Function to display a "location" of a StockItem.
+     * 
+     * Complicating factors: A StockItem may not actually *be* in a location!
+     * - Could be at a customer
+     * - Could be installed in another stock item
+     * - Could be assigned to a sales order
+     * - Could be currently in production!
+     *
+     * So, instead of being naive, we'll check!
+     */
+
+    // Display text
+    var text = '';
+
+    // URL (optional)
+    var url = '';
+
+    if (row.is_building && row.build) {
+        // StockItem is currently being built!
+        text = '{% trans "In production" %}';
+        url = `/build/${row.build}/`;
+    } else if (row.belongs_to) {
+        // StockItem is installed inside a different StockItem
+        text = `{% trans "Installed in Stock Item" %} ${row.belongs_to}`;
+        url = `/stock/item/${row.belongs_to}/installed/`;
+    } else if (row.customer) {
+        // StockItem has been assigned to a customer
+        text = '{% trans "Shipped to customer" %}';
+        url = `/company/${row.customer}/assigned-stock/`;
+    } else if (row.sales_order) {
+        // StockItem has been assigned to a sales order
+        text = '{% trans "Assigned to Sales Order" %}';
+        url = `/order/sales-order/${row.sales_order}/`;
+    } else if (row.location) {
+        text = row.location_detail.pathstring;
+        url = `/stock/location/${row.location}/`;
+    } else {
+        text = '{% trans "No stock location set" %}';
+        url = '';
+    }
+
+    if (showLink && url) {
+        return renderLink(text, url);
+    } else {
+        return text;
+    }
+}
+
+
 function loadStockTable(table, options) {
     /* Load data into a stock table with adjustable options.
      * Fetches data (via AJAX) and loads into a bootstrap table.
@@ -271,56 +455,6 @@ function loadStockTable(table, options) {
         filters[key] = params[key];
     }
 
-    function locationDetail(row) {
-        /* 
-         * Function to display a "location" of a StockItem.
-         * 
-         * Complicating factors: A StockItem may not actually *be* in a location!
-         * - Could be at a customer
-         * - Could be installed in another stock item
-         * - Could be assigned to a sales order
-         * - Could be currently in production!
-         *
-         * So, instead of being naive, we'll check!
-         */
-
-        // Display text
-        var text = '';
-
-        // URL (optional)
-        var url = '';
-
-        if (row.is_building && row.build) {
-            // StockItem is currently being built!
-            text = '{% trans "In production" %}';
-            url = `/build/${row.build}/`;
-        } else if (row.belongs_to) {
-            // StockItem is installed inside a different StockItem
-            text = `{% trans "Installed in Stock Item" %} ${row.belongs_to}`;
-            url = `/stock/item/${row.belongs_to}/installed/`;
-        } else if (row.customer) {
-            // StockItem has been assigned to a customer
-            text = '{% trans "Shipped to customer" %}';
-            url = `/company/${row.customer}/assigned-stock/`;
-        } else if (row.sales_order) {
-            // StockItem has been assigned to a sales order
-            text = '{% trans "Assigned to Sales Order" %}';
-            url = `/order/sales-order/${row.sales_order}/`;
-        } else if (row.location) {
-            text = row.location_detail.pathstring;
-            url = `/stock/location/${row.location}/`;
-        } else {
-            text = '{% trans "No stock location set" %}';
-            url = '';
-        }
-
-        if (url) {
-            return renderLink(text, url);
-        } else {
-            return text;
-        }
-    }
-
     var grouping = true;
 
     if ('grouping' in options) {
@@ -741,114 +875,14 @@ function loadStockTable(table, options) {
         ]
     );
 
+
     function stockAdjustment(action) {
         var items = $("#stock-table").bootstrapTable("getSelections");
 
-        var stock = [];
-
-        items.forEach(function(item) {
-            stock.push(item.pk);
+        adjustStock(items, {
+            action: action,
         });
 
-        var title = 'Form title';
-
-        switch (action) {
-            case 'move':
-                title = '{% trans "Transfer Stock" %}';
-                break;
-            case 'count':
-                title = '{% trans "Count Stock" %}';
-                break;
-            case 'take':
-                title = '{% trans "Remove Stock" %}';
-                break;
-            case 'add':
-                title = '{% trans "Add Stock" %}';
-                break;
-            case 'delete':
-                title = '{% trans "Delete Stock" %}';
-                break;
-            default:
-                break;
-        }
-
-        var modal = createNewModal({
-            title: title,
-        });
-
-        // Generate content for the modal
-
-        var html = `
-        
-        
-        
-            | {% trans "Part" %}- | {% trans "Stock" %}- | {% trans "Location" %}- | - | 
-        
-        
-        `;
-
-        items.forEach(function(item) {
-
-            var pk = item.pk;
-
-            var image = item.part_detail.thumbnail || item.part_detail.image || blankImage();
-
-            var status = stockStatusDisplay(item.status, {
-                classes: 'float-right'
-            });
-
-            var quantity = item.quantity;
-
-            if (item.serial != null) {
-                quantity = `#${item.serial}`;
-            }
-
-            var buttons = ``;
-
-            buttons += makeIconButton(
-                'fa-trash-alt icon-red',
-                'button-stock-item-remove',
-                pk,
-                '{% trans "Remove stock item" %}',
-            );
-
-            buttons += `
`;
-
-            html += `
-            
-                | - ${item.part_detail.full_name}${status} | ${quantity}- | ${item.location_detail.pathstring}- | ${buttons}- | 
`;
-
-        });
-
-        html += `
`;
-
-        $(modal).find('.modal-form-content').html(html);
-
-        // Attach callbacks for the action buttons
-        $(modal).find('.button-stock-item-remove').click(function() {
-            var pk = $(this).attr('pk');
-
-            $(modal).find(`#stock_item_${pk}`).remove();
-        });
-
-        // Add a "confirm" button
-        insertConfirmButton({
-            modal: modal,
-        });
-
-        attachToggle(modal);
-
-        $(modal + ' .select2-container').addClass('select-full-width');
-        $(modal + ' .select2-container').css('width', '100%');
-
         return;
 
         // Buttons for launching secondary modals