diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py
index 61beba3262..49a1bcf5dc 100644
--- a/InvenTree/build/models.py
+++ b/InvenTree/build/models.py
@@ -485,6 +485,9 @@ class Build(MPTTModel):
if self.completed < self.quantity:
return False
+ if not self.areUntrackedPartsFullyAllocated():
+ return False
+
# No issues!
return True
@@ -494,7 +497,7 @@ class Build(MPTTModel):
Mark this build as complete
"""
- if not self.can_complete:
+ if self.incomplete_count > 0:
return
self.completion_date = datetime.now().date()
@@ -502,6 +505,9 @@ class Build(MPTTModel):
self.status = BuildStatus.COMPLETE
self.save()
+ # Remove untracked allocated stock
+ self.subtractUntrackedStock(user)
+
# Ensure that there are no longer any BuildItem objects
# which point to thie Build Order
self.allocated_stock.all().delete()
@@ -775,6 +781,24 @@ class Build(MPTTModel):
build_item.save()
+ @transaction.atomic
+ def subtractUntrackedStock(self, user):
+ """
+ Called when the Build is marked as "complete",
+ this function removes the allocated untracked items from stock.
+ """
+
+ items = self.allocated_stock.filter(
+ stock_item__part__trackable=False
+ )
+
+ # Remove stock
+ for item in items:
+ item.complete_allocation(user)
+
+ # Delete allocation
+ items.all().delete()
+
@transaction.atomic
def completeBuildOutput(self, output, user, **kwargs):
"""
@@ -790,9 +814,6 @@ class Build(MPTTModel):
# List the allocated BuildItem objects for the given output
allocated_items = output.items_to_install.all()
- # Ensure that only "trackable" parts are installed in the particular build output
- allocated_items = allocated_items.filter(part__trackable=True)
-
for build_item in allocated_items:
# TODO: This is VERY SLOW as each deletion from the database takes ~1 second to complete
@@ -915,6 +936,13 @@ class Build(MPTTModel):
# All parts must be fully allocated!
return True
+ def areUntrackedPartsFullyAllocated(self):
+ """
+ Returns True if the un-tracked parts are fully allocated for this BuildOrder
+ """
+
+ return self.isFullyAllocated(None)
+
def allocatedParts(self, output):
"""
Return a list of parts which have been fully allocated against a particular output
diff --git a/InvenTree/build/templates/build/allocate.html b/InvenTree/build/templates/build/allocate.html
index a1e1ff2f8e..dee90a26a0 100644
--- a/InvenTree/build/templates/build/allocate.html
+++ b/InvenTree/build/templates/build/allocate.html
@@ -31,6 +31,15 @@
-->
+{% if build.areUntrackedPartsFullyAllocated %}
+
+ {% trans "Untracked stock has been fully allocated for this Build Order" %}
+
+{% else %}
+
+ {% trans "Untracked stock has not been fully allocated for this Build Order" %}
+