2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-05-28 03:49:20 +00:00

Offload order completion tasks

This commit is contained in:
Oliver Walters
2026-05-23 07:44:17 +00:00
parent 2155ed604c
commit 6066dabe43
2 changed files with 81 additions and 39 deletions
+23 -34
View File
@@ -849,25 +849,18 @@ class PurchaseOrder(TotalPriceMixin, Order):
Order must be currently PLACED.
"""
if self.status == PurchaseOrderStatus.PLACED:
if self.status != PurchaseOrderStatus.PLACED:
return
# Schedule the order completion task, which will perform the necessary stock movements and other related actions
InvenTree.tasks.offload_task(
order.tasks.complete_purchase_order, self.pk, group='purchase_order'
)
self.status = PurchaseOrderStatus.COMPLETE.value
self.complete_date = InvenTree.helpers.current_date()
self.save()
unique_parts = set()
# Schedule pricing update for any referenced parts
for line in self.lines.all().prefetch_related('part__part'):
# Ensure we only check 'unique' parts
if line.part and line.part.part:
unique_parts.add(line.part.part)
for part in unique_parts:
part.schedule_pricing_update(create=True, refresh=False)
trigger_event(PurchaseOrderEvents.COMPLETED, id=self.pk)
@transaction.atomic
def issue_order(self):
"""Equivalent to 'place_order'."""
@@ -1584,20 +1577,15 @@ class SalesOrder(TotalPriceMixin, Order):
if not self.can_complete(**kwargs):
return False
# Offload task to process the shipment lines
InvenTree.tasks.offload_task(
order.tasks.complete_sales_order, self.pk, group='sales_order'
)
bypass_shipped = InvenTree.helpers.str2bool(
get_global_setting('SALESORDER_SHIP_COMPLETE')
)
# Update line items
for line in self.lines.all():
# Mark any "virtual" parts as shipped at this point
if line.part and line.part.virtual and line.shipped != line.quantity:
line.shipped = line.quantity
line.save()
if line.part:
line.part.schedule_pricing_update(create=True)
if bypass_shipped or self.status == SalesOrderStatus.SHIPPED:
self.status = SalesOrderStatus.COMPLETE.value
else:
@@ -1608,9 +1596,6 @@ class SalesOrder(TotalPriceMixin, Order):
self.shipment_date = InvenTree.helpers.current_date()
self.save()
trigger_event(SalesOrderEvents.COMPLETED, id=self.pk)
return True
@property
@@ -3459,18 +3444,22 @@ class TransferOrder(Order):
if not self.can_complete(raise_error=True, **kwargs):
return False
if self.status == TransferOrderStatus.ISSUED:
for allocation in self.allocations():
# execute each transfer
allocation.complete_allocation(user)
if self.status != TransferOrderStatus.ISSUED:
return
# Offload task to perform the transfer of each allocated stock item
InvenTree.tasks.offload_task(
order.tasks.complete_transfer_order,
self.pk,
user.pk if user else None,
group='transfer_order',
)
self.status = TransferOrderStatus.COMPLETE.value
self.complete_date = InvenTree.helpers.current_date()
self.save()
trigger_event(TransferOrderEvents.COMPLETED, id=self.pk)
return True
@transaction.atomic
+54 -1
View File
@@ -15,7 +15,7 @@ import common.notifications
import InvenTree.helpers_model
import order.models
from InvenTree.tasks import ScheduledTask, scheduled_task
from order.events import PurchaseOrderEvents, SalesOrderEvents
from order.events import PurchaseOrderEvents, SalesOrderEvents, TransferOrderEvents
from order.status_codes import (
PurchaseOrderStatusGroups,
ReturnOrderStatusGroups,
@@ -273,3 +273,56 @@ def complete_sales_order_shipment(
# Trigger event signalling that the shipment has been completed
trigger_event(SalesOrderEvents.SHIPMENT_COMPLETE, id=shipment.pk)
@tracer.start_as_current_span('complete_purchase_order')
def complete_purchase_order(order_id: int):
"""Run completion tasks for a PurchaseOrder that has just been marked as complete."""
po = order.models.PurchaseOrder.objects.get(pk=order_id)
unique_parts = set()
# Schedule pricing update for any referenced parts
for line in po.lines.all().prefetch_related('part__part'):
# Ensure we only check 'unique' parts
if line.part and line.part.part:
unique_parts.add(line.part.part)
for part in unique_parts:
part.schedule_pricing_update(create=True, refresh=False)
trigger_event(PurchaseOrderEvents.COMPLETED, id=order_id)
# Trigger event signalling that the purchase order has been completed
trigger_event(PurchaseOrderEvents.COMPLETE, id=order_id)
@tracer.start_as_current_span('complete_sales_order')
def complete_sales_order(order_id: int):
"""Run completion tasks for a SalesOrder that has just been marked as complete."""
so = order.models.SalesOrder.objects.get(pk=order_id)
# Update line items
for line in so.lines.all():
# Mark any "virtual" parts as shipped at this point
if line.part and line.part.virtual and line.shipped != line.quantity:
line.shipped = line.quantity
line.save()
if line.part:
line.part.schedule_pricing_update(create=True)
trigger_event(SalesOrderEvents.COMPLETED, id=order_id)
@tracer.start_as_current_span('complete_transfer_order')
def complete_transfer_order(order_id: int, user_id: int):
"""Run completion tasks for a TransferOrder that has just been marked as complete."""
transfer_order = order.models.TransferOrder.objects.get(pk=order_id)
user = User.objects.filter(pk=user_id).first() if user_id else None
for allocation in transfer_order.allocations():
# execute each transfer
allocation.complete_allocation(user)
trigger_event(TransferOrderEvents.COMPLETED, id=order_id)