2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-29 20:16:44 +00:00

Merge pull request #2731 from SchrodingersGat/exclude-from-location

Add "exclude_location" to build order auto-allocation
This commit is contained in:
Oliver 2022-03-09 15:51:14 +11:00 committed by GitHub
commit 7af302f08e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 6 deletions

View File

@ -12,11 +12,15 @@ import common.models
INVENTREE_SW_VERSION = "0.7.0 dev" INVENTREE_SW_VERSION = "0.7.0 dev"
# InvenTree API version # InvenTree API version
INVENTREE_API_VERSION = 29 INVENTREE_API_VERSION = 30
""" """
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
v30 -> 2022-03-09
- Adds "exclude_location" field to BuildAutoAllocation API endpoint
- Allows BuildItem API endpoint to be filtered by BomItem relation
v29 -> 2022-03-08 v29 -> 2022-03-08
- Adds "scheduling" endpoint for predicted stock scheduling information - Adds "scheduling" endpoint for predicted stock scheduling information

View File

@ -461,6 +461,7 @@ class BuildItemList(generics.ListCreateAPIView):
filter_fields = [ filter_fields = [
'build', 'build',
'stock_item', 'stock_item',
'bom_item',
'install_into', 'install_into',
] ]

View File

@ -842,6 +842,7 @@ class Build(MPTTModel, ReferenceIndexingMixin):
""" """
location = kwargs.get('location', None) location = kwargs.get('location', None)
exclude_location = kwargs.get('exclude_location', None)
interchangeable = kwargs.get('interchangeable', False) interchangeable = kwargs.get('interchangeable', False)
substitutes = kwargs.get('substitutes', True) substitutes = kwargs.get('substitutes', True)
@ -875,6 +876,11 @@ class Build(MPTTModel, ReferenceIndexingMixin):
sublocations = location.get_descendants(include_self=True) sublocations = location.get_descendants(include_self=True)
available_stock = available_stock.filter(location__in=[loc for loc in sublocations]) available_stock = available_stock.filter(location__in=[loc for loc in sublocations])
if exclude_location:
# Exclude any stock items from the provided location
sublocations = exclude_location.get_descendants(include_self=True)
available_stock = available_stock.exclude(location__in=[loc for loc in sublocations])
""" """
Next, we sort the available stock items with the following priority: Next, we sort the available stock items with the following priority:
1. Direct part matches (+1) 1. Direct part matches (+1)

View File

@ -717,6 +717,7 @@ class BuildAutoAllocationSerializer(serializers.Serializer):
class Meta: class Meta:
fields = [ fields = [
'location', 'location',
'exclude_location',
'interchangeable', 'interchangeable',
'substitutes', 'substitutes',
] ]
@ -730,6 +731,15 @@ class BuildAutoAllocationSerializer(serializers.Serializer):
help_text=_('Stock location where parts are to be sourced (leave blank to take from any location)'), help_text=_('Stock location where parts are to be sourced (leave blank to take from any location)'),
) )
exclude_location = serializers.PrimaryKeyRelatedField(
queryset=StockLocation.objects.all(),
many=False,
allow_null=True,
required=False,
label=_('Exclude Location'),
help_text=_('Exclude stock items from this selected location'),
)
interchangeable = serializers.BooleanField( interchangeable = serializers.BooleanField(
default=False, default=False,
label=_('Interchangeable Stock'), label=_('Interchangeable Stock'),
@ -750,6 +760,7 @@ class BuildAutoAllocationSerializer(serializers.Serializer):
build.auto_allocate_stock( build.auto_allocate_stock(
location=data.get('location', None), location=data.get('location', None),
exclude_location=data.get('exclude_location', None),
interchangeable=data['interchangeable'], interchangeable=data['interchangeable'],
substitutes=data['substitutes'], substitutes=data['substitutes'],
) )

View File

@ -1219,6 +1219,18 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
$(table).bootstrapTable('updateByUniqueId', key, tableRow, true); $(table).bootstrapTable('updateByUniqueId', key, tableRow, true);
} }
// Update any rows which we did not receive allocation information for
var td = $(table).bootstrapTable('getData');
td.forEach(function(tableRow) {
if (tableRow.allocations == null) {
tableRow.allocations = [];
$(table).bootstrapTable('updateByUniqueId', tableRow.pk, tableRow, true);
}
});
// Update the progress bar for this build output // Update the progress bar for this build output
var build_progress = $(`#output-progress-${outputId}`); var build_progress = $(`#output-progress-${outputId}`);
@ -1419,15 +1431,17 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
formatter: function(value, row) { formatter: function(value, row) {
var allocated = 0; var allocated = 0;
if (row.allocations) { if (row.allocations != null) {
row.allocations.forEach(function(item) { row.allocations.forEach(function(item) {
allocated += item.quantity; allocated += item.quantity;
}); });
var required = requiredQuantity(row);
return makeProgressBar(allocated, required);
} else {
return `<em>{% trans "loading" %}...</em><span class='fas fa-spinner fa-spin float-right'></span>`;
} }
var required = requiredQuantity(row);
return makeProgressBar(allocated, required);
}, },
sorter: function(valA, valB, rowA, rowB) { sorter: function(valA, valB, rowA, rowB) {
// Custom sorting function for progress bars // Custom sorting function for progress bars
@ -1876,6 +1890,7 @@ function autoAllocateStockToBuild(build_id, bom_items=[], options={}) {
location: { location: {
value: options.location, value: options.location,
}, },
exclude_location: {},
interchangeable: { interchangeable: {
value: true, value: true,
}, },