Merge pull request 'Restock product inventory when an order is cancelled' (#9) from fix/restock-on-cancel into master
Reviewed-on: #9
This commit is contained in:
commit
aff0e77339
2 changed files with 38 additions and 0 deletions
|
|
@ -1,11 +1,14 @@
|
|||
from itertools import groupby
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import F
|
||||
from django.utils import timezone
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from utils.exceptions import Conflict
|
||||
|
||||
from apps.catalog.models import Product
|
||||
|
||||
from .models import Cart, Notification, Order, OrderGroup, OrderItem, OrderStatusLog
|
||||
|
||||
|
||||
|
|
@ -136,6 +139,16 @@ def checkout(user, address, delivery_type, scheduled_at, payment_method, notes):
|
|||
return order_group
|
||||
|
||||
|
||||
def _restock_order_items(order):
|
||||
"""Reverses the stock_quantity/sold_count decrement made at checkout (see checkout())."""
|
||||
for item in order.items.select_related('product').filter(product__isnull=False):
|
||||
Product.objects.filter(pk=item.product_id).update(
|
||||
stock_quantity=F('stock_quantity') + item.quantity,
|
||||
sold_count=F('sold_count') - item.quantity,
|
||||
)
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def _transition(order, to_status, *, changed_by=None, note='', **extra_fields):
|
||||
from_status = order.status
|
||||
order.status = to_status
|
||||
|
|
@ -147,6 +160,7 @@ def _transition(order, to_status, *, changed_by=None, note='', **extra_fields):
|
|||
OrderStatusLog.objects.create(order=order, from_status=from_status, to_status=to_status, changed_by=changed_by, note=note)
|
||||
|
||||
if to_status == Order.Status.CANCELLED:
|
||||
_restock_order_items(order)
|
||||
notify(
|
||||
recipient=order.store.owner,
|
||||
type=Notification.Type.ORDER_CANCELLED,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,30 @@ class StatusTransitionTests(OrdersTestCase):
|
|||
self.order.refresh_from_db()
|
||||
self.assertEqual(self.order.status, Order.Status.CANCELLED)
|
||||
|
||||
def test_cancelling_an_order_restocks_its_products(self):
|
||||
self.product1.refresh_from_db()
|
||||
stock_after_checkout = self.product1.stock_quantity
|
||||
sold_after_checkout = self.product1.sold_count
|
||||
self.assertEqual(stock_after_checkout, 49) # base.py seeds 50, checkout bought 1
|
||||
self.assertEqual(sold_after_checkout, 1)
|
||||
|
||||
self.client.force_authenticate(user=self.customer)
|
||||
response = self.client.post(f'/api/v1/orders/{self.order.uuid}/cancel/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.product1.refresh_from_db()
|
||||
self.assertEqual(self.product1.stock_quantity, stock_after_checkout + 1)
|
||||
self.assertEqual(self.product1.sold_count, sold_after_checkout - 1)
|
||||
|
||||
def test_cancelling_after_confirm_also_restocks(self):
|
||||
self._as_seller()
|
||||
self.client.post(f'/api/v1/seller/orders/{self.order.uuid}/confirm/')
|
||||
self.client.post(f'/api/v1/seller/orders/{self.order.uuid}/cancel/')
|
||||
|
||||
self.product1.refresh_from_db()
|
||||
self.assertEqual(self.product1.stock_quantity, 50)
|
||||
self.assertEqual(self.product1.sold_count, 0)
|
||||
|
||||
def test_cannot_cancel_after_handed_to_courier(self):
|
||||
self._as_seller()
|
||||
for action in ('confirm', 'mark-ready', 'mark-shipped'):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue