Repository: saleor/saleor

Issue:
Refactor CancelOrderForm to not call CancelGroupForm
See: https://github.com/mirumee/saleor/blob/108b545ecebb90ffb44f9106cee8540ba92f6478/saleor/dashboard/order/forms.py#L267-L270

The actual cancellation code can be a function. It makes little sense for one form to instantiate another in order to call a single method.


Discussion:

Resolving patch:
diff --git a/saleor/dashboard/order/forms.py b/saleor/dashboard/order/forms.py
--- a/saleor/dashboard/order/forms.py
+++ b/saleor/dashboard/order/forms.py
@@ -13,6 +13,7 @@
 from ...discount.models import Voucher
 from ...order import Status
 from ...order.models import DeliveryGroup, Order, OrderedItem, OrderNote
+from ...order.utils import cancel_order, cancel_delivery_group
 from ...product.models import ProductVariant, Stock
 
 
@@ -236,17 +237,7 @@ def __init__(self, *args, **kwargs):
         super(CancelGroupForm, self).__init__(*args, **kwargs)
 
     def cancel_group(self):
-        for line in self.delivery_group:
-            if line.stock:
-                Stock.objects.deallocate_stock(line.stock, line.quantity)
-        self.delivery_group.status = Status.CANCELLED
-        self.delivery_group.save()
-        other_groups = self.delivery_group.order.groups.all()
-        statuses = set(other_groups.values_list('status', flat=True))
-        if statuses == {Status.CANCELLED}:
-            # Cancel whole order
-            self.delivery_group.order.status = Status.CANCELLED
-            self.delivery_group.order.save(update_fields=['status'])
+        cancel_delivery_group(self.delivery_group)
 
 
 class CancelOrderForm(forms.Form):
@@ -265,9 +256,7 @@ def clean(self):
         return data
 
     def cancel_order(self):
-        for group in self.order.groups.all():
-            group_form = CancelGroupForm(delivery_group=group)
-            group_form.cancel_group()
+        cancel_order(self.order)
 
 
 class RemoveVoucherForm(forms.Form):
diff --git a/saleor/order/utils.py b/saleor/order/utils.py
--- a/saleor/order/utils.py
+++ b/saleor/order/utils.py
@@ -1,15 +1,15 @@
 import logging
 from functools import wraps
 
-from payments.signals import status_changed
 from django.dispatch import receiver
 from django.shortcuts import get_object_or_404, redirect
+from payments.signals import status_changed
 
-from .models import Order
+from . import Status
 from ..core import analytics
 from ..product.models import Stock
 from ..userprofile.utils import store_user_address
-
+from .models import Order
 
 logger = logging.getLogger(__name__)
 
@@ -67,3 +67,24 @@ def add_items_to_delivery_group(delivery_group, partition, discounts=None):
             # allocate quantity to avoid overselling
             Stock.objects.allocate_stock(stock, quantity)
 
+
+def cancel_delivery_group(group, cancel_order=True):
+    for line in group:
+        if line.stock:
+            Stock.objects.deallocate_stock(line.stock, line.quantity)
+    group.status = Status.CANCELLED
+    group.save()
+    if cancel_order:
+        other_groups = group.order.groups.all()
+        statuses = set(other_groups.values_list('status', flat=True))
+        if statuses == {Status.CANCELLED}:
+            # Cancel whole order
+            group.order.status = Status.CANCELLED
+            group.order.save(update_fields=['status'])
+
+
+def cancel_order(order):
+    for group in order.groups.all():
+        cancel_delivery_group(group, cancel_order=False)
+    order.status = Status.CANCELLED
+    order.save()


Test patch: