From 63ff8e46f950ba30f2866e8a4836336b1b0c9c6f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 23 May 2026 05:37:30 +0000 Subject: [PATCH] Offload build complete task --- src/backend/InvenTree/build/models.py | 55 ++---------------------- src/backend/InvenTree/build/tasks.py | 61 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 51 deletions(-) diff --git a/src/backend/InvenTree/build/models.py b/src/backend/InvenTree/build/models.py index 0ebe93fbab..bf410e3bd9 100644 --- a/src/backend/InvenTree/build/models.py +++ b/src/backend/InvenTree/build/models.py @@ -37,7 +37,6 @@ from build.validators import ( validate_build_order_reference, ) from common.models import ProjectCode -from common.notifications import trigger_notification from common.settings import ( get_global_setting, prevent_build_output_complete_on_incompleted_tests, @@ -702,64 +701,18 @@ class Build( _('Cannot complete build order with incomplete outputs') ) - if trim_allocated_stock: - self.trim_allocated_stock() - self.completion_date = InvenTree.helpers.current_date() self.completed_by = user self.status = BuildStatus.COMPLETE.value self.save() - # Offload task to complete build allocations - if not InvenTree.tasks.offload_task( - build.tasks.complete_build_allocations, + # Offload background task to complete build allocations + InvenTree.tasks.offload_task( + build.tasks.complete_build, self.pk, user.pk if user else None, + trim_allocated_stock=trim_allocated_stock, group='build', - ): - raise ValidationError( - _('Failed to offload task to complete build allocations') - ) - - # Register an event - trigger_event(BuildEvents.COMPLETED, id=self.pk) - - # Notify users that this build has been completed - targets = [self.issued_by, self.responsible] - - # Also inform anyone subscribed to the assembly part - targets.extend(self.part.get_subscribers()) - - # Notify those users interested in the parent build - if self.parent: - targets.append(self.parent.issued_by) - targets.append(self.parent.responsible) - - # Notify users if this build points to a sales order - if self.sales_order: - targets.append(self.sales_order.created_by) - targets.append(self.sales_order.responsible) - - build = self - name = _(f'Build order {build} has been completed') - - context = { - 'build': build, - 'name': name, - 'slug': 'build.completed', - 'message': _('A build order has been completed'), - 'link': InvenTree.helpers_model.construct_absolute_url( - self.get_absolute_url() - ), - 'template': {'html': 'email/build_order_completed.html', 'subject': name}, - } - - trigger_notification( - build, - 'build.completed', - targets=targets, - context=context, - target_exclude=[user], ) @transaction.atomic diff --git a/src/backend/InvenTree/build/tasks.py b/src/backend/InvenTree/build/tasks.py index 5bdb167910..162f2fb266 100644 --- a/src/backend/InvenTree/build/tasks.py +++ b/src/backend/InvenTree/build/tasks.py @@ -247,6 +247,67 @@ def cancel_build( trigger_event(BuildEvents.CANCELLED, id=build.pk) +@tracer.start_as_current_span('complete_build') +def complete_build(build_id: int, user_id: int, trim_allocated_stock: bool = False): + """Tasks to run after a BuildOrder is completed. + + Arguments: + build_id: The ID of the BuildOrder which has been completed + user_id: The ID of the user who completed the BuildOrder + trim_allocated_stock: If True, trim any allocated stock which was not consumed + """ + from build.models import Build + + build = Build.objects.get(pk=build_id) + user = User.objects.filter(pk=user_id).first() if user_id else None + + if trim_allocated_stock: + build.trim_allocated_stock() + + # Complete any remaining allocations for this build order + complete_build_allocations(build_id, user_id) + + # Register an event + trigger_event(BuildEvents.COMPLETED, id=build.pk) + + # Notify users that this build has been completed + targets = [build.issued_by, build.responsible] + + # Also inform anyone subscribed to the assembly part + targets.extend(build.part.get_subscribers()) + + # Notify those users interested in the parent build + if build.parent: + targets.append(build.parent.issued_by) + targets.append(build.parent.responsible) + + # Notify users if this build points to a sales order + if build.sales_order: + targets.append(build.sales_order.created_by) + targets.append(build.sales_order.responsible) + + name = _(f'Build order {build} has been completed') + + context = { + 'build': build, + 'name': name, + 'slug': 'build.completed', + 'message': _('A build order has been completed'), + 'link': InvenTree.helpers_model.construct_absolute_url( + build.get_absolute_url() + ), + 'template': {'html': 'email/build_order_completed.html', 'subject': name}, + } + + common.notifications.trigger_notification( + build, + 'build.completed', + targets=targets, + context=context, + target_exclude=[user], + ) + + @tracer.start_as_current_span('update_build_order_lines') def update_build_order_lines(bom_item_pk: int): """Update all BuildOrderLineItem objects which reference a particular BomItem.