mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 15:15:42 +00:00 
			
		
		
		
	Further improvements to build allocation form
- Auto-allocation button ignores outputs which are complete - StockItem API allows filtering by BomItem - Quantity inputs are now auto-filled - Display progress bar in the modal form
This commit is contained in:
		@@ -10,11 +10,15 @@ import common.models
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
INVENTREE_SW_VERSION = "0.6.0 dev"
 | 
					INVENTREE_SW_VERSION = "0.6.0 dev"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INVENTREE_API_VERSION = 12
 | 
					INVENTREE_API_VERSION = 13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
 | 
					Increment this API version number whenever there is a significant change to the API that any clients need to know about
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					v13 -> 2021-10-05
 | 
				
			||||||
 | 
					    - Adds API endpoint to allocate stock items against a BuildOrder
 | 
				
			||||||
 | 
					    - Updates StockItem API with improved filtering against BomItem data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
v12 -> 2021-09-07
 | 
					v12 -> 2021-09-07
 | 
				
			||||||
    - Adds API endpoint to receive stock items against a PurchaseOrder
 | 
					    - Adds API endpoint to receive stock items against a PurchaseOrder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,8 +9,9 @@ import decimal
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
from django.core.exceptions import ValidationError
 | 
					from django.core.exceptions import ValidationError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.urls import reverse
 | 
					from django.urls import reverse
 | 
				
			||||||
@@ -1055,8 +1056,10 @@ class BuildItem(models.Model):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Attributes:
 | 
					    Attributes:
 | 
				
			||||||
        build: Link to a Build object
 | 
					        build: Link to a Build object
 | 
				
			||||||
 | 
					        bom_item: Link to a BomItem object (may or may not point to the same part as the build)
 | 
				
			||||||
        stock_item: Link to a StockItem object
 | 
					        stock_item: Link to a StockItem object
 | 
				
			||||||
        quantity: Number of units allocated
 | 
					        quantity: Number of units allocated
 | 
				
			||||||
 | 
					        install_into: Destination stock item (or None)
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -433,16 +433,32 @@ $("#btn-auto-allocate").on('click', function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    var bom_items = $("#allocation-table-untracked").bootstrapTable("getData");
 | 
					    var bom_items = $("#allocation-table-untracked").bootstrapTable("getData");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var incomplete_bom_items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bom_items.forEach(function(bom_item) {
 | 
				
			||||||
 | 
					        if (bom_item.required > bom_item.allocated) {
 | 
				
			||||||
 | 
					            incomplete_bom_items.push(bom_item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (incomplete_bom_items.length == 0) {
 | 
				
			||||||
 | 
					        showAlertDialog(
 | 
				
			||||||
 | 
					            '{% trans "Allocation Complete" %}',
 | 
				
			||||||
 | 
					            '{% trans "All untracked stock items have been allocated" %}',
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        allocateStockToBuild(
 | 
					        allocateStockToBuild(
 | 
				
			||||||
            {{ build.pk }},
 | 
					            {{ build.pk }},
 | 
				
			||||||
            {{ build.part.pk }},
 | 
					            {{ build.part.pk }},
 | 
				
			||||||
        bom_items,
 | 
					            incomplete_bom_items,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                success: function(data) {
 | 
					                success: function(data) {
 | 
				
			||||||
                    $('#allocation-table-untracked').bootstrapTable('refresh');
 | 
					                    $('#allocation-table-untracked').bootstrapTable('refresh');
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$('#btn-unallocate').on('click', function() {
 | 
					$('#btn-unallocate').on('click', function() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,18 +1,6 @@
 | 
				
			|||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
import logging
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from PIL import UnidentifiedImageError
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from django.apps import AppConfig
 | 
					from django.apps import AppConfig
 | 
				
			||||||
from django.db.utils import OperationalError, ProgrammingError
 | 
					 | 
				
			||||||
from django.conf import settings
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from InvenTree.ready import canAppAccessDatabase
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
logger = logging.getLogger("inventree")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CompanyConfig(AppConfig):
 | 
					class CompanyConfig(AppConfig):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,9 @@
 | 
				
			|||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db.utils import OperationalError, ProgrammingError
 | 
					from django.db.utils import OperationalError, ProgrammingError
 | 
				
			||||||
from django.apps import AppConfig
 | 
					from django.apps import AppConfig
 | 
				
			||||||
from django.conf import settings
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from PIL import UnidentifiedImageError
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from InvenTree.ready import canAppAccessDatabase
 | 
					from InvenTree.ready import canAppAccessDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,7 +36,7 @@ class PartConfig(AppConfig):
 | 
				
			|||||||
            items = BomItem.objects.filter(part__trackable=False, sub_part__trackable=True)
 | 
					            items = BomItem.objects.filter(part__trackable=False, sub_part__trackable=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for item in items:
 | 
					            for item in items:
 | 
				
			||||||
                print(f"Marking part '{item.part.name}' as trackable")
 | 
					                logger.info(f"Marking part '{item.part.name}' as trackable")
 | 
				
			||||||
                item.part.trackable = True
 | 
					                item.part.trackable = True
 | 
				
			||||||
                item.part.clean()
 | 
					                item.part.clean()
 | 
				
			||||||
                item.part.save()
 | 
					                item.part.save()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2329,6 +2329,23 @@ class BomItem(models.Model):
 | 
				
			|||||||
    def get_api_url():
 | 
					    def get_api_url():
 | 
				
			||||||
        return reverse('api-bom-list')
 | 
					        return reverse('api-bom-list')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_stock_filter(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Return a queryset filter for selecting StockItems which match this BomItem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        - If allow_variants is True, allow all part variants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Target part
 | 
				
			||||||
 | 
					        part = self.sub_part
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.allow_variants:
 | 
				
			||||||
 | 
					            variants = part.get_descendants(include_self=True)
 | 
				
			||||||
 | 
					            return Q(part__in=[v.pk for v in variants])
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return Q(part=part)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self, *args, **kwargs):
 | 
					    def save(self, *args, **kwargs):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.clean()
 | 
					        self.clean()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,11 +2,18 @@
 | 
				
			|||||||
JSON API for the Stock app
 | 
					JSON API for the Stock app
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from decimal import Decimal, InvalidOperation
 | 
				
			||||||
 | 
					from datetime import datetime, timedelta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.conf.urls import url, include
 | 
					from django.conf.urls import url, include
 | 
				
			||||||
from django.urls import reverse
 | 
					from django.urls import reverse
 | 
				
			||||||
from django.http import JsonResponse
 | 
					from django.http import JsonResponse
 | 
				
			||||||
from django.db.models import Q
 | 
					from django.db.models import Q
 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from rest_framework import status
 | 
					from rest_framework import status
 | 
				
			||||||
from rest_framework.serializers import ValidationError
 | 
					from rest_framework.serializers import ValidationError
 | 
				
			||||||
@@ -22,7 +29,7 @@ from .models import StockItemTracking
 | 
				
			|||||||
from .models import StockItemAttachment
 | 
					from .models import StockItemAttachment
 | 
				
			||||||
from .models import StockItemTestResult
 | 
					from .models import StockItemTestResult
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from part.models import Part, PartCategory
 | 
					from part.models import BomItem, Part, PartCategory
 | 
				
			||||||
from part.serializers import PartBriefSerializer
 | 
					from part.serializers import PartBriefSerializer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from company.models import Company, SupplierPart
 | 
					from company.models import Company, SupplierPart
 | 
				
			||||||
@@ -45,10 +52,6 @@ from InvenTree.helpers import str2bool, isNull
 | 
				
			|||||||
from InvenTree.api import AttachmentMixin
 | 
					from InvenTree.api import AttachmentMixin
 | 
				
			||||||
from InvenTree.filters import InvenTreeOrderingFilter
 | 
					from InvenTree.filters import InvenTreeOrderingFilter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from decimal import Decimal, InvalidOperation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from datetime import datetime, timedelta
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StockCategoryTree(TreeSerializer):
 | 
					class StockCategoryTree(TreeSerializer):
 | 
				
			||||||
    title = _('Stock')
 | 
					    title = _('Stock')
 | 
				
			||||||
@@ -670,14 +673,14 @@ class StockList(generics.ListCreateAPIView):
 | 
				
			|||||||
        return queryset
 | 
					        return queryset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def filter_queryset(self, queryset):
 | 
					    def filter_queryset(self, queryset):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Custom filtering for the StockItem queryset
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        params = self.request.query_params
 | 
					        params = self.request.query_params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        queryset = super().filter_queryset(queryset)
 | 
					        queryset = super().filter_queryset(queryset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Perform basic filtering:
 | 
					 | 
				
			||||||
        # Note: We do not let DRF filter here, it be slow AF
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        supplier_part = params.get('supplier_part', None)
 | 
					        supplier_part = params.get('supplier_part', None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if supplier_part:
 | 
					        if supplier_part:
 | 
				
			||||||
@@ -843,6 +846,18 @@ class StockList(generics.ListCreateAPIView):
 | 
				
			|||||||
            except (ValueError, PartCategory.DoesNotExist):
 | 
					            except (ValueError, PartCategory.DoesNotExist):
 | 
				
			||||||
                raise ValidationError({"category": "Invalid category id specified"})
 | 
					                raise ValidationError({"category": "Invalid category id specified"})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Does the client wish to filter by BomItem
 | 
				
			||||||
 | 
					        bom_item_id = params.get('bom_item', None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if bom_item_id is not None:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                bom_item = BomItem.objects.get(pk=bom_item_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                queryset = queryset.filter(bom_item.get_stock_filter())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            except (ValueError, BomItem.DoesNotExist):
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Filter by StockItem status
 | 
					        # Filter by StockItem status
 | 
				
			||||||
        status = params.get('status', None)
 | 
					        status = params.get('status', None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -345,18 +345,26 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
 | 
				
			|||||||
    function requiredQuantity(row) {
 | 
					    function requiredQuantity(row) {
 | 
				
			||||||
        // Return the requied quantity for a given row
 | 
					        // Return the requied quantity for a given row
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var quantity = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (output) {
 | 
					        if (output) {
 | 
				
			||||||
            // "Tracked" parts are calculated against individual build outputs
 | 
					            // "Tracked" parts are calculated against individual build outputs
 | 
				
			||||||
            return row.quantity * output.quantity;
 | 
					            quantity = row.quantity * output.quantity;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // "Untracked" parts are specified against the build itself
 | 
					            // "Untracked" parts are specified against the build itself
 | 
				
			||||||
            return row.quantity * buildInfo.quantity;
 | 
					            quantity = row.quantity * buildInfo.quantity;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Store the required quantity in the row data
 | 
				
			||||||
 | 
					        row.required = quantity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return quantity;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function sumAllocations(row) {
 | 
					    function sumAllocations(row) {
 | 
				
			||||||
        // Calculat total allocations for a given row
 | 
					        // Calculat total allocations for a given row
 | 
				
			||||||
        if (!row.allocations) {
 | 
					        if (!row.allocations) {
 | 
				
			||||||
 | 
					            row.allocated = 0;
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -366,6 +374,8 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
 | 
				
			|||||||
            quantity += item.quantity;
 | 
					            quantity += item.quantity;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        row.allocated = quantity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return quantity;
 | 
					        return quantity;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -394,7 +404,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
 | 
				
			|||||||
                ],
 | 
					                ],
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    success: function(data) {
 | 
					                    success: function(data) {
 | 
				
			||||||
                        // TODO: Reload table
 | 
					                        $(table).bootstrapTable('refresh');
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
@@ -854,6 +864,11 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var allocated_display = makeProgressBar(
 | 
				
			||||||
 | 
					            bom_item.allocated,
 | 
				
			||||||
 | 
					            bom_item.required,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var stock_input = constructField(
 | 
					        var stock_input = constructField(
 | 
				
			||||||
            `items_stock_item_${pk}`,
 | 
					            `items_stock_item_${pk}`,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@@ -872,11 +887,12 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
            <td id='part_${pk}'>
 | 
					            <td id='part_${pk}'>
 | 
				
			||||||
                ${thumb} ${sub_part.full_name}
 | 
					                ${thumb} ${sub_part.full_name}
 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td id='allocated_${pk}'>
 | 
				
			||||||
 | 
					                ${allocated_display}
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
            <td id='stock_item_${pk}'>
 | 
					            <td id='stock_item_${pk}'>
 | 
				
			||||||
                ${stock_input}
 | 
					                ${stock_input}
 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
            <td id='allocated_${pk}'>
 | 
					 | 
				
			||||||
            </td>
 | 
					 | 
				
			||||||
            <td id='quantity_${pk}'>
 | 
					            <td id='quantity_${pk}'>
 | 
				
			||||||
                ${quantity_input}
 | 
					                ${quantity_input}
 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
@@ -894,7 +910,15 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
    for (var idx = 0; idx < bom_items.length; idx++) {
 | 
					    for (var idx = 0; idx < bom_items.length; idx++) {
 | 
				
			||||||
        var bom_item = bom_items[idx];
 | 
					        var bom_item = bom_items[idx];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        table_entries += renderBomItemRow(bom_item);
 | 
					        var required = bom_item.required || 0;
 | 
				
			||||||
 | 
					        var allocated = bom_item.allocated || 0;
 | 
				
			||||||
 | 
					        var remaining = required - allocated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (remaining < 0) {
 | 
				
			||||||
 | 
					            remaining = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        table_entries += renderBomItemRow(bom_item, remaining);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bom_items.length == 0) {
 | 
					    if (bom_items.length == 0) {
 | 
				
			||||||
@@ -913,8 +937,8 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
        <thead>
 | 
					        <thead>
 | 
				
			||||||
            <tr>
 | 
					            <tr>
 | 
				
			||||||
                <th>{% trans "Part" %}</th>
 | 
					                <th>{% trans "Part" %}</th>
 | 
				
			||||||
                <th style='min-width: 250px;'>{% trans "Stock Item" %}</th>
 | 
					 | 
				
			||||||
                <th>{% trans "Allocated" %}</th>
 | 
					                <th>{% trans "Allocated" %}</th>
 | 
				
			||||||
 | 
					                <th style='min-width: 250px;'>{% trans "Stock Item" %}</th>
 | 
				
			||||||
                <th>{% trans "Quantity" %}</th>
 | 
					                <th>{% trans "Quantity" %}</th>
 | 
				
			||||||
                <th></th>
 | 
					                <th></th>
 | 
				
			||||||
            </tr>
 | 
					            </tr>
 | 
				
			||||||
@@ -942,7 +966,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
                        name: `items_stock_item_${bom_item.pk}`,
 | 
					                        name: `items_stock_item_${bom_item.pk}`,
 | 
				
			||||||
                        api_url: '{% url "api-stock-list" %}',
 | 
					                        api_url: '{% url "api-stock-list" %}',
 | 
				
			||||||
                        filters: {
 | 
					                        filters: {
 | 
				
			||||||
                            part: bom_item.sub_part,
 | 
					                            bom_item: bom_item.pk,
 | 
				
			||||||
                            in_stock: true,
 | 
					                            in_stock: true,
 | 
				
			||||||
                            part_detail: false,
 | 
					                            part_detail: false,
 | 
				
			||||||
                            location_detail: true,
 | 
					                            location_detail: true,
 | 
				
			||||||
@@ -968,7 +992,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
                $(options.modal).find(`#allocation_row_${pk}`).remove();
 | 
					                $(options.modal).find(`#allocation_row_${pk}`).remove();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        onSubmit: function(fields, options) {
 | 
					        onSubmit: function(fields, opts) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Extract elements from the form
 | 
					            // Extract elements from the form
 | 
				
			||||||
            var data = {
 | 
					            var data = {
 | 
				
			||||||
@@ -983,7 +1007,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
                    `items_quantity_${item.pk}`,
 | 
					                    `items_quantity_${item.pk}`,
 | 
				
			||||||
                    {},
 | 
					                    {},
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        modal: options.modal,
 | 
					                        modal: opts.modal,
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -991,7 +1015,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
                    `items_stock_item_${item.pk}`,
 | 
					                    `items_stock_item_${item.pk}`,
 | 
				
			||||||
                    {},
 | 
					                    {},
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        modal: options.modal,
 | 
					                        modal: opts.modal,
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1007,18 +1031,18 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Provide nested values
 | 
					            // Provide nested values
 | 
				
			||||||
            options.nested = {
 | 
					            opts.nested = {
 | 
				
			||||||
                "items": item_pk_values
 | 
					                "items": item_pk_values
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            inventreePut(
 | 
					            inventreePut(
 | 
				
			||||||
                options.url,
 | 
					                opts.url,
 | 
				
			||||||
                data,
 | 
					                data,
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    method: 'POST',
 | 
					                    method: 'POST',
 | 
				
			||||||
                    success: function(response) {
 | 
					                    success: function(response) {
 | 
				
			||||||
                        // Hide the modal
 | 
					                        // Hide the modal
 | 
				
			||||||
                        $(options.modal).modal('hide');
 | 
					                        $(opts.modal).modal('hide');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (options.success) {
 | 
					                        if (options.success) {
 | 
				
			||||||
                            options.success(response);
 | 
					                            options.success(response);
 | 
				
			||||||
@@ -1027,10 +1051,10 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
 | 
				
			|||||||
                    error: function(xhr) {
 | 
					                    error: function(xhr) {
 | 
				
			||||||
                        switch (xhr.status) {
 | 
					                        switch (xhr.status) {
 | 
				
			||||||
                            case 400:
 | 
					                            case 400:
 | 
				
			||||||
                                handleFormErrors(xhr.responseJSON, fields, options);
 | 
					                                handleFormErrors(xhr.responseJSON, fields, opts);
 | 
				
			||||||
                                break;
 | 
					                                break;
 | 
				
			||||||
                            default:
 | 
					                            default:
 | 
				
			||||||
                                $(options.modal).modal('hide');
 | 
					                                $(opts.modal).modal('hide');
 | 
				
			||||||
                                showApiError(xhr);
 | 
					                                showApiError(xhr);
 | 
				
			||||||
                                break;
 | 
					                                break;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user