2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-05-28 11:59:23 +00:00

Refactor "build cancel"

- Offload expensive ops to background worker
This commit is contained in:
Oliver Walters
2026-05-23 05:32:35 +00:00
parent 7cefb3c6df
commit 9b3ff421ad
2 changed files with 50 additions and 31 deletions
+10 -31
View File
@@ -37,7 +37,7 @@ from build.validators import (
validate_build_order_reference, validate_build_order_reference,
) )
from common.models import ProjectCode from common.models import ProjectCode
from common.notifications import InvenTreeNotificationBodies, trigger_notification from common.notifications import trigger_notification
from common.settings import ( from common.settings import (
get_global_setting, get_global_setting,
prevent_build_output_complete_on_incompleted_tests, prevent_build_output_complete_on_incompleted_tests,
@@ -839,27 +839,6 @@ class Build(
remove_allocated_stock = kwargs.get('remove_allocated_stock', False) remove_allocated_stock = kwargs.get('remove_allocated_stock', False)
remove_incomplete_outputs = kwargs.get('remove_incomplete_outputs', False) remove_incomplete_outputs = kwargs.get('remove_incomplete_outputs', False)
if remove_allocated_stock:
# Offload task to remove allocated stock
if not InvenTree.tasks.offload_task(
build.tasks.complete_build_allocations,
self.pk,
user.pk if user else None,
group='build',
):
raise ValidationError(
_('Failed to offload task to complete build allocations')
)
else:
self.allocated_stock.all().delete()
# Remove incomplete outputs (if required)
if remove_incomplete_outputs:
outputs = self.build_outputs.filter(is_building=True)
outputs.delete()
# Date of 'completion' is the date the build was cancelled # Date of 'completion' is the date the build was cancelled
self.completion_date = InvenTree.helpers.current_date() self.completion_date = InvenTree.helpers.current_date()
self.completed_by = user self.completed_by = user
@@ -867,17 +846,17 @@ class Build(
self.status = BuildStatus.CANCELLED.value self.status = BuildStatus.CANCELLED.value
self.save() self.save()
# Notify users that the order has been canceled # Offload background task to take care of the expensive operations
InvenTree.helpers_model.notify_responsible( InvenTree.tasks.offload_task(
self, build.tasks.cancel_build(
Build, self.pk,
exclude=self.issued_by, user.pk if user else None,
content=InvenTreeNotificationBodies.OrderCanceled, remove_allocated_stock=remove_allocated_stock,
extra_users=self.part.get_subscribers(), remove_incomplete_outputs=remove_incomplete_outputs,
group='build',
)
) )
trigger_event(BuildEvents.CANCELLED, id=self.pk)
@transaction.atomic @transaction.atomic
def deallocate_stock(self, build_line=None, output=None): def deallocate_stock(self, build_line=None, output=None):
"""Deallocate stock from this Build. """Deallocate stock from this Build.
+40
View File
@@ -207,6 +207,46 @@ def complete_build_outputs(
) )
@tracer.start_as_current_span('cancel_build')
def cancel_build(
build_id: int,
user_id: int,
remove_allocated_stock: bool = False,
remove_incomplete_outputs: bool = False,
):
"""Tasks to run after a BuildOrder is cancelled.
Arguments:
build_id: The ID of the BuildOrder which has been cancelled
user_id: The ID of the user who cancelled the BuildOrder
remove_allocated_stock: If True, deallocate any allocated stock
remove_incomplete_outputs: If True, delete any incomplete build outputs
"""
from build.models import Build
build = Build.objects.get(pk=build_id)
if remove_allocated_stock:
complete_build_allocations(build_id, user_id)
else:
build.allocated_stock.all().delete()
if remove_incomplete_outputs:
build.build_outputs.filter(is_building=True).delete()
# Notify users that the order has been canceled
InvenTree.helpers_model.notify_responsible(
build,
Build,
exclude=build.issued_by,
content=common.notifications.InvenTreeNotificationBodies.OrderCanceled,
extra_users=build.part.get_subscribers(),
)
trigger_event(BuildEvents.CANCELLED, id=build.pk)
@tracer.start_as_current_span('update_build_order_lines') @tracer.start_as_current_span('update_build_order_lines')
def update_build_order_lines(bom_item_pk: int): def update_build_order_lines(bom_item_pk: int):
"""Update all BuildOrderLineItem objects which reference a particular BomItem. """Update all BuildOrderLineItem objects which reference a particular BomItem.