diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py
index 43a8d4a529..cc7535bac9 100644
--- a/InvenTree/order/forms.py
+++ b/InvenTree/order/forms.py
@@ -50,6 +50,17 @@ class CancelPurchaseOrderForm(HelperForm):
fields = [
'confirm',
]
+
+
+class CancelSalesOrderForm(HelperForm):
+
+ confirm = forms.BooleanField(required=False, help_text=_('Cancel order'))
+
+ class Meta:
+ model = SalesOrder
+ fields = [
+ 'confirm',
+ ]
class ReceivePurchaseOrderForm(HelperForm):
diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py
index 136402f471..85eabfa3d0 100644
--- a/InvenTree/order/models.py
+++ b/InvenTree/order/models.py
@@ -289,6 +289,10 @@ class SalesOrder(Order):
related_name='+'
)
+ @property
+ def is_pending(self):
+ return self.status == SalesOrderStatus.PENDING
+
def is_fully_allocated(self):
""" Return True if all line items are fully allocated """
@@ -298,6 +302,42 @@ class SalesOrder(Order):
return True
+ @transaction.atomic
+ def ship_order(self, user):
+ """ Mark this order as 'shipped' """
+
+ if not self.status == SalesOrderStatus.PENDING:
+ return False
+
+ # Ensure the order status is marked as "Shipped"
+ self.status = SalesOrderStatus.SHIPPED
+ self.shipment_date = datetime.now().date()
+ self.shipped_by = user
+ self.save()
+
+ return True
+
+ @transaction.atomic
+ def cancel_order(self):
+ """
+ Cancel this order (only if it is "pending")
+
+ - Mark the order as 'cancelled'
+ - Delete any StockItems which have been allocated
+ """
+
+ if not self.status == SalesOrderStatus.PENDING:
+ return False
+
+ self.status = SalesOrderStatus.CANCELLED
+ self.save()
+
+ for line in self.lines.all():
+ for allocation in line.allocations.all():
+ allocation.delete()
+
+ return True
+
class PurchaseOrderAttachment(InvenTreeAttachment):
"""
diff --git a/InvenTree/order/templates/order/order_cancel.html b/InvenTree/order/templates/order/order_cancel.html
index 3c71028b06..91707ae737 100644
--- a/InvenTree/order/templates/order/order_cancel.html
+++ b/InvenTree/order/templates/order/order_cancel.html
@@ -1,7 +1,9 @@
{% extends "modal_form.html" %}
+{% load i18n %}
+
{% block pre_form_content %}
-Cancelling this order means that the order will no longer be editable.
+{% trans "Cancelling this order means that the order will no longer be editable." %}
{% endblock %}
\ No newline at end of file
diff --git a/InvenTree/order/templates/order/sales_order_base.html b/InvenTree/order/templates/order/sales_order_base.html
index 234a040a31..5cba99a0cb 100644
--- a/InvenTree/order/templates/order/sales_order_base.html
+++ b/InvenTree/order/templates/order/sales_order_base.html
@@ -27,6 +27,7 @@ src="{% static 'img/blank_image.png' %}"
/>
{% endblock %}
+
{% block page_data %}